Merge branch 'omap-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6

* 'omap-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6:
  OMAP3: serial - fix bug introduced in
  mfd: twl: fix twl4030 rename for remaining driver, board files
  USB ehci: replace mach header with plat
  omap3: Allow EHCI to be built on OMAP3
diff --git a/.gitignore b/.gitignore
index 946c7ec..fb2190c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@
 *.lst
 *.symtypes
 *.order
+modules.builtin
 *.elf
 *.bin
 *.gz
@@ -45,14 +46,8 @@
 #
 # Generated include files
 #
-include/asm
-include/asm-*/asm-offsets.h
 include/config
-include/linux/autoconf.h
-include/linux/compile.h
 include/linux/version.h
-include/linux/utsrelease.h
-include/linux/bounds.h
 include/generated
 
 # stgit generated dirs
diff --git a/Documentation/ABI/testing/sysfs-memory-page-offline b/Documentation/ABI/testing/sysfs-memory-page-offline
new file mode 100644
index 0000000..e14703f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-memory-page-offline
@@ -0,0 +1,44 @@
+What:		/sys/devices/system/memory/soft_offline_page
+Date:		Sep 2009
+KernelVersion:	2.6.33
+Contact:	andi@firstfloor.org
+Description:
+		Soft-offline the memory page containing the physical address
+		written into this file. Input is a hex number specifying the
+		physical address of the page. The kernel will then attempt
+		to soft-offline it, by moving the contents elsewhere or
+		dropping it if possible. The kernel will then be placed
+		on the bad page list and never be reused.
+
+		The offlining is done in kernel specific granuality.
+		Normally it's the base page size of the kernel, but
+		this might change.
+
+		The page must be still accessible, not poisoned. The
+		kernel will never kill anything for this, but rather
+		fail the offline.  Return value is the size of the
+		number, or a error when the offlining failed.  Reading
+		the file is not allowed.
+
+What:		/sys/devices/system/memory/hard_offline_page
+Date:		Sep 2009
+KernelVersion:	2.6.33
+Contact:	andi@firstfloor.org
+Description:
+		Hard-offline the memory page containing the physical
+		address written into this file. Input is a hex number
+		specifying the physical address of the page. The
+		kernel will then attempt to hard-offline the page, by
+		trying to drop the page or killing any owner or
+		triggering IO errors if needed.  Note this may kill
+		any processes owning the page. The kernel will avoid
+		to access this page assuming it's poisoned by the
+		hardware.
+
+		The offlining is done in kernel specific granuality.
+		Normally it's the base page size of the kernel, but
+		this might change.
+
+		Return value is the size of the number, or a error when
+		the offlining failed.
+		Reading the file is not allowed.
diff --git a/Documentation/Changes b/Documentation/Changes
index 6d0f1ef..f08b313 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -49,6 +49,8 @@
 o  udev                   081                     # udevinfo -V
 o  grub                   0.93                    # grub --version
 o  mcelog		  0.6
+o  iptables               1.4.1                   # iptables -V
+
 
 Kernel compilation
 ==================
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index ab8300f..325cfd1 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -8,7 +8,7 @@
 
 DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
-	    procfs-guide.xml writing_usb_driver.xml networking.xml \
+	    writing_usb_driver.xml networking.xml \
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
@@ -32,10 +32,10 @@
 
 ###
 # The targets that may be used.
-PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs media
+PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
 
 BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
-xmldocs: $(BOOKS)
+xmldocs: $(BOOKS) xmldoclinks
 sgmldocs: xmldocs
 
 PS := $(patsubst %.xml, %.ps, $(BOOKS))
@@ -45,15 +45,24 @@
 pdfdocs: $(PDF)
 
 HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
-htmldocs: media $(HTML)
+htmldocs: $(HTML)
 	$(call build_main_index)
+	$(call build_images)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
 
-media:
-	mkdir -p $(srctree)/Documentation/DocBook/media/
-	cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(srctree)/Documentation/DocBook/media/
+build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
+	       cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
+
+xmldoclinks:
+ifneq ($(objtree),$(srctree))
+	for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \
+		rm -f $(objtree)/Documentation/DocBook/$$dep \
+		&& ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \
+		|| exit; \
+	done
+endif
 
 installmandocs: mandocs
 	mkdir -p /usr/local/man/man9/
@@ -65,7 +74,7 @@
 DOCPROC   = $(objtree)/scripts/basic/docproc
 
 XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
-#XMLTOFLAGS += --skip-validation
+XMLTOFLAGS += --skip-validation
 
 ###
 # DOCPROC is used for two purposes:
@@ -101,17 +110,6 @@
 # Changes in kernel-doc force a rebuild of all documentation
 $(BOOKS): $(KERNELDOC)
 
-###
-# procfs guide uses a .c file as example code.
-# This requires an explicit dependency
-C-procfs-example = procfs_example.xml
-C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
-$(obj)/procfs-guide.xml: $(C-procfs-example2)
-
-# List of programs to build
-##oops, this is a kernel module::hostprogs-y := procfs_example
-obj-m += procfs_example.o
-
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 
@@ -238,7 +236,7 @@
 	$(patsubst %.xml, %.pdf,  $(DOCBOOKS)) \
 	$(patsubst %.xml, %.html, $(DOCBOOKS)) \
 	$(patsubst %.xml, %.9,    $(DOCBOOKS)) \
-	$(C-procfs-example) $(index)
+	$(index)
 
 clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
 
diff --git a/Documentation/DocBook/media-entities.tmpl b/Documentation/DocBook/media-entities.tmpl
index bb5ab74..c725cb8 100644
--- a/Documentation/DocBook/media-entities.tmpl
+++ b/Documentation/DocBook/media-entities.tmpl
@@ -23,6 +23,7 @@
 <!ENTITY VIDIOC-ENUMINPUT "<link linkend='vidioc-enuminput'><constant>VIDIOC_ENUMINPUT</constant></link>">
 <!ENTITY VIDIOC-ENUMOUTPUT "<link linkend='vidioc-enumoutput'><constant>VIDIOC_ENUMOUTPUT</constant></link>">
 <!ENTITY VIDIOC-ENUMSTD "<link linkend='vidioc-enumstd'><constant>VIDIOC_ENUMSTD</constant></link>">
+<!ENTITY VIDIOC-ENUM-DV-PRESETS "<link linkend='vidioc-enum-dv-presets'><constant>VIDIOC_ENUM_DV_PRESETS</constant></link>">
 <!ENTITY VIDIOC-ENUM-FMT "<link linkend='vidioc-enum-fmt'><constant>VIDIOC_ENUM_FMT</constant></link>">
 <!ENTITY VIDIOC-ENUM-FRAMEINTERVALS "<link linkend='vidioc-enum-frameintervals'><constant>VIDIOC_ENUM_FRAMEINTERVALS</constant></link>">
 <!ENTITY VIDIOC-ENUM-FRAMESIZES "<link linkend='vidioc-enum-framesizes'><constant>VIDIOC_ENUM_FRAMESIZES</constant></link>">
@@ -30,6 +31,8 @@
 <!ENTITY VIDIOC-G-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_G_AUDOUT</constant></link>">
 <!ENTITY VIDIOC-G-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_G_CROP</constant></link>">
 <!ENTITY VIDIOC-G-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_G_CTRL</constant></link>">
+<!ENTITY VIDIOC-G-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_G_DV_PRESET</constant></link>">
+<!ENTITY VIDIOC-G-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_G_DV_TIMINGS</constant></link>">
 <!ENTITY VIDIOC-G-ENC-INDEX "<link linkend='vidioc-g-enc-index'><constant>VIDIOC_G_ENC_INDEX</constant></link>">
 <!ENTITY VIDIOC-G-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_G_EXT_CTRLS</constant></link>">
 <!ENTITY VIDIOC-G-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_G_FBUF</constant></link>">
@@ -53,6 +56,7 @@
 <!ENTITY VIDIOC-QUERYCTRL "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYCTRL</constant></link>">
 <!ENTITY VIDIOC-QUERYMENU "<link linkend='vidioc-queryctrl'><constant>VIDIOC_QUERYMENU</constant></link>">
 <!ENTITY VIDIOC-QUERYSTD "<link linkend='vidioc-querystd'><constant>VIDIOC_QUERYSTD</constant></link>">
+<!ENTITY VIDIOC-QUERY-DV-PRESET "<link linkend='vidioc-query-dv-preset'><constant>VIDIOC_QUERY_DV_PRESET</constant></link>">
 <!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>">
 <!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>">
 <!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>">
@@ -60,6 +64,8 @@
 <!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>">
 <!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>">
 <!ENTITY VIDIOC-S-CTRL "<link linkend='vidioc-g-ctrl'><constant>VIDIOC_S_CTRL</constant></link>">
+<!ENTITY VIDIOC-S-DV-PRESET "<link linkend='vidioc-g-dv-preset'><constant>VIDIOC_S_DV_PRESET</constant></link>">
+<!ENTITY VIDIOC-S-DV-TIMINGS "<link linkend='vidioc-g-dv-timings'><constant>VIDIOC_S_DV_TIMINGS</constant></link>">
 <!ENTITY VIDIOC-S-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_S_EXT_CTRLS</constant></link>">
 <!ENTITY VIDIOC-S-FBUF "<link linkend='vidioc-g-fbuf'><constant>VIDIOC_S_FBUF</constant></link>">
 <!ENTITY VIDIOC-S-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_S_FMT</constant></link>">
@@ -118,6 +124,7 @@
 <!-- Structures -->
 <!ENTITY v4l2-audio "struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link>">
 <!ENTITY v4l2-audioout "struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link>">
+<!ENTITY v4l2-bt-timings "struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link>">
 <!ENTITY v4l2-buffer "struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link>">
 <!ENTITY v4l2-capability "struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link>">
 <!ENTITY v4l2-captureparm "struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link>">
@@ -128,6 +135,9 @@
 <!ENTITY v4l2-dbg-chip-ident "struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link>">
 <!ENTITY v4l2-dbg-match "struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link>">
 <!ENTITY v4l2-dbg-register "struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link>">
+<!ENTITY v4l2-dv-enum-preset "struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link>">
+<!ENTITY v4l2-dv-preset "struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link>">
+<!ENTITY v4l2-dv-timings "struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link>">
 <!ENTITY v4l2-enc-idx "struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>">
 <!ENTITY v4l2-enc-idx-entry "struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>">
 <!ENTITY v4l2-encoder-cmd "struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>">
@@ -243,6 +253,10 @@
 <!ENTITY sub-enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
 <!ENTITY sub-enuminput SYSTEM "v4l/vidioc-enuminput.xml">
 <!ENTITY sub-enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
+<!ENTITY sub-enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
+<!ENTITY sub-g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
+<!ENTITY sub-query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
+<!ENTITY sub-g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
 <!ENTITY sub-enumstd SYSTEM "v4l/vidioc-enumstd.xml">
 <!ENTITY sub-g-audio SYSTEM "v4l/vidioc-g-audio.xml">
 <!ENTITY sub-g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">
@@ -333,6 +347,10 @@
 <!ENTITY enumaudioout SYSTEM "v4l/vidioc-enumaudioout.xml">
 <!ENTITY enuminput SYSTEM "v4l/vidioc-enuminput.xml">
 <!ENTITY enumoutput SYSTEM "v4l/vidioc-enumoutput.xml">
+<!ENTITY enum-dv-presets SYSTEM "v4l/vidioc-enum-dv-presets.xml">
+<!ENTITY g-dv-preset SYSTEM "v4l/vidioc-g-dv-preset.xml">
+<!ENTITY query-dv-preset SYSTEM "v4l/vidioc-query-dv-preset.xml">
+<!ENTITY g-dv-timings SYSTEM "v4l/vidioc-g-dv-timings.xml">
 <!ENTITY enumstd SYSTEM "v4l/vidioc-enumstd.xml">
 <!ENTITY g-audio SYSTEM "v4l/vidioc-g-audio.xml">
 <!ENTITY g-audioout SYSTEM "v4l/vidioc-g-audioout.xml">
diff --git a/Documentation/DocBook/media-indices.tmpl b/Documentation/DocBook/media-indices.tmpl
index 9e30a23..78d6031 100644
--- a/Documentation/DocBook/media-indices.tmpl
+++ b/Documentation/DocBook/media-indices.tmpl
@@ -36,6 +36,7 @@
 <indexentry><primaryie>enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link></primaryie></indexentry>
+<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link></primaryie></indexentry>
@@ -46,6 +47,9 @@
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link></primaryie></indexentry>
+<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link></primaryie></indexentry>
+<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link></primaryie></indexentry>
+<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link></primaryie></indexentry>
 <indexentry><primaryie>struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link></primaryie></indexentry>
diff --git a/Documentation/DocBook/procfs-guide.tmpl b/Documentation/DocBook/procfs-guide.tmpl
deleted file mode 100644
index 9eba4b7..0000000
--- a/Documentation/DocBook/procfs-guide.tmpl
+++ /dev/null
@@ -1,626 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY procfsexample SYSTEM "procfs_example.xml">
-]>
-
-<book id="LKProcfsGuide">
-  <bookinfo>
-    <title>Linux Kernel Procfs Guide</title>
-
-    <authorgroup>
-      <author>
-	<firstname>Erik</firstname>
-	<othername>(J.A.K.)</othername>
-	<surname>Mouw</surname>
-	<affiliation>
-	  <address>
-            <email>mouw@nl.linux.org</email>
-          </address>
-	</affiliation>
-      </author>
-      <othercredit>
-	<contrib>
-	This software and documentation were written while working on the
-	LART computing board
-	(<ulink url="http://www.lartmaker.nl/">http://www.lartmaker.nl/</ulink>),
-	which was sponsored by the Delt University of Technology projects
-	Mobile Multi-media Communications and Ubiquitous Communications.
-	</contrib>
-      </othercredit>
-    </authorgroup>
-
-    <revhistory>
-      <revision>
-	<revnumber>1.0</revnumber>
-	<date>May 30, 2001</date>
-	<revremark>Initial revision posted to linux-kernel</revremark>
-      </revision>
-      <revision>
-	<revnumber>1.1</revnumber>
-	<date>June 3, 2001</date>
-	<revremark>Revised after comments from linux-kernel</revremark>
-      </revision>
-    </revhistory>
-
-    <copyright>
-      <year>2001</year>
-      <holder>Erik Mouw</holder>
-    </copyright>
-
-
-    <legalnotice>
-      <para>
-        This documentation is free software; you can redistribute it
-        and/or modify it under the terms of the GNU General Public
-        License as published by the Free Software Foundation; either
-        version 2 of the License, or (at your option) any later
-        version.
-      </para>
-      
-      <para>
-        This documentation is distributed in the hope that it will be
-        useful, but WITHOUT ANY WARRANTY; without even the implied
-        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-        PURPOSE.  See the GNU General Public License for more details.
-      </para>
-      
-      <para>
-        You should have received a copy of the GNU General Public
-        License along with this program; if not, write to the Free
-        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-        MA 02111-1307 USA
-      </para>
-      
-      <para>
-        For more details see the file COPYING in the source
-        distribution of Linux.
-      </para>
-    </legalnotice>
-  </bookinfo>
-
-
-
-
-  <toc>
-  </toc>
-
-
-
-
-  <preface id="Preface">
-    <title>Preface</title>
-
-    <para>
-      This guide describes the use of the procfs file system from
-      within the Linux kernel. The idea to write this guide came up on
-      the #kernelnewbies IRC channel (see <ulink
-      url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
-      when Jeff Garzik explained the use of procfs and forwarded me a
-      message Alexander Viro wrote to the linux-kernel mailing list. I
-      agreed to write it up nicely, so here it is.
-    </para>
-
-    <para>
-      I'd like to thank Jeff Garzik
-      <email>jgarzik@pobox.com</email> and Alexander Viro
-      <email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input,
-      Tim Waugh <email>twaugh@redhat.com</email> for his <ulink
-      url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
-      and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
-      proofreading.
-    </para>
-
-    <para>
-      Erik
-    </para>
-  </preface>
-
-
-
-
-  <chapter id="intro">
-    <title>Introduction</title>
-
-    <para>
-      The <filename class="directory">/proc</filename> file system
-      (procfs) is a special file system in the linux kernel. It's a
-      virtual file system: it is not associated with a block device
-      but exists only in memory. The files in the procfs are there to
-      allow userland programs access to certain information from the
-      kernel (like process information in <filename
-      class="directory">/proc/[0-9]+/</filename>), but also for debug
-      purposes (like <filename>/proc/ksyms</filename>).
-    </para>
-
-    <para>
-      This guide describes the use of the procfs file system from
-      within the Linux kernel. It starts by introducing all relevant
-      functions to manage the files within the file system. After that
-      it shows how to communicate with userland, and some tips and
-      tricks will be pointed out. Finally a complete example will be
-      shown.
-    </para>
-
-    <para>
-      Note that the files in <filename
-      class="directory">/proc/sys</filename> are sysctl files: they
-      don't belong to procfs and are governed by a completely
-      different API described in the Kernel API book.
-    </para>
-  </chapter>
-
-
-
-
-  <chapter id="managing">
-    <title>Managing procfs entries</title>
-    
-    <para>
-      This chapter describes the functions that various kernel
-      components use to populate the procfs with files, symlinks,
-      device nodes, and directories.
-    </para>
-
-    <para>
-      A minor note before we start: if you want to use any of the
-      procfs functions, be sure to include the correct header file! 
-      This should be one of the first lines in your code:
-    </para>
-
-    <programlisting>
-#include &lt;linux/proc_fs.h&gt;
-    </programlisting>
-
-
-
-
-    <sect1 id="regularfile">
-      <title>Creating a regular file</title>
-      
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
-	  <paramdef>const char* <parameter>name</parameter></paramdef>
-	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-
-      <para>
-        This function creates a regular file with the name
-        <parameter>name</parameter>, file mode
-        <parameter>mode</parameter> in the directory
-        <parameter>parent</parameter>. To create a file in the root of
-        the procfs, use <constant>NULL</constant> as
-        <parameter>parent</parameter> parameter. When successful, the
-        function will return a pointer to the freshly created
-        <structname>struct proc_dir_entry</structname>; otherwise it
-        will return <constant>NULL</constant>. <xref
-        linkend="userland"/> describes how to do something useful with
-        regular files.
-      </para>
-
-      <para>
-        Note that it is specifically supported that you can pass a
-        path that spans multiple directories. For example
-        <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
-        will create the <filename class="directory">via0</filename>
-        directory if necessary, with standard
-        <constant>0755</constant> permissions.
-      </para>
-
-    <para>
-      If you only want to be able to read the file, the function
-      <function>create_proc_read_entry</function> described in <xref
-      linkend="convenience"/> may be used to create and initialise
-      the procfs entry in one single call.
-    </para>
-    </sect1>
-
-
-
-
-    <sect1 id="Creating_a_symlink">
-      <title>Creating a symlink</title>
-
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>struct proc_dir_entry*
-	  <function>proc_symlink</function></funcdef> <paramdef>const
-	  char* <parameter>name</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry*
-	  <parameter>parent</parameter></paramdef> <paramdef>const
-	  char* <parameter>dest</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-      
-      <para>
-        This creates a symlink in the procfs directory
-        <parameter>parent</parameter> that points from
-        <parameter>name</parameter> to
-        <parameter>dest</parameter>. This translates in userland to
-        <literal>ln -s</literal> <parameter>dest</parameter>
-        <parameter>name</parameter>.
-      </para>
-    </sect1>
-
-    <sect1 id="Creating_a_directory">
-      <title>Creating a directory</title>
-      
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
-	  <paramdef>const char* <parameter>name</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-
-      <para>
-        Create a directory <parameter>name</parameter> in the procfs
-        directory <parameter>parent</parameter>.
-      </para>
-    </sect1>
-
-
-
-
-    <sect1 id="Removing_an_entry">
-      <title>Removing an entry</title>
-      
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>void <function>remove_proc_entry</function></funcdef>
-	  <paramdef>const char* <parameter>name</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-
-      <para>
-        Removes the entry <parameter>name</parameter> in the directory
-        <parameter>parent</parameter> from the procfs. Entries are
-        removed by their <emphasis>name</emphasis>, not by the
-        <structname>struct proc_dir_entry</structname> returned by the
-        various create functions. Note that this function doesn't
-        recursively remove entries.
-      </para>
-
-      <para>
-        Be sure to free the <structfield>data</structfield> entry from
-        the <structname>struct proc_dir_entry</structname> before
-        <function>remove_proc_entry</function> is called (that is: if
-        there was some <structfield>data</structfield> allocated, of
-        course). See <xref linkend="usingdata"/> for more information
-        on using the <structfield>data</structfield> entry.
-      </para>
-    </sect1>
-  </chapter>
-
-
-
-
-  <chapter id="userland">
-    <title>Communicating with userland</title>
-    
-    <para>
-       Instead of reading (or writing) information directly from
-       kernel memory, procfs works with <emphasis>call back
-       functions</emphasis> for files: functions that are called when
-       a specific file is being read or written. Such functions have
-       to be initialised after the procfs file is created by setting
-       the <structfield>read_proc</structfield> and/or
-       <structfield>write_proc</structfield> fields in the
-       <structname>struct proc_dir_entry*</structname> that the
-       function <function>create_proc_entry</function> returned:
-    </para>
-
-    <programlisting>
-struct proc_dir_entry* entry;
-
-entry->read_proc = read_proc_foo;
-entry->write_proc = write_proc_foo;
-    </programlisting>
-
-    <para>
-      If you only want to use a the
-      <structfield>read_proc</structfield>, the function
-      <function>create_proc_read_entry</function> described in <xref
-      linkend="convenience"/> may be used to create and initialise the
-      procfs entry in one single call.
-    </para>
-
-
-
-    <sect1 id="Reading_data">
-      <title>Reading data</title>
-
-      <para>
-        The read function is a call back function that allows userland
-        processes to read data from the kernel. The read function
-        should have the following format:
-      </para>
-
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>int <function>read_func</function></funcdef>
-	  <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>peof</parameter></paramdef>
-	  <paramdef>void* <parameter>data</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-
-      <para>
-        The read function should write its information into the
-        <parameter>buffer</parameter>, which will be exactly
-        <literal>PAGE_SIZE</literal> bytes long.
-      </para>
-
-      <para>
-        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>peof</parameter> points to.
-      </para>
-
-      <para>
-        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 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.
-      </para>
-    </sect1>
-
-
-
-
-    <sect1 id="Writing_data">
-      <title>Writing data</title>
-
-      <para>
-        The write call back function allows a userland process to write
-        data to the kernel, so it has some kind of control over the
-        kernel. The write function should have the following format:
-      </para>
-
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>int <function>write_func</function></funcdef>
-	  <paramdef>struct file* <parameter>file</parameter></paramdef>
-	  <paramdef>const char* <parameter>buffer</parameter></paramdef>
-	  <paramdef>unsigned long <parameter>count</parameter></paramdef>
-	  <paramdef>void* <parameter>data</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-
-      <para>
-        The write function should read <parameter>count</parameter>
-        bytes at maximum from the <parameter>buffer</parameter>. Note
-        that the <parameter>buffer</parameter> doesn't live in the
-        kernel's memory space, so it should first be copied to kernel
-        space with <function>copy_from_user</function>. The
-        <parameter>file</parameter> parameter is usually
-        ignored. <xref linkend="usingdata"/> shows how to use the
-        <parameter>data</parameter> parameter.
-      </para>
-
-      <para>
-        Again, <xref linkend="example"/> shows how to use this call back
-        function.
-      </para>
-    </sect1>
-
-
-
-
-    <sect1 id="usingdata">
-      <title>A single call back for many files</title>
-
-      <para>
-         When a large number of almost identical files is used, it's
-         quite inconvenient to use a separate call back function for
-         each file. A better approach is to have a single call back
-         function that distinguishes between the files by using the
-         <structfield>data</structfield> field in <structname>struct
-         proc_dir_entry</structname>. First of all, the
-         <structfield>data</structfield> field has to be initialised:
-      </para>
-
-      <programlisting>
-struct proc_dir_entry* entry;
-struct my_file_data *file_data;
-
-file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
-entry->data = file_data;
-      </programlisting>
-     
-      <para>
-          The <structfield>data</structfield> field is a <type>void
-          *</type>, so it can be initialised with anything.
-      </para>
-
-      <para>
-        Now that the <structfield>data</structfield> field is set, the
-        <function>read_proc</function> and
-        <function>write_proc</function> can use it to distinguish
-        between files because they get it passed into their
-        <parameter>data</parameter> parameter:
-      </para>
-
-      <programlisting>
-int foo_read_func(char *page, char **start, off_t off,
-                  int count, int *eof, void *data)
-{
-        int len;
-
-        if(data == file_data) {
-                /* special case for this file */
-        } else {
-                /* normal processing */
-        }
-
-        return len;
-}
-      </programlisting>
-
-      <para>
-        Be sure to free the <structfield>data</structfield> data field
-        when removing the procfs entry.
-      </para>
-    </sect1>
-  </chapter>
-
-
-
-
-  <chapter id="tips">
-    <title>Tips and tricks</title>
-
-
-
-
-    <sect1 id="convenience">
-      <title>Convenience functions</title>
-
-      <funcsynopsis>
-	<funcprototype>
-	  <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
-	  <paramdef>const char* <parameter>name</parameter></paramdef>
-	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
-	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
-	  <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
-	  <paramdef>void* <parameter>data</parameter></paramdef>
-	</funcprototype>
-      </funcsynopsis>
-      
-      <para>
-        This function creates a regular file in exactly the same way
-        as <function>create_proc_entry</function> from <xref
-        linkend="regularfile"/> does, but also allows to set the read
-        function <parameter>read_proc</parameter> in one call. This
-        function can set the <parameter>data</parameter> as well, like
-        explained in <xref linkend="usingdata"/>.
-      </para>
-    </sect1>
-
-
-
-    <sect1 id="Modules">
-      <title>Modules</title>
-
-      <para>
-        If procfs is being used from within a module, be sure to set
-        the <structfield>owner</structfield> field in the
-        <structname>struct proc_dir_entry</structname> to
-        <constant>THIS_MODULE</constant>.
-      </para>
-
-      <programlisting>
-struct proc_dir_entry* entry;
-
-entry->owner = THIS_MODULE;
-      </programlisting>
-    </sect1>
-
-
-
-
-    <sect1 id="Mode_and_ownership">
-      <title>Mode and ownership</title>
-
-      <para>
-        Sometimes it is useful to change the mode and/or ownership of
-        a procfs entry. Here is an example that shows how to achieve
-        that:
-      </para>
-
-      <programlisting>
-struct proc_dir_entry* entry;
-
-entry->mode =  S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
-entry->uid = 0;
-entry->gid = 100;
-      </programlisting>
-
-    </sect1>
-  </chapter>
-
-
-
-
-  <chapter id="example">
-    <title>Example</title>
-
-    <!-- be careful with the example code: it shouldn't be wider than
-    approx. 60 columns, or otherwise it won't fit properly on a page
-    -->
-
-&procfsexample;
-
-  </chapter>
-</book>
diff --git a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c
deleted file mode 100644
index a5b1179..0000000
--- a/Documentation/DocBook/procfs_example.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * procfs_example.c: an example proc interface
- *
- * Copyright (C) 2001, Erik Mouw (mouw@nl.linux.org)
- *
- * This file accompanies the procfs-guide in the Linux kernel
- * source. Its main use is to demonstrate the concepts and
- * functions described in the guide.
- *
- * This software has been developed while working on the LART
- * computing board (http://www.lartmaker.nl), which was sponsored
- * by the Delt University of Technology projects Mobile Multi-media
- * Communications and Ubiquitous Communications.
- *
- * This program is free software; you can redistribute
- * it and/or modify it under the terms of the 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/kernel.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/jiffies.h>
-#include <asm/uaccess.h>
-
-
-#define MODULE_VERS "1.0"
-#define MODULE_NAME "procfs_example"
-
-#define FOOBAR_LEN 8
-
-struct fb_data_t {
-	char name[FOOBAR_LEN + 1];
-	char value[FOOBAR_LEN + 1];
-};
-
-
-static struct proc_dir_entry *example_dir, *foo_file,
-	*bar_file, *jiffies_file, *symlink;
-
-
-struct fb_data_t foo_data, bar_data;
-
-
-static int proc_read_jiffies(char *page, char **start,
-			     off_t off, int count,
-			     int *eof, void *data)
-{
-	int len;
-
-	len = sprintf(page, "jiffies = %ld\n",
-                      jiffies);
-
-	return len;
-}
-
-
-static int proc_read_foobar(char *page, char **start,
-			    off_t off, int count, 
-			    int *eof, void *data)
-{
-	int len;
-	struct fb_data_t *fb_data = (struct fb_data_t *)data;
-
-	/* DON'T DO THAT - buffer overruns are bad */
-	len = sprintf(page, "%s = '%s'\n", 
-		      fb_data->name, fb_data->value);
-
-	return len;
-}
-
-
-static int proc_write_foobar(struct file *file,
-			     const char *buffer,
-			     unsigned long count, 
-			     void *data)
-{
-	int len;
-	struct fb_data_t *fb_data = (struct fb_data_t *)data;
-
-	if(count > FOOBAR_LEN)
-		len = FOOBAR_LEN;
-	else
-		len = count;
-
-	if(copy_from_user(fb_data->value, buffer, len))
-		return -EFAULT;
-
-	fb_data->value[len] = '\0';
-
-	return len;
-}
-
-
-static int __init init_procfs_example(void)
-{
-	int rv = 0;
-
-	/* create directory */
-	example_dir = proc_mkdir(MODULE_NAME, NULL);
-	if(example_dir == NULL) {
-		rv = -ENOMEM;
-		goto out;
-	}
-	/* create jiffies using convenience function */
-	jiffies_file = create_proc_read_entry("jiffies", 
-					      0444, example_dir, 
-					      proc_read_jiffies,
-					      NULL);
-	if(jiffies_file == NULL) {
-		rv  = -ENOMEM;
-		goto no_jiffies;
-	}
-
-	/* create foo and bar files using same callback
-	 * functions 
-	 */
-	foo_file = create_proc_entry("foo", 0644, example_dir);
-	if(foo_file == NULL) {
-		rv = -ENOMEM;
-		goto no_foo;
-	}
-
-	strcpy(foo_data.name, "foo");
-	strcpy(foo_data.value, "foo");
-	foo_file->data = &foo_data;
-	foo_file->read_proc = proc_read_foobar;
-	foo_file->write_proc = proc_write_foobar;
-		
-	bar_file = create_proc_entry("bar", 0644, example_dir);
-	if(bar_file == NULL) {
-		rv = -ENOMEM;
-		goto no_bar;
-	}
-
-	strcpy(bar_data.name, "bar");
-	strcpy(bar_data.value, "bar");
-	bar_file->data = &bar_data;
-	bar_file->read_proc = proc_read_foobar;
-	bar_file->write_proc = proc_write_foobar;
-		
-	/* create symlink */
-	symlink = proc_symlink("jiffies_too", example_dir, 
-			       "jiffies");
-	if(symlink == NULL) {
-		rv = -ENOMEM;
-		goto no_symlink;
-	}
-
-	/* everything OK */
-	printk(KERN_INFO "%s %s initialised\n",
-	       MODULE_NAME, MODULE_VERS);
-	return 0;
-
-no_symlink:
-	remove_proc_entry("bar", example_dir);
-no_bar:
-	remove_proc_entry("foo", example_dir);
-no_foo:
-	remove_proc_entry("jiffies", example_dir);
-no_jiffies:			      
-	remove_proc_entry(MODULE_NAME, NULL);
-out:
-	return rv;
-}
-
-
-static void __exit cleanup_procfs_example(void)
-{
-	remove_proc_entry("jiffies_too", example_dir);
-	remove_proc_entry("bar", example_dir);
-	remove_proc_entry("foo", example_dir);
-	remove_proc_entry("jiffies", example_dir);
-	remove_proc_entry(MODULE_NAME, NULL);
-
-	printk(KERN_INFO "%s %s removed\n",
-	       MODULE_NAME, MODULE_VERS);
-}
-
-
-module_init(init_procfs_example);
-module_exit(cleanup_procfs_example);
-
-MODULE_AUTHOR("Erik Mouw");
-MODULE_DESCRIPTION("procfs examples");
-MODULE_LICENSE("GPL");
diff --git a/Documentation/DocBook/v4l/common.xml b/Documentation/DocBook/v4l/common.xml
index b1a81d2..c65f0ac 100644
--- a/Documentation/DocBook/v4l/common.xml
+++ b/Documentation/DocBook/v4l/common.xml
@@ -716,6 +716,41 @@
 }
       </programlisting>
     </example>
+  <section id="dv-timings">
+	<title>Digital Video (DV) Timings</title>
+	<para>
+	The video standards discussed so far has been dealing with Analog TV and the
+corresponding video timings. Today there are many more different hardware interfaces
+such as High Definition TV interfaces (HDMI), VGA, DVI connectors etc., that carry
+video signals and there is a need to extend the API to select the video timings
+for these interfaces. Since it is not possible to extend the &v4l2-std-id; due to
+the limited bits available, a new set of IOCTLs is added to set/get video timings at
+the input and output: </para><itemizedlist>
+	<listitem>
+	<para>DV Presets: Digital Video (DV) presets. These are IDs representing a
+video timing at the input/output. Presets are pre-defined timings implemented
+by the hardware according to video standards. A __u32 data type is used to represent
+a preset unlike the bit mask that is used in &v4l2-std-id; allowing future extensions
+to support as many different presets as needed.</para>
+	</listitem>
+	<listitem>
+	<para>Custom DV Timings: This will allow applications to define more detailed
+custom video timings for the interface. This includes parameters such as width, height,
+polarities, frontporch, backporch etc.
+	</para>
+	</listitem>
+	</itemizedlist>
+	<para>To enumerate and query the attributes of DV presets supported by a device,
+applications use the &VIDIOC-ENUM-DV-PRESETS; ioctl. To get the current DV preset,
+applications use the &VIDIOC-G-DV-PRESET; ioctl and to set a preset they use the
+&VIDIOC-S-DV-PRESET; ioctl.</para>
+	<para>To set custom DV timings for the device, applications use the
+&VIDIOC-S-DV-TIMINGS; ioctl and to get current custom DV timings they use the
+&VIDIOC-G-DV-TIMINGS; ioctl.</para>
+	<para>Applications can make use of the <xref linkend="input-capabilities" /> and
+<xref linkend="output-capabilities"/> flags to decide what ioctls are available to set the
+video timings for the device.</para>
+	</section>
   </section>
 
   &sub-controls;
diff --git a/Documentation/DocBook/v4l/compat.xml b/Documentation/DocBook/v4l/compat.xml
index 4d1902a..b9dbdf9 100644
--- a/Documentation/DocBook/v4l/compat.xml
+++ b/Documentation/DocBook/v4l/compat.xml
@@ -2291,8 +2291,8 @@
 	<listitem>
 	  <para>New control <constant>V4L2_CID_COLORFX</constant> was added.</para>
 	</listitem>
-       </orderedlist>
-     </section>
+      </orderedlist>
+    </section>
     <section>
       <title>V4L2 in Linux 2.6.32</title>
       <orderedlist>
@@ -2322,8 +2322,16 @@
 	<listitem>
 	  <para>Added Remote Controller chapter, describing the default Remote Controller mapping for media devices.</para>
 	</listitem>
-       </orderedlist>
-     </section>
+      </orderedlist>
+    </section>
+    <section>
+      <title>V4L2 in Linux 2.6.33</title>
+      <orderedlist>
+	<listitem>
+	  <para>Added support for Digital Video timings in order to support HDTV receivers and transmitters.</para>
+	</listitem>
+      </orderedlist>
+    </section>
    </section>
 
    <section id="other">
diff --git a/Documentation/DocBook/v4l/v4l2.xml b/Documentation/DocBook/v4l/v4l2.xml
index 937b415..060105a 100644
--- a/Documentation/DocBook/v4l/v4l2.xml
+++ b/Documentation/DocBook/v4l/v4l2.xml
@@ -74,6 +74,17 @@
 	  </address>
 	</affiliation>
       </author>
+
+      <author>
+	<firstname>Muralidharan</firstname>
+	<surname>Karicheri</surname>
+	<contrib>Documented the Digital Video timings API.</contrib>
+	<affiliation>
+	  <address>
+	    <email>m-karicheri2@ti.com</email>
+	  </address>
+	</affiliation>
+      </author>
     </authorgroup>
 
     <copyright>
@@ -89,7 +100,7 @@
       <year>2008</year>
       <year>2009</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
-Rubli, Andy Walls, Mauro Carvalho Chehab</holder>
+Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
     </copyright>
     <legalnotice>
     <para>Except when explicitly stated as GPL, programming examples within
@@ -103,6 +114,13 @@
 applications. -->
 
       <revision>
+	<revnumber>2.6.33</revnumber>
+	<date>2009-12-03</date>
+	<authorinitials>mk</authorinitials>
+	<revremark>Added documentation for the Digital Video timings API.</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>2.6.32</revnumber>
 	<date>2009-08-31</date>
 	<authorinitials>mcc</authorinitials>
@@ -355,7 +373,7 @@
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 2.6.32</subtitle>
+ <subtitle>Revision 2.6.33</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -411,6 +429,7 @@
     &sub-encoder-cmd;
     &sub-enumaudio;
     &sub-enumaudioout;
+    &sub-enum-dv-presets;
     &sub-enum-fmt;
     &sub-enum-framesizes;
     &sub-enum-frameintervals;
@@ -421,6 +440,8 @@
     &sub-g-audioout;
     &sub-g-crop;
     &sub-g-ctrl;
+    &sub-g-dv-preset;
+    &sub-g-dv-timings;
     &sub-g-enc-index;
     &sub-g-ext-ctrls;
     &sub-g-fbuf;
@@ -441,6 +462,7 @@
     &sub-querybuf;
     &sub-querycap;
     &sub-queryctrl;
+    &sub-query-dv-preset;
     &sub-querystd;
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml
index 3e282ed..0683259 100644
--- a/Documentation/DocBook/v4l/videodev2.h.xml
+++ b/Documentation/DocBook/v4l/videodev2.h.xml
@@ -734,6 +734,99 @@
 };
 
 /*
+ *      V I D E O       T I M I N G S   D V     P R E S E T
+ */
+struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link> {
+        __u32   preset;
+        __u32   reserved[4];
+};
+
+/*
+ *      D V     P R E S E T S   E N U M E R A T I O N
+ */
+struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link> {
+        __u32   index;
+        __u32   preset;
+        __u8    name[32]; /* Name of the preset timing */
+        __u32   width;
+        __u32   height;
+        __u32   reserved[4];
+};
+
+/*
+ *      D V     P R E S E T     V A L U E S
+ */
+#define         V4L2_DV_INVALID         0
+#define         V4L2_DV_480P59_94       1 /* BT.1362 */
+#define         V4L2_DV_576P50          2 /* BT.1362 */
+#define         V4L2_DV_720P24          3 /* SMPTE 296M */
+#define         V4L2_DV_720P25          4 /* SMPTE 296M */
+#define         V4L2_DV_720P30          5 /* SMPTE 296M */
+#define         V4L2_DV_720P50          6 /* SMPTE 296M */
+#define         V4L2_DV_720P59_94       7 /* SMPTE 274M */
+#define         V4L2_DV_720P60          8 /* SMPTE 274M/296M */
+#define         V4L2_DV_1080I29_97      9 /* BT.1120/ SMPTE 274M */
+#define         V4L2_DV_1080I30         10 /* BT.1120/ SMPTE 274M */
+#define         V4L2_DV_1080I25         11 /* BT.1120 */
+#define         V4L2_DV_1080I50         12 /* SMPTE 296M */
+#define         V4L2_DV_1080I60         13 /* SMPTE 296M */
+#define         V4L2_DV_1080P24         14 /* SMPTE 296M */
+#define         V4L2_DV_1080P25         15 /* SMPTE 296M */
+#define         V4L2_DV_1080P30         16 /* SMPTE 296M */
+#define         V4L2_DV_1080P50         17 /* BT.1120 */
+#define         V4L2_DV_1080P60         18 /* BT.1120 */
+
+/*
+ *      D V     B T     T I M I N G S
+ */
+
+/* BT.656/BT.1120 timing data */
+struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link> {
+        __u32   width;          /* width in pixels */
+        __u32   height;         /* height in lines */
+        __u32   interlaced;     /* Interlaced or progressive */
+        __u32   polarities;     /* Positive or negative polarity */
+        __u64   pixelclock;     /* Pixel clock in HZ. Ex. 74.25MHz-&gt;74250000 */
+        __u32   hfrontporch;    /* Horizpontal front porch in pixels */
+        __u32   hsync;          /* Horizontal Sync length in pixels */
+        __u32   hbackporch;     /* Horizontal back porch in pixels */
+        __u32   vfrontporch;    /* Vertical front porch in pixels */
+        __u32   vsync;          /* Vertical Sync length in lines */
+        __u32   vbackporch;     /* Vertical back porch in lines */
+        __u32   il_vfrontporch; /* Vertical front porch for bottom field of
+                                 * interlaced field formats
+                                 */
+        __u32   il_vsync;       /* Vertical sync length for bottom field of
+                                 * interlaced field formats
+                                 */
+        __u32   il_vbackporch;  /* Vertical back porch for bottom field of
+                                 * interlaced field formats
+                                 */
+        __u32   reserved[16];
+} __attribute__ ((packed));
+
+/* Interlaced or progressive format */
+#define V4L2_DV_PROGRESSIVE     0
+#define V4L2_DV_INTERLACED      1
+
+/* Polarities. If bit is not set, it is assumed to be negative polarity */
+#define V4L2_DV_VSYNC_POS_POL   0x00000001
+#define V4L2_DV_HSYNC_POS_POL   0x00000002
+
+
+/* DV timings */
+struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link> {
+        __u32 type;
+        union {
+                struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link>  bt;
+                __u32   reserved[32];
+        };
+} __attribute__ ((packed));
+
+/* Values for the type field */
+#define V4L2_DV_BT_656_1120     0       /* BT.656/1120 timing type */
+
+/*
  *      V I D E O   I N P U T S
  */
 struct <link linkend="v4l2-input">v4l2_input</link> {
@@ -744,7 +837,8 @@
         __u32        tuner;             /*  Associated tuner */
         v4l2_std_id  std;
         __u32        status;
-        __u32        reserved[4];
+        __u32        capabilities;
+        __u32        reserved[3];
 };
 
 /*  Values for the 'type' field */
@@ -775,6 +869,11 @@
 #define V4L2_IN_ST_NO_ACCESS   0x02000000  /* Conditional access denied */
 #define V4L2_IN_ST_VTR         0x04000000  /* VTR time constant */
 
+/* capabilities flags */
+#define V4L2_IN_CAP_PRESETS             0x00000001 /* Supports S_DV_PRESET */
+#define V4L2_IN_CAP_CUSTOM_TIMINGS      0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_IN_CAP_STD                 0x00000004 /* Supports S_STD */
+
 /*
  *      V I D E O   O U T P U T S
  */
@@ -785,13 +884,19 @@
         __u32        audioset;          /*  Associated audios (bitfield) */
         __u32        modulator;         /*  Associated modulator */
         v4l2_std_id  std;
-        __u32        reserved[4];
+        __u32        capabilities;
+        __u32        reserved[3];
 };
 /*  Values for the 'type' field */
 #define V4L2_OUTPUT_TYPE_MODULATOR              1
 #define V4L2_OUTPUT_TYPE_ANALOG                 2
 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY       3
 
+/* capabilities flags */
+#define V4L2_OUT_CAP_PRESETS            0x00000001 /* Supports S_DV_PRESET */
+#define V4L2_OUT_CAP_CUSTOM_TIMINGS     0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_OUT_CAP_STD                0x00000004 /* Supports S_STD */
+
 /*
  *      C O N T R O L S
  */
@@ -1626,6 +1731,13 @@
 #endif
 
 #define VIDIOC_S_HW_FREQ_SEEK    _IOW('V', 82, struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link>)
+#define VIDIOC_ENUM_DV_PRESETS  _IOWR('V', 83, struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link>)
+#define VIDIOC_S_DV_PRESET      _IOWR('V', 84, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
+#define VIDIOC_G_DV_PRESET      _IOWR('V', 85, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
+#define VIDIOC_QUERY_DV_PRESET  _IOR('V',  86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
+#define VIDIOC_S_DV_TIMINGS     _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
+#define VIDIOC_G_DV_TIMINGS     _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
diff --git a/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml b/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml
new file mode 100644
index 0000000..1d31427
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-enum-dv-presets.xml
@@ -0,0 +1,238 @@
+<refentry id="vidioc-enum-dv-presets">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_ENUM_DV_PRESETS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_ENUM_DV_PRESETS</refname>
+    <refpurpose>Enumerate supported Digital Video presets</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_dv_enum_preset *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_ENUM_DV_PRESETS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>To query the attributes of a DV preset, applications initialize the
+<structfield>index</structfield> field and zero the reserved array of &v4l2-dv-enum-preset;
+and call the <constant>VIDIOC_ENUM_DV_PRESETS</constant> ioctl with a pointer to this
+structure. Drivers fill the rest of the structure or return an
+&EINVAL; when the index is out of bounds. To enumerate all DV Presets supported,
+applications shall begin at index zero, incrementing by one until the
+driver returns <errorcode>EINVAL</errorcode>. Drivers may enumerate a
+different set of DV presets after switching the video input or
+output.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-dv-enum-preset">
+      <title>struct <structname>v4l2_dv_enum_presets</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>Number of the DV preset, set by the
+application.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>preset</structfield></entry>
+	    <entry>This field identifies one of the DV preset values listed in <xref linkend="v4l2-dv-presets-vals"/>.</entry>
+	  </row>
+	  <row>
+	    <entry>__u8</entry>
+	    <entry><structfield>name</structfield>[24]</entry>
+	    <entry>Name of the preset, a NUL-terminated ASCII string, for example: "720P-60", "1080I-60". This information is
+intended for the user.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>width</structfield></entry>
+	    <entry>Width of the active video in pixels for the DV preset.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>height</structfield></entry>
+	    <entry>Height of the active video in lines for the DV preset.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[4]</entry>
+	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="v4l2-dv-presets-vals">
+      <title>struct <structname>DV Presets</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>Preset</entry>
+	    <entry>Preset value</entry>
+	    <entry>Description</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_INVALID</entry>
+	    <entry>0</entry>
+	    <entry>Invalid preset value.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_480P59_94</entry>
+	    <entry>1</entry>
+	    <entry>720x480 progressive video at 59.94 fps as per BT.1362.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_576P50</entry>
+	    <entry>2</entry>
+	    <entry>720x576 progressive video at 50 fps as per BT.1362.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P24</entry>
+	    <entry>3</entry>
+	    <entry>1280x720 progressive video at 24 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P25</entry>
+	    <entry>4</entry>
+	    <entry>1280x720 progressive video at 25 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P30</entry>
+	    <entry>5</entry>
+	    <entry>1280x720 progressive video at 30 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P50</entry>
+	    <entry>6</entry>
+	    <entry>1280x720 progressive video at 50 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P59_94</entry>
+	    <entry>7</entry>
+	    <entry>1280x720 progressive video at 59.94 fps as per SMPTE 274M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_720P60</entry>
+	    <entry>8</entry>
+	    <entry>1280x720 progressive video at 60 fps as per SMPTE 274M/296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080I29_97</entry>
+	    <entry>9</entry>
+	    <entry>1920x1080 interlaced video at 29.97 fps as per BT.1120/SMPTE 274M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080I30</entry>
+	    <entry>10</entry>
+	    <entry>1920x1080 interlaced video at 30 fps as per BT.1120/SMPTE 274M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080I25</entry>
+	    <entry>11</entry>
+	    <entry>1920x1080 interlaced video at 25 fps as per BT.1120.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080I50</entry>
+	    <entry>12</entry>
+	    <entry>1920x1080 interlaced video at 50 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080I60</entry>
+	    <entry>13</entry>
+	    <entry>1920x1080 interlaced video at 60 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080P24</entry>
+	    <entry>14</entry>
+	    <entry>1920x1080 progressive video at 24 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080P25</entry>
+	    <entry>15</entry>
+	    <entry>1920x1080 progressive video at 25 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080P30</entry>
+	    <entry>16</entry>
+	    <entry>1920x1080 progressive video at 30 fps as per SMPTE 296M.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080P50</entry>
+	    <entry>17</entry>
+	    <entry>1920x1080 progressive video at 50 fps as per BT.1120.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_1080P60</entry>
+	    <entry>18</entry>
+	    <entry>1920x1080 progressive video at 60 fps as per BT.1120.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-dv-enum-preset; <structfield>index</structfield>
+is out of bounds.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/v4l/vidioc-enuminput.xml b/Documentation/DocBook/v4l/vidioc-enuminput.xml
index 414856b..71b868e 100644
--- a/Documentation/DocBook/v4l/vidioc-enuminput.xml
+++ b/Documentation/DocBook/v4l/vidioc-enuminput.xml
@@ -124,7 +124,13 @@
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[4]</entry>
+	    <entry><structfield>capabilities</structfield></entry>
+	    <entry>This field provides capabilities for the
+input. See <xref linkend="input-capabilities" /> for flags.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[3]</entry>
 	    <entry>Reserved for future extensions. Drivers must set
 the array to zero.</entry>
 	  </row>
@@ -261,6 +267,34 @@
 	</tbody>
       </tgroup>
     </table>
+
+    <!-- Capability flags based on video timings RFC by Muralidharan
+Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
+input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
+	-->
+    <table frame="none" pgwide="1" id="input-capabilities">
+      <title>Input capabilities</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_IN_CAP_PRESETS</constant></entry>
+	    <entry>0x00000001</entry>
+	    <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
+	    <entry>0x00000002</entry>
+	    <entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_IN_CAP_STD</constant></entry>
+	    <entry>0x00000004</entry>
+	    <entry>This input supports setting the TV standard by using VIDIOC_S_STD.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
   </refsect1>
 
   <refsect1>
diff --git a/Documentation/DocBook/v4l/vidioc-enumoutput.xml b/Documentation/DocBook/v4l/vidioc-enumoutput.xml
index e8d16dc..a281d26 100644
--- a/Documentation/DocBook/v4l/vidioc-enumoutput.xml
+++ b/Documentation/DocBook/v4l/vidioc-enumoutput.xml
@@ -114,7 +114,13 @@
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[4]</entry>
+	    <entry><structfield>capabilities</structfield></entry>
+	    <entry>This field provides capabilities for the
+output. See <xref linkend="output-capabilities" /> for flags.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[3]</entry>
 	    <entry>Reserved for future extensions. Drivers must set
 the array to zero.</entry>
 	  </row>
@@ -147,6 +153,34 @@
       </tgroup>
     </table>
 
+    <!-- Capabilities flags based on video timings RFC by Muralidharan
+Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
+input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
+	-->
+    <table frame="none" pgwide="1" id="output-capabilities">
+      <title>Output capabilities</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_OUT_CAP_PRESETS</constant></entry>
+	    <entry>0x00000001</entry>
+	    <entry>This output supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
+	    <entry>0x00000002</entry>
+	    <entry>This output supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_OUT_CAP_STD</constant></entry>
+	    <entry>0x00000004</entry>
+	    <entry>This output supports setting the TV standard by using VIDIOC_S_STD.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
   </refsect1>
   <refsect1>
     &return-value;
diff --git a/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml b/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml
new file mode 100644
index 0000000..3c6784e
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-g-dv-preset.xml
@@ -0,0 +1,111 @@
+<refentry id="vidioc-g-dv-preset">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_G_DV_PRESET</refname>
+    <refname>VIDIOC_S_DV_PRESET</refname>
+    <refpurpose>Query or select the DV preset of the current input or output</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>&v4l2-dv-preset;
+*<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+    <para>To query and select the current DV preset, applications
+use the <constant>VIDIOC_G_DV_PRESET</constant> and <constant>VIDIOC_S_DV_PRESET</constant>
+ioctls which take a pointer to a &v4l2-dv-preset; type as argument.
+Applications must zero the reserved array in &v4l2-dv-preset;.
+<constant>VIDIOC_G_DV_PRESET</constant> returns a dv preset in the field
+<structfield>preset</structfield> of &v4l2-dv-preset;.</para>
+
+    <para><constant>VIDIOC_S_DV_PRESET</constant> accepts a pointer to a &v4l2-dv-preset;
+that has the preset value to be set. Applications must zero the reserved array in &v4l2-dv-preset;.
+If the preset is not supported, it returns an &EINVAL; </para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>This ioctl is not supported, or the
+<constant>VIDIOC_S_DV_PRESET</constant>,<constant>VIDIOC_S_DV_PRESET</constant> parameter was unsuitable.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The device is busy and therefore can not change the preset.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+
+    <table pgwide="1" frame="none" id="v4l2-dv-preset">
+      <title>struct <structname>v4l2_dv_preset</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>preset</structfield></entry>
+	    <entry>Preset value to represent the digital video timings</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[4]</structfield></entry>
+	    <entry>Reserved fields for future use</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml b/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml
new file mode 100644
index 0000000..ecc1957
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-g-dv-timings.xml
@@ -0,0 +1,224 @@
+<refentry id="vidioc-g-dv-timings">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_G_DV_TIMINGS</refname>
+    <refname>VIDIOC_S_DV_TIMINGS</refname>
+    <refpurpose>Get or set custom DV timings for input or output</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>&v4l2-dv-timings;
+*<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+    <para>To set custom DV timings for the input or output, applications use the
+<constant>VIDIOC_S_DV_TIMINGS</constant> ioctl and to get the current custom timings,
+applications use the <constant>VIDIOC_G_DV_TIMINGS</constant> ioctl. The detailed timing
+information is filled in using the structure &v4l2-dv-timings;. These ioctls take
+a pointer to the &v4l2-dv-timings; structure as argument. If the ioctl is not supported
+or the timing values are not correct, the driver returns &EINVAL;.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>This ioctl is not supported, or the
+<constant>VIDIOC_S_DV_TIMINGS</constant> parameter was unsuitable.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The device is busy and therefore can not change the timings.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+
+    <table pgwide="1" frame="none" id="v4l2-bt-timings">
+      <title>struct <structname>v4l2_bt_timings</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>width</structfield></entry>
+	    <entry>Width of the active video in pixels</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>height</structfield></entry>
+	    <entry>Height of the active video in lines</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>interlaced</structfield></entry>
+	    <entry>Progressive (0) or interlaced (1)</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>polarities</structfield></entry>
+	    <entry>This is a bit mask that defines polarities of sync signals.
+bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_HSYNC_POS_POL) is for horizontal sync polarity. If the bit is set
+(1) it is positive polarity and if is cleared (0), it is negative polarity.</entry>
+	  </row>
+	  <row>
+	    <entry>__u64</entry>
+	    <entry><structfield>pixelclock</structfield></entry>
+	    <entry>Pixel clock in Hz. Ex. 74.25MHz->74250000</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>hfrontporch</structfield></entry>
+	    <entry>Horizontal front porch in pixels</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>hsync</structfield></entry>
+	    <entry>Horizontal sync length in pixels</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>hbackporch</structfield></entry>
+	    <entry>Horizontal back porch in pixels</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>vfrontporch</structfield></entry>
+	    <entry>Vertical front porch in lines</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>vsync</structfield></entry>
+	    <entry>Vertical sync length in lines</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>vbackporch</structfield></entry>
+	    <entry>Vertical back porch in lines</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>il_vfrontporch</structfield></entry>
+	    <entry>Vertical front porch in lines for bottom field of interlaced field formats</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>il_vsync</structfield></entry>
+	    <entry>Vertical sync length in lines for bottom field of interlaced field formats</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>il_vbackporch</structfield></entry>
+	    <entry>Vertical back porch in lines for bottom field of interlaced field formats</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="v4l2-dv-timings">
+      <title>struct <structname>v4l2_dv_timings</structname></title>
+      <tgroup cols="4">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry></entry>
+	    <entry>Type of DV timings as listed in <xref linkend="dv-timing-types"/>.</entry>
+	  </row>
+	  <row>
+	    <entry>union</entry>
+	    <entry><structfield></structfield></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>&v4l2-bt-timings;</entry>
+	    <entry><structfield>bt</structfield></entry>
+	    <entry>Timings defined by BT.656/1120 specifications</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[32]</entry>
+	    <entry></entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="dv-timing-types">
+      <title>DV Timing types</title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>Timing type</entry>
+	    <entry>value</entry>
+	    <entry>Description</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_BT_656_1120</entry>
+	    <entry>0</entry>
+	    <entry>BT.656/1120 timings</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/v4l/vidioc-g-std.xml b/Documentation/DocBook/v4l/vidioc-g-std.xml
index b6f5d26..912f851 100644
--- a/Documentation/DocBook/v4l/vidioc-g-std.xml
+++ b/Documentation/DocBook/v4l/vidioc-g-std.xml
@@ -86,6 +86,12 @@
 <constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
 	</listitem>
       </varlistentry>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The device is busy and therefore can not change the standard</para>
+	</listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
diff --git a/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
new file mode 100644
index 0000000..87e4f0f
--- /dev/null
+++ b/Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
@@ -0,0 +1,85 @@
+<refentry id="vidioc-query-dv-preset">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_QUERY_DV_PRESET</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_QUERY_DV_PRESET</refname>
+    <refpurpose>Sense the DV preset received by the current
+input</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>&v4l2-dv-preset; *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+	<varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_QUERY_DV_PRESET</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>The hardware may be able to detect the current DV preset
+automatically, similar to sensing the video standard. To do so, applications
+call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
+&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
+returned in the preset field of &v4l2-dv-preset;. When detection is not
+possible or fails, the value V4L2_DV_INVALID is returned.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>This ioctl is not supported.</para>
+	</listitem>
+    </varlistentry>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The device is busy and therefore can not sense the preset</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/v4l/vidioc-querystd.xml b/Documentation/DocBook/v4l/vidioc-querystd.xml
index b5a7ff9..1a9e603 100644
--- a/Documentation/DocBook/v4l/vidioc-querystd.xml
+++ b/Documentation/DocBook/v4l/vidioc-querystd.xml
@@ -70,6 +70,12 @@
 	  <para>This ioctl is not supported.</para>
 	</listitem>
       </varlistentry>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The device is busy and therefore can not detect the standard</para>
+	</listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 78a9168..1053a56 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -15,7 +15,7 @@
 2: Passes allnoconfig, allmodconfig
 
 3: Builds on multiple CPU architectures by using local cross-compile tools
-   or something like PLM at OSDL.
+   or some other build farm.
 
 4: ppc64 is a good architecture for cross-compilation checking because it
    tends to use `unsigned long' for 64-bit quantities.
@@ -88,3 +88,6 @@
 
 24: All memory barriers {e.g., barrier(), rmb(), wmb()} need a comment in the
     source code that explains the logic of what they are doing and why.
+
+25: If any ioctl's are added by the patch, then also update
+    Documentation/ioctl/ioctl-number.txt.
diff --git a/Documentation/acpi/method-customizing.txt b/Documentation/acpi/method-customizing.txt
new file mode 100644
index 0000000..e628cd2
--- /dev/null
+++ b/Documentation/acpi/method-customizing.txt
@@ -0,0 +1,66 @@
+Linux ACPI Custom Control Method How To
+=======================================
+
+Written by Zhang Rui <rui.zhang@intel.com>
+
+
+Linux supports customizing ACPI control methods at runtime.
+
+Users can use this to
+1. override an existing method which may not work correctly,
+   or just for debugging purposes.
+2. insert a completely new method in order to create a missing
+   method such as _OFF, _ON, _STA, _INI, etc.
+For these cases, it is far simpler to dynamically install a single
+control method rather than override the entire DSDT, because kernel
+rebuild/reboot is not needed and test result can be got in minutes.
+
+Note: Only ACPI METHOD can be overridden, any other object types like
+      "Device", "OperationRegion", are not recognized.
+Note: The same ACPI control method can be overridden for many times,
+      and it's always the latest one that used by Linux/kernel.
+
+1. override an existing method
+   a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT,
+      just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat"
+   b) disassemble the table by running "iasl -d dsdt.dat".
+   c) rewrite the ASL code of the method and save it in a new file,
+   d) package the new file (psr.asl) to an ACPI table format.
+      Here is an example of a customized \_SB._AC._PSR method,
+
+      DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
+      {
+	External (ACON)
+
+	Method (\_SB_.AC._PSR, 0, NotSerialized)
+	{
+		Store ("In AC _PSR", Debug)
+		Return (ACON)
+	}
+      }
+      Note that the full pathname of the method in ACPI namespace
+      should be used.
+      And remember to use "External" to declare external objects.
+   e) assemble the file to generate the AML code of the method.
+      e.g. "iasl psr.asl" (psr.aml is generated as a result)
+   f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
+   g) override the old method via the debugfs by running
+      "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
+
+2. insert a new method
+   This is easier than overriding an existing method.
+   We just need to create the ASL code of the method we want to
+   insert and then follow the step c) ~ g) in section 1.
+
+3. undo your changes
+   The "undo" operation is not supported for a new inserted method
+   right now, i.e. we can not remove a method currently.
+   For an overrided method, in order to undo your changes, please
+   save a copy of the method original ASL code in step c) section 1,
+   and redo step c) ~ g) to override the method with the original one.
+
+
+Note: We can use a kernel with multiple custom ACPI method running,
+      But each individual write to debugfs can implement a SINGLE
+      method override. i.e. if we want to insert/override multiple
+      ACPI methods, we need to redo step c) ~ g) for multiple times.
diff --git a/Documentation/blackfin/00-INDEX b/Documentation/blackfin/00-INDEX
index d6840a9..c34e124 100644
--- a/Documentation/blackfin/00-INDEX
+++ b/Documentation/blackfin/00-INDEX
@@ -1,9 +1,6 @@
 00-INDEX
 	- This file
 
-cache-lock.txt
-	- HOWTO for blackfin cache locking.
-
 cachefeatures.txt
 	- Supported cache features.
 
diff --git a/Documentation/blackfin/Makefile b/Documentation/blackfin/Makefile
new file mode 100644
index 0000000..773dbb1
--- /dev/null
+++ b/Documentation/blackfin/Makefile
@@ -0,0 +1,6 @@
+obj-m := gptimers-example.o
+
+all: modules
+
+modules clean:
+	$(MAKE) -C ../.. SUBDIRS=$(PWD) $@
diff --git a/Documentation/blackfin/cache-lock.txt b/Documentation/blackfin/cache-lock.txt
deleted file mode 100644
index 88ba1e6..0000000
--- a/Documentation/blackfin/cache-lock.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * File:         Documentation/blackfin/cache-lock.txt
- * Based on:
- * Author:
- *
- * Created:
- * Description:  This file contains the simple DMA Implementation for Blackfin
- *
- * Rev:          $Id: cache-lock.txt 2384 2006-11-01 04:12:43Z magicyang $
- *
- * Modified:
- *               Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs:         Enter bugs at http://blackfin.uclinux.org/
- *
- */
-
-How to lock your code in cache in uClinux/blackfin
---------------------------------------------------
-
-There are only a few steps required to lock your code into the cache.
-Currently you can lock the code by Way.
-
-Below are the interface provided for locking the cache.
-
-
-1. cache_grab_lock(int Ways);
-
-This function grab the lock for locking your code into the cache specified
-by Ways.
-
-
-2. cache_lock(int Ways);
-
-This function should be called after your critical code has been executed.
-Once the critical code exits, the code is now loaded into the cache. This
-function locks the code into the cache.
-
-
-So, the example sequence will be:
-
-	cache_grab_lock(WAY0_L);	/* Grab the lock */
-
-	critical_code();		/* Execute the code of interest */
-
-	cache_lock(WAY0_L);		/* Lock the cache */
-
-Where WAY0_L signifies WAY0 locking.
diff --git a/Documentation/blackfin/cachefeatures.txt b/Documentation/blackfin/cachefeatures.txt
index 0fbec23..75de51f 100644
--- a/Documentation/blackfin/cachefeatures.txt
+++ b/Documentation/blackfin/cachefeatures.txt
@@ -41,16 +41,6 @@
 		icplb_flush();
 		dcplb_flush();
 
-	- Locking the cache.
-
-		cache_grab_lock();
-		cache_lock();
-
-	Please refer linux-2.6.x/Documentation/blackfin/cache-lock.txt for how to
-	lock the cache.
-
-	Locking the cache is optional feature.
-
 	- Miscellaneous cache functions.
 
 		flush_cache_all();
diff --git a/Documentation/blackfin/gptimers-example.c b/Documentation/blackfin/gptimers-example.c
new file mode 100644
index 0000000..b1bd634
--- /dev/null
+++ b/Documentation/blackfin/gptimers-example.c
@@ -0,0 +1,83 @@
+/*
+ * Simple gptimers example
+ *	http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:gptimers
+ *
+ * Copyright 2007-2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/gptimers.h>
+#include <asm/portmux.h>
+
+/* ... random driver includes ... */
+
+#define DRIVER_NAME "gptimer_example"
+
+struct gptimer_data {
+	uint32_t period, width;
+};
+static struct gptimer_data data;
+
+/* ... random driver state ... */
+
+static irqreturn_t gptimer_example_irq(int irq, void *dev_id)
+{
+	struct gptimer_data *data = dev_id;
+
+	/* make sure it was our timer which caused the interrupt */
+	if (!get_gptimer_intr(TIMER5_id))
+		return IRQ_NONE;
+
+	/* read the width/period values that were captured for the waveform */
+	data->width = get_gptimer_pwidth(TIMER5_id);
+	data->period = get_gptimer_period(TIMER5_id);
+
+	/* acknowledge the interrupt */
+	clear_gptimer_intr(TIMER5_id);
+
+	/* tell the upper layers we took care of things */
+	return IRQ_HANDLED;
+}
+
+/* ... random driver code ... */
+
+static int __init gptimer_example_init(void)
+{
+	int ret;
+
+	/* grab the peripheral pins */
+	ret = peripheral_request(P_TMR5, DRIVER_NAME);
+	if (ret) {
+		printk(KERN_NOTICE DRIVER_NAME ": peripheral request failed\n");
+		return ret;
+	}
+
+	/* grab the IRQ for the timer */
+	ret = request_irq(IRQ_TIMER5, gptimer_example_irq, IRQF_SHARED, DRIVER_NAME, &data);
+	if (ret) {
+		printk(KERN_NOTICE DRIVER_NAME ": IRQ request failed\n");
+		peripheral_free(P_TMR5);
+		return ret;
+	}
+
+	/* setup the timer and enable it */
+	set_gptimer_config(TIMER5_id, WDTH_CAP | PULSE_HI | PERIOD_CNT | IRQ_ENA);
+	enable_gptimers(TIMER5bit);
+
+	return 0;
+}
+module_init(gptimer_example_init);
+
+static void __exit gptimer_example_exit(void)
+{
+	disable_gptimers(TIMER5bit);
+	free_irq(IRQ_TIMER5, &data);
+	peripheral_free(P_TMR5);
+}
+module_exit(gptimer_example_exit);
+
+MODULE_LICENSE("BSD");
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index e151b2a..3ad6ace 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -103,6 +103,7 @@
 gen-devlist
 gen_crc32table
 gen_init_cpio
+generated
 genheaders
 genksyms
 *_gray256.c
diff --git a/Documentation/fb/viafb.txt b/Documentation/fb/viafb.txt
index 67dbf44..f3e046a 100644
--- a/Documentation/fb/viafb.txt
+++ b/Documentation/fb/viafb.txt
@@ -7,7 +7,7 @@
     VIA UniChrome Family(CLE266, PM800 / CN400 / CN300,
                         P4M800CE / P4M800Pro / CN700 / VN800,
                         CX700 / VX700, K8M890, P4M890,
-                        CN896 / P4M900, VX800)
+                        CN896 / P4M900, VX800, VX855)
 
 [Driver features]
 ------------------------
@@ -154,13 +154,6 @@
         0 : No Dual Edge Panel (default)
         1 : Dual Edge Panel
 
-    viafb_video_dev:
-        This option is used to specify video output devices(CRT, DVI, LCD) for
-        duoview case.
-        For example:
-        To output video on DVI, we should use:
-            modprobe viafb viafb_video_dev=DVI...
-
     viafb_lcd_port:
         This option is used to specify LCD output port,
         available values are "DVP0" "DVP1" "DFP_HIGHLOW" "DFP_HIGH" "DFP_LOW".
@@ -181,9 +174,6 @@
        and bpp, need to call VIAFB specified ioctl interface VIAFB_SET_DEVICE
        instead of calling common ioctl function FBIOPUT_VSCREENINFO since
        viafb doesn't support multi-head well, or it will cause screen crush.
-    4. VX800 2D accelerator hasn't been supported in this driver yet. When
-       using driver on VX800, the driver will disable the acceleration
-       function as default.
 
 
 [Configure viafb with "fbset" tool]
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 21ab935..870d190 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -474,3 +474,22 @@
 Who:	Jean Delvare <khali@linux-fr.org>
 
 ---------------------------
+What:	Support for lcd_switch and display_get in asus-laptop driver
+When:	March 2010
+Why:	These two features use non-standard interfaces. There are the
+	only features that really need multiple path to guess what's
+	the right method name on a specific laptop.
+
+	Removing them will allow to remove a lot of code an significantly
+	clean the drivers.
+
+	This will affect the backlight code which won't be able to know
+	if the backlight is on or off. The platform display file will also be
+	write only (like the one in eeepc-laptop).
+
+	This should'nt affect a lot of user because they usually know
+	when their display is on or off.
+
+Who:	Corentin Chary <corentin.chary@gmail.com>
+
+----------------------------
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 7001782..875d496 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -1,7 +1,5 @@
 00-INDEX
 	- this file (info on some of the filesystems supported by linux).
-Exporting
-	- explanation of how to make filesystems exportable.
 Locking
 	- info on locking rules as they pertain to Linux VFS.
 9p.txt
@@ -68,12 +66,8 @@
 	- info on the Linux implementation of Sys V mandatory file locking.
 ncpfs.txt
 	- info on Novell Netware(tm) filesystem using NCP protocol.
-nfs41-server.txt
-	- info on the Linux server implementation of NFSv4 minor version 1.
-nfs-rdma.txt
-	- how to install and setup the Linux NFS/RDMA client and server software.
-nfsroot.txt
-	- short guide on setting up a diskless box with NFS root filesystem.
+nfs/
+	- nfs-related documentation.
 nilfs2.txt
 	- info and mount options for the NILFS2 filesystem.
 ntfs.txt
@@ -92,8 +86,6 @@
 	- info on relay, for efficient streaming from kernel to user space.
 romfs.txt
 	- description of the ROMFS filesystem.
-rpc-cache.txt
-	- introduction to the caching mechanisms in the sunrpc layer.
 seq_file.txt
 	- how to use the seq_file API
 sharedsubtree.txt
diff --git a/Documentation/filesystems/nfs/00-INDEX b/Documentation/filesystems/nfs/00-INDEX
new file mode 100644
index 0000000..2f68cd6
--- /dev/null
+++ b/Documentation/filesystems/nfs/00-INDEX
@@ -0,0 +1,16 @@
+00-INDEX
+	- this file (nfs-related documentation).
+Exporting
+	- explanation of how to make filesystems exportable.
+knfsd-stats.txt
+	- statistics which the NFS server makes available to user space.
+nfs.txt
+	- nfs client, and DNS resolution for fs_locations.
+nfs41-server.txt
+	- info on the Linux server implementation of NFSv4 minor version 1.
+nfs-rdma.txt
+	- how to install and setup the Linux NFS/RDMA client and server software
+nfsroot.txt
+	- short guide on setting up a diskless box with NFS root filesystem.
+rpc-cache.txt
+	- introduction to the caching mechanisms in the sunrpc layer.
diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/nfs/Exporting
similarity index 100%
rename from Documentation/filesystems/Exporting
rename to Documentation/filesystems/nfs/Exporting
diff --git a/Documentation/filesystems/knfsd-stats.txt b/Documentation/filesystems/nfs/knfsd-stats.txt
similarity index 100%
rename from Documentation/filesystems/knfsd-stats.txt
rename to Documentation/filesystems/nfs/knfsd-stats.txt
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs/nfs-rdma.txt
similarity index 100%
rename from Documentation/filesystems/nfs-rdma.txt
rename to Documentation/filesystems/nfs/nfs-rdma.txt
diff --git a/Documentation/filesystems/nfs.txt b/Documentation/filesystems/nfs/nfs.txt
similarity index 100%
rename from Documentation/filesystems/nfs.txt
rename to Documentation/filesystems/nfs/nfs.txt
diff --git a/Documentation/filesystems/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
similarity index 96%
rename from Documentation/filesystems/nfs41-server.txt
rename to Documentation/filesystems/nfs/nfs41-server.txt
index 5920fe2..1bd0d0c 100644
--- a/Documentation/filesystems/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -41,7 +41,7 @@
 	  conformant with the spec (for example, we don't use kerberos
 	  on the backchannel correctly).
 	- no trunking support: no clients currently take advantage of
-	  trunking, but this is a mandatory failure, and its use is
+	  trunking, but this is a mandatory feature, and its use is
 	  recommended to clients in a number of places.  (E.g. to ensure
 	  timely renewal in case an existing connection's retry timeouts
 	  have gotten too long; see section 8.3 of the draft.)
@@ -213,3 +213,10 @@
   DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
 * DESTROY_SESSION MUST be the final operation in the COMPOUND request.
 
+Nonstandard compound limitations:
+* No support for a sessions fore channel RPC compound that requires both a
+  ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
+  fail to live up to the promise we made in CREATE_SESSION fore channel
+  negotiation.
+* No more than one IO operation (read, write, readdir) allowed per
+  compound.
diff --git a/Documentation/filesystems/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
similarity index 100%
rename from Documentation/filesystems/nfsroot.txt
rename to Documentation/filesystems/nfs/nfsroot.txt
diff --git a/Documentation/filesystems/rpc-cache.txt b/Documentation/filesystems/nfs/rpc-cache.txt
similarity index 100%
rename from Documentation/filesystems/rpc-cache.txt
rename to Documentation/filesystems/nfs/rpc-cache.txt
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 92b888d..a7e9746 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -140,7 +140,7 @@
 New super_block field "struct export_operations *s_export_op" for
 explicit support for exporting, e.g. via NFS.  The structure is fully
 documented at its declaration in include/linux/fs.h, and in
-Documentation/filesystems/Exporting.
+Documentation/filesystems/nfs/Exporting.
 
 Briefly it allows for the definition of decode_fh and encode_fh operations
 to encode and decode filehandles, and allows the filesystem to use
diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt
index 0d15ebc..a1e2e0d 100644
--- a/Documentation/filesystems/seq_file.txt
+++ b/Documentation/filesystems/seq_file.txt
@@ -248,9 +248,7 @@
 	{
 	        struct proc_dir_entry *entry;
 
-	        entry = create_proc_entry("sequence", 0, NULL);
-	        if (entry)
-	                entry->proc_fops = &ct_file_ops;
+	        proc_create("sequence", 0, NULL, &ct_file_ops);
 	        return 0;
 	}
 
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e4e7daed2..1866c27 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -531,6 +531,13 @@
 		This file exists only if the pin can be configured as an
 		interrupt generating input pin.
 
+	"active_low" ... reads as either 0 (false) or 1 (true).  Write
+		any nonzero value to invert the value attribute both
+		for reading and writing.  Existing and subsequent
+		poll(2) support configuration via the edge attribute
+		for "rising" and "falling" edges will follow this
+		setting.
+
 GPIO controllers have paths like /sys/class/gpio/gpiochip42/ (for the
 controller implementing GPIOs starting at #42) and have the following
 read-only attributes:
@@ -566,6 +573,8 @@
 	int gpio_export_link(struct device *dev, const char *name,
 		unsigned gpio)
 
+	/* change the polarity of a GPIO node in sysfs */
+	int gpio_sysfs_set_active_low(unsigned gpio, int value);
 
 After a kernel driver requests a GPIO, it may only be made available in
 the sysfs interface by gpio_export().  The driver can control whether the
@@ -580,3 +589,9 @@
 symlinks from elsewhere in sysfs to the GPIO sysfs node.  Drivers can
 use this to provide the interface under their own device in sysfs with
 a descriptive name.
+
+Drivers can use gpio_sysfs_set_active_low() to hide GPIO line polarity
+differences between boards from user space.  This only affects the
+sysfs interface.  Polarity change can be done both before and after
+gpio_export(), and previously enabled poll(2) support for either
+rising or falling edge will be reconfigured to follow this setting.
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp
new file mode 100644
index 0000000..a7a18d4
--- /dev/null
+++ b/Documentation/hwmon/k10temp
@@ -0,0 +1,60 @@
+Kernel driver k10temp
+=====================
+
+Supported chips:
+* AMD Family 10h processors:
+  Socket F: Quad-Core/Six-Core/Embedded Opteron
+  Socket AM2+: Opteron, Phenom (II) X3/X4
+  Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
+  Socket S1G3: Athlon II, Sempron, Turion II
+* AMD Family 11h processors:
+  Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
+
+  Prefix: 'k10temp'
+  Addresses scanned: PCI space
+  Datasheets:
+  BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors:
+    http://support.amd.com/us/Processor_TechDocs/31116.pdf
+  BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41256.pdf
+  Revision Guide for AMD Family 10h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41322.pdf
+  Revision Guide for AMD Family 11h Processors:
+    http://support.amd.com/us/Processor_TechDocs/41788.pdf
+  AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
+    http://support.amd.com/us/Processor_TechDocs/43373.pdf
+  AMD Family 10h Server and Workstation Processor Power and Thermal Data Sheet:
+    http://support.amd.com/us/Processor_TechDocs/43374.pdf
+  AMD Family 10h Desktop Processor Power and Thermal Data Sheet:
+    http://support.amd.com/us/Processor_TechDocs/43375.pdf
+
+Author: Clemens Ladisch <clemens@ladisch.de>
+
+Description
+-----------
+
+This driver permits reading of the internal temperature sensor of AMD
+Family 10h and 11h processors.
+
+All these processors have a sensor, but on older revisions of Family 10h
+processors, the sensor may return inconsistent values (erratum 319). The
+driver will refuse to load on these revisions unless you specify the
+"force=1" module parameter.
+
+There is one temperature measurement value, available as temp1_input in
+sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
+Please note that it is defined as a relative value; to quote the AMD manual:
+
+  Tctl is the processor temperature control value, used by the platform to
+  control cooling systems. Tctl is a non-physical temperature on an
+  arbitrary scale measured in degrees. It does _not_ represent an actual
+  physical temperature like die or case temperature. Instead, it specifies
+  the processor temperature relative to the point at which the system must
+  supply the maximum cooling for the processor's specified maximum case
+  temperature and maximum thermal power dissipation.
+
+The maximum value for Tctl is available in the file temp1_max.
+
+If the BIOS has enabled hardware temperature control, the threshold at
+which the processor will throttle itself to avoid damage is available in
+temp1_crit and temp1_crit_hyst.
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 6d40f00..64eeb55 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -36,11 +36,11 @@
   fabric with a 2K MTU, the IPoIB MTU will be 2048 - 4 = 2044 bytes.
 
   In connected mode, the IB RC (Reliable Connected) transport is used.
-  Connected mode is to takes advantage of the connected nature of the
-  IB transport and allows an MTU up to the maximal IP packet size of
-  64K, which reduces the number of IP packets needed for handling
-  large UDP datagrams, TCP segments, etc and increases the performance
-  for large messages.
+  Connected mode takes advantage of the connected nature of the IB
+  transport and allows an MTU up to the maximal IP packet size of 64K,
+  which reduces the number of IP packets needed for handling large UDP
+  datagrams, TCP segments, etc and increases the performance for large
+  messages.
 
   In connected mode, the interface's UD QP is still used for multicast
   and communication with peers that don't support connected mode. In
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index bb3bf38..6f8c1ca 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -1,3 +1,17 @@
+Output files
+
+modules.order
+--------------------------------------------------
+This file records the order in which modules appear in Makefiles. This
+is used by modprobe to deterministically resolve aliases that match
+multiple modules.
+
+modules.builtin
+--------------------------------------------------
+This file lists all modules that are built into the kernel. This is used
+by modprobe to not fail when trying to load something builtin.
+
+
 Environment variables
 
 KCPPFLAGS
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
index 849b5e5..49efae7 100644
--- a/Documentation/kbuild/kconfig.txt
+++ b/Documentation/kbuild/kconfig.txt
@@ -103,10 +103,16 @@
 This environment variable can be set to specify the path & name of the
 "auto.conf" file.  Its default value is "include/config/auto.conf".
 
+KCONFIG_TRISTATE
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"tristate.conf" file.  Its default value is "include/config/tristate.conf".
+
 KCONFIG_AUTOHEADER
 --------------------------------------------------
 This environment variable can be set to specify the path & name of the
-"autoconf.h" (header) file.  Its default value is "include/linux/autoconf.h".
+"autoconf.h" (header) file.
+Its default value is "include/generated/autoconf.h".
 
 
 ======================================================================
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ab95d3a..5ba4d9d 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1032,7 +1032,7 @@
 			No delay
 
 	ip=		[IP_PNP]
-			See Documentation/filesystems/nfsroot.txt.
+			See Documentation/filesystems/nfs/nfsroot.txt.
 
 	ip2=		[HW] Set IO/IRQ pairs for up to 4 IntelliPort boards
 			See comment before ip2_setup() in
@@ -1553,10 +1553,10 @@
 			going to be removed in 2.6.29.
 
 	nfsaddrs=	[NFS]
-			See Documentation/filesystems/nfsroot.txt.
+			See Documentation/filesystems/nfs/nfsroot.txt.
 
 	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
-			See Documentation/filesystems/nfsroot.txt.
+			See Documentation/filesystems/nfs/nfsroot.txt.
 
 	nfs.callback_tcpport=
 			[NFS] set the TCP port on which the NFSv4 callback
@@ -2729,6 +2729,11 @@
 	vmpoff=		[KNL,S390] Perform z/VM CP command after power off.
 			Format: <command>
 
+	vt.cur_default=	[VT] Default cursor shape.
+			Format: 0xCCBBAA, where AA, BB, and CC are the same as
+			the parameters of the <Esc>[?A;B;Cc escape sequence;
+			see VGA-softcursor.txt. Default: 2 = underline.
+
 	vt.default_blu=	[VT]
 			Format: <blue0>,<blue1>,<blue2>,...,<blue15>
 			Change the default blue palette of the console.
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index aafcaa6..169091f 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
 		     ThinkPad ACPI Extras Driver
 
-                            Version 0.23
-                          April 10th, 2009
+                            Version 0.24
+                        December 11th,  2009
 
                Borislav Deianov <borislav@users.sf.net>
              Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -460,6 +460,8 @@
 				For Lenovo ThinkPads with a new
 				BIOS, it has to be handled either
 				by the ACPI OSI, or by userspace.
+				The driver does the right thing,
+				never mess with this.
 0x1011	0x10	FN+END		Brightness down.  See brightness
 				up for details.
 
@@ -582,46 +584,15 @@
 
 Brightness hotkey notes:
 
-These are the current sane choices for brightness key mapping in
-thinkpad-acpi:
+Don't mess with the brightness hotkeys in a Thinkpad.  If you want
+notifications for OSD, use the sysfs backlight class event support.
 
-For IBM and Lenovo models *without* ACPI backlight control (the ones on
-which thinkpad-acpi will autoload its backlight interface by default,
-and on which ACPI video does not export a backlight interface):
-
-1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as
-   these older firmware versions unfortunately won't respect the hotkey
-   mask for brightness keys anyway, and always reacts to them.  This
-   usually work fine, unless X.org drivers are doing something to block
-   the BIOS.  In that case, use (3) below.  This is the default mode of
-   operation.
-
-2. Enable the hotkeys, but map them to something else that is NOT
-   KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
-   userspace to try to change the backlight level, and use that as an
-   on-screen-display hint.
-
-3. IF AND ONLY IF X.org drivers find a way to block the firmware from
-   automatically changing the brightness, enable the hotkeys and map
-   them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
-   something that calls xbacklight.  thinkpad-acpi will not be able to
-   change brightness in that case either, so you should disable its
-   backlight interface.
-
-For Lenovo models *with* ACPI backlight control:
-
-1. Load up ACPI video and use that.  ACPI video will report ACPI
-   events for brightness change keys.  Do not mess with thinkpad-acpi
-   defaults in this case.  thinkpad-acpi should not have anything to do
-   with backlight events in a scenario where ACPI video is loaded:
-   brightness hotkeys must be disabled, and the backlight interface is
-   to be kept disabled as well.  This is the default mode of operation.
-
-2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
-   and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN.  Process
-   these keys on userspace somehow (e.g. by calling xbacklight).
-   The driver will do this automatically if it detects that ACPI video
-   has been disabled.
+The driver will issue KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN events
+automatically for the cases were userspace has to do something to
+implement brightness changes.  When you override these events, you will
+either fail to handle properly the ThinkPads that require explicit
+action to change backlight brightness, or the ThinkPads that require
+that no action be taken to work properly.
 
 
 Bluetooth
@@ -1121,25 +1092,61 @@
     its level up and down at every change.
 
 
-Volume control -- /proc/acpi/ibm/volume
----------------------------------------
+Volume control
+--------------
 
-This feature allows volume control on ThinkPad models which don't have
-a hardware volume knob. The available commands are:
+procfs: /proc/acpi/ibm/volume
+ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC"
+
+NOTE: by default, the volume control interface operates in read-only
+mode, as it is supposed to be used for on-screen-display purposes.
+The read/write mode can be enabled through the use of the
+"volume_control=1" module parameter.
+
+NOTE: distros are urged to not enable volume_control by default, this
+should be done by the local admin only.  The ThinkPad UI is for the
+console audio control to be done through the volume keys only, and for
+the desktop environment to just provide on-screen-display feedback.
+Software volume control should be done only in the main AC97/HDA
+mixer.
+
+This feature allows volume control on ThinkPad models with a digital
+volume knob (when available, not all models have it), as well as
+mute/unmute control.  The available commands are:
 
 	echo up   >/proc/acpi/ibm/volume
 	echo down >/proc/acpi/ibm/volume
 	echo mute >/proc/acpi/ibm/volume
+	echo unmute >/proc/acpi/ibm/volume
 	echo 'level <level>' >/proc/acpi/ibm/volume
 
-The <level> number range is 0 to 15 although not all of them may be
+The <level> number range is 0 to 14 although not all of them may be
 distinct. The unmute the volume after the mute command, use either the
-up or down command (the level command will not unmute the volume).
+up or down command (the level command will not unmute the volume), or
+the unmute command.
+
 The current volume level and mute state is shown in the file.
 
-The ALSA mixer interface to this feature is still missing, but patches
-to add it exist.  That problem should be addressed in the not so
-distant future.
+You can use the volume_capabilities parameter to tell the driver
+whether your thinkpad has volume control or mute-only control:
+volume_capabilities=1 for mixers with mute and volume control,
+volume_capabilities=2 for mixers with only mute control.
+
+If the driver misdetects the capabilities for your ThinkPad model,
+please report this to ibm-acpi-devel@lists.sourceforge.net, so that we
+can update the driver.
+
+There are two strategies for volume control.  To select which one
+should be used, use the volume_mode module parameter: volume_mode=1
+selects EC mode, and volume_mode=3 selects EC mode with NVRAM backing
+(so that volume/mute changes are remembered across shutdown/reboot).
+
+The driver will operate in volume_mode=3 by default. If that does not
+work well on your ThinkPad model, please report this to
+ibm-acpi-devel@lists.sourceforge.net.
+
+The driver supports the standard ALSA module parameters.  If the ALSA
+mixer is disabled, the driver will disable all volume functionality.
 
 
 Fan control and monitoring: fan speed, fan enable/disable
@@ -1405,6 +1412,7 @@
 	0x0008			HKEY event interface, hotkeys
 	0x0010			Fan control
 	0x0020			Backlight brightness
+	0x0040			Audio mixer/volume control
 
 There is also a kernel build option to enable more debugging
 information, which may be necessary to debug driver problems.
@@ -1465,3 +1473,9 @@
 		and it is always able to disable hot keys.  Very old
 		thinkpads are properly supported.  hotkey_bios_mask
 		is deprecated and marked for removal.
+
+0x020600:	Marker for backlight change event support.
+
+0x020700:	Support for mute-only mixers.
+		Volume control in read-only mode by default.
+		Marker for ALSA mixer support.
diff --git a/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt b/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt
new file mode 100644
index 0000000..515ebcf
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/4xx/ppc440spe-adma.txt
@@ -0,0 +1,93 @@
+PPC440SPe DMA/XOR (DMA Controller and XOR Accelerator)
+
+Device nodes needed for operation of the ppc440spe-adma driver
+are specified hereby. These are I2O/DMA, DMA and XOR nodes
+for DMA engines and Memory Queue Module node. The latter is used
+by ADMA driver for configuration of RAID-6 H/W capabilities of
+the PPC440SPe. In addition to the nodes and properties described
+below, the ranges property of PLB node must specify ranges for
+DMA devices.
+
+ i) The I2O node
+
+ Required properties:
+
+ - compatible		: "ibm,i2o-440spe";
+ - reg			: <registers mapping>
+ - dcr-reg		: <DCR registers range>
+
+ Example:
+
+	I2O: i2o@400100000 {
+		compatible = "ibm,i2o-440spe";
+		reg = <0x00000004 0x00100000 0x100>;
+		dcr-reg = <0x060 0x020>;
+	};
+
+
+ ii) The DMA node
+
+ Required properties:
+
+ - compatible		: "ibm,dma-440spe";
+ - cell-index		: 1 cell, hardware index of the DMA engine
+			  (typically 0x0 and 0x1 for DMA0 and DMA1)
+ - reg			: <registers mapping>
+ - dcr-reg		: <DCR registers range>
+ - interrupts		: <interrupt mapping for DMA0/1 interrupts sources:
+			   2 sources: DMAx CS FIFO Needs Service IRQ (on UIC0)
+			   and DMA Error IRQ (on UIC1). The latter is common
+			   for both DMA engines>.
+ - interrupt-parent	: needed for interrupt mapping
+
+ Example:
+
+	DMA0: dma0@400100100 {
+		compatible = "ibm,dma-440spe";
+		cell-index = <0>;
+		reg = <0x00000004 0x00100100 0x100>;
+		dcr-reg = <0x060 0x020>;
+		interrupt-parent = <&DMA0>;
+		interrupts = <0 1>;
+		#interrupt-cells = <1>;
+		#address-cells = <0>;
+		#size-cells = <0>;
+		interrupt-map = <
+			0 &UIC0 0x14 4
+			1 &UIC1 0x16 4>;
+	};
+
+
+ iii) XOR Accelerator node
+
+ Required properties:
+
+ - compatible		: "amcc,xor-accelerator";
+ - reg			: <registers mapping>
+ - interrupts		: <interrupt mapping for XOR interrupt source>
+ - interrupt-parent	: for interrupt mapping
+
+ Example:
+
+	xor-accel@400200000 {
+		compatible = "amcc,xor-accelerator";
+		reg = <0x00000004 0x00200000 0x400>;
+		interrupt-parent = <&UIC1>;
+		interrupts = <0x1f 4>;
+	};
+
+
+ iv) Memory Queue Module node
+
+ Required properties:
+
+ - compatible		: "ibm,mq-440spe";
+ - dcr-reg		: <DCR registers range>
+
+ Example:
+
+	MQ0: mq {
+		compatible = "ibm,mq-440spe";
+		dcr-reg = <0x040 0x020>;
+	};
+
diff --git a/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt b/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt
new file mode 100644
index 0000000..b558585
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/nintendo/gamecube.txt
@@ -0,0 +1,109 @@
+
+Nintendo GameCube device tree
+=============================
+
+1) The "flipper" node
+
+  This node represents the multi-function "Flipper" chip, which packages
+  many of the devices found in the Nintendo GameCube.
+
+  Required properties:
+
+   - compatible : Should be "nintendo,flipper"
+
+1.a) The Video Interface (VI) node
+
+  Represents the interface between the graphics processor and a external
+  video encoder.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-vi"
+   - reg : should contain the VI registers location and length
+   - interrupts : should contain the VI interrupt
+
+1.b) The Processor Interface (PI) node
+
+  Represents the data and control interface between the main processor
+  and graphics and audio processor.
+
+  Required properties:
+
+  - compatible : should be "nintendo,flipper-pi"
+  - reg : should contain the PI registers location and length
+
+1.b.i) The "Flipper" interrupt controller node
+
+  Represents the interrupt controller within the "Flipper" chip.
+  The node for the "Flipper" interrupt controller must be placed under
+  the PI node.
+
+  Required properties:
+
+  - compatible : should be "nintendo,flipper-pic"
+
+1.c) The Digital Signal Procesor (DSP) node
+
+  Represents the digital signal processor interface, designed to offload
+  audio related tasks.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-dsp"
+   - reg : should contain the DSP registers location and length
+   - interrupts : should contain the DSP interrupt
+
+1.c.i) The Auxiliary RAM (ARAM) node
+
+  Represents the non cpu-addressable ram designed mainly to store audio
+  related information.
+  The ARAM node must be placed under the DSP node.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-aram"
+   - reg : should contain the ARAM start (zero-based) and length
+
+1.d) The Disk Interface (DI) node
+
+  Represents the interface used to communicate with mass storage devices.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-di"
+   - reg : should contain the DI registers location and length
+   - interrupts : should contain the DI interrupt
+
+1.e) The Audio Interface (AI) node
+
+  Represents the interface to the external 16-bit stereo digital-to-analog
+  converter.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-ai"
+   - reg : should contain the AI registers location and length
+   - interrupts : should contain the AI interrupt
+
+1.f) The Serial Interface (SI) node
+
+  Represents the interface to the four single bit serial interfaces.
+  The SI is a proprietary serial interface used normally to control gamepads.
+  It's NOT a RS232-type interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-si"
+   - reg : should contain the SI registers location and length
+   - interrupts : should contain the SI interrupt
+
+1.g) The External Interface (EXI) node
+
+  Represents the multi-channel SPI-like interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,flipper-exi"
+   - reg : should contain the EXI registers location and length
+   - interrupts : should contain the EXI interrupt
+
diff --git a/Documentation/powerpc/dts-bindings/nintendo/wii.txt b/Documentation/powerpc/dts-bindings/nintendo/wii.txt
new file mode 100644
index 0000000..a7e155a
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/nintendo/wii.txt
@@ -0,0 +1,184 @@
+
+Nintendo Wii device tree
+========================
+
+0) The root node
+
+  This node represents the Nintendo Wii video game console.
+
+  Required properties:
+
+   - model : Should be "nintendo,wii"
+   - compatible : Should be "nintendo,wii"
+
+1) The "hollywood" node
+
+  This node represents the multi-function "Hollywood" chip, which packages
+  many of the devices found in the Nintendo Wii.
+
+  Required properties:
+
+   - compatible : Should be "nintendo,hollywood"
+
+1.a) The Video Interface (VI) node
+
+  Represents the interface between the graphics processor and a external
+  video encoder.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-vi","nintendo,flipper-vi"
+   - reg : should contain the VI registers location and length
+   - interrupts : should contain the VI interrupt
+
+1.b) The Processor Interface (PI) node
+
+  Represents the data and control interface between the main processor
+  and graphics and audio processor.
+
+  Required properties:
+
+  - compatible : should be "nintendo,hollywood-pi","nintendo,flipper-pi"
+  - reg : should contain the PI registers location and length
+
+1.b.i) The "Flipper" interrupt controller node
+
+  Represents the "Flipper" interrupt controller within the "Hollywood" chip.
+  The node for the "Flipper" interrupt controller must be placed under
+  the PI node.
+
+  Required properties:
+
+  - #interrupt-cells : <1>
+  - compatible : should be "nintendo,flipper-pic"
+  - interrupt-controller
+
+1.c) The Digital Signal Procesor (DSP) node
+
+  Represents the digital signal processor interface, designed to offload
+  audio related tasks.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-dsp","nintendo,flipper-dsp"
+   - reg : should contain the DSP registers location and length
+   - interrupts : should contain the DSP interrupt
+
+1.d) The Serial Interface (SI) node
+
+  Represents the interface to the four single bit serial interfaces.
+  The SI is a proprietary serial interface used normally to control gamepads.
+  It's NOT a RS232-type interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-si","nintendo,flipper-si"
+   - reg : should contain the SI registers location and length
+   - interrupts : should contain the SI interrupt
+
+1.e) The Audio Interface (AI) node
+
+  Represents the interface to the external 16-bit stereo digital-to-analog
+  converter.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-ai","nintendo,flipper-ai"
+   - reg : should contain the AI registers location and length
+   - interrupts : should contain the AI interrupt
+
+1.f) The External Interface (EXI) node
+
+  Represents the multi-channel SPI-like interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-exi","nintendo,flipper-exi"
+   - reg : should contain the EXI registers location and length
+   - interrupts : should contain the EXI interrupt
+
+1.g) The Open Host Controller Interface (OHCI) nodes
+
+  Represent the USB 1.x Open Host Controller Interfaces.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-usb-ohci","usb-ohci"
+   - reg : should contain the OHCI registers location and length
+   - interrupts : should contain the OHCI interrupt
+
+1.h) The Enhanced Host Controller Interface (EHCI) node
+
+  Represents the USB 2.0 Enhanced Host Controller Interface.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-usb-ehci","usb-ehci"
+   - reg : should contain the EHCI registers location and length
+   - interrupts : should contain the EHCI interrupt
+
+1.i) The Secure Digital Host Controller Interface (SDHCI) nodes
+
+  Represent the Secure Digital Host Controller Interfaces.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-sdhci","sdhci"
+   - reg : should contain the SDHCI registers location and length
+   - interrupts : should contain the SDHCI interrupt
+
+1.j) The Inter-Processsor Communication (IPC) node
+
+  Represent the Inter-Processor Communication interface. This interface
+  enables communications between the Broadway and the Starlet processors.
+
+   - compatible : should be "nintendo,hollywood-ipc"
+   - reg : should contain the IPC registers location and length
+   - interrupts : should contain the IPC interrupt
+
+1.k) The "Hollywood" interrupt controller node
+
+  Represents the "Hollywood" interrupt controller within the
+  "Hollywood" chip.
+
+  Required properties:
+
+  - #interrupt-cells : <1>
+  - compatible : should be "nintendo,hollywood-pic"
+  - reg : should contain the controller registers location and length
+  - interrupt-controller
+  - interrupts : should contain the cascade interrupt of the "flipper" pic
+  - interrupt-parent: should contain the phandle of the "flipper" pic
+
+1.l) The General Purpose I/O (GPIO) controller node
+
+  Represents the dual access 32 GPIO controller interface.
+
+  Required properties:
+
+  - #gpio-cells : <2>
+  - compatible : should be "nintendo,hollywood-gpio"
+  - reg : should contain the IPC registers location and length
+  - gpio-controller
+
+1.m) The control node
+
+  Represents the control interface used to setup several miscellaneous
+  settings of the "Hollywood" chip like boot memory mappings, resets,
+  disk interface mode, etc.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-control"
+   - reg : should contain the control registers location and length
+
+1.n) The Disk Interface (DI) node
+
+  Represents the interface used to communicate with mass storage devices.
+
+  Required properties:
+
+   - compatible : should be "nintendo,hollywood-di"
+   - reg : should contain the DI registers location and length
+   - interrupts : should contain the DI interrupt
+
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index a87dc27..cb3d15b 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -206,6 +206,7 @@
 	passive trip point for the zone. Activation is done by polling with
 	an interval of 1 second.
 	Unit: millidegrees Celsius
+	Valid values: 0 (disabled) or greater than 1000
 	RW, Optional
 
 *****************************
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
index 319d983..1800a62 100644
--- a/Documentation/video4linux/gspca.txt
+++ b/Documentation/video4linux/gspca.txt
@@ -12,6 +12,7 @@
 spca501		040a:0002	Kodak DVC-325
 spca500		040a:0300	Kodak EZ200
 zc3xx		041e:041e	Creative WebCam Live!
+ov519		041e:4003	Video Blaster WebCam Go Plus
 spca500		041e:400a	Creative PC-CAM 300
 sunplus		041e:400b	Creative PC-CAM 600
 sunplus		041e:4012	PC-Cam350
@@ -168,10 +169,14 @@
 zc3xx		055f:d003	Mustek WCam300A
 zc3xx		055f:d004	Mustek WCam300 AN
 conex		0572:0041	Creative Notebook cx11646
+ov519		05a9:0511	Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Camera
+ov519		05a9:0518	Creative WebCam
 ov519		05a9:0519	OV519 Microphone
 ov519		05a9:0530	OmniVision
+ov519		05a9:2800	OmniVision SuperCAM
 ov519		05a9:4519	Webcam Classic
 ov519		05a9:8519	OmniVision
+ov519		05a9:a511	D-Link USB Digital Video Camera
 ov519		05a9:a518	D-Link DSB-C310 Webcam
 sunplus		05da:1018	Digital Dream Enigma 1.3
 stk014		05e1:0893	Syntek DV4000
@@ -187,7 +192,7 @@
 ov534		06f8:3003	Hercules Dualpix HD Weblog
 sonixj		06f8:3004	Hercules Classic Silver
 sonixj		06f8:3008	Hercules Deluxe Optical Glass
-pac7311		06f8:3009	Hercules Classic Link
+pac7302		06f8:3009	Hercules Classic Link
 spca508		0733:0110	ViewQuest VQ110
 spca501		0733:0401	Intel Create and Share
 spca501		0733:0402	ViewQuest M318B
@@ -199,6 +204,7 @@
 sunplus		0733:3261	Concord 3045 spca536a
 sunplus		0733:3281	Cyberpix S550V
 spca506		0734:043b	3DeMon USB Capture aka
+ov519		0813:0002	Dual Mode USB Camera Plus
 spca500		084d:0003	D-Link DSC-350
 spca500		08ca:0103	Aiptek PocketDV
 sunplus		08ca:0104	Aiptek PocketDVII 1.3
@@ -236,15 +242,15 @@
 pac7311		093a:2608	Trust WB-3300p
 pac7311		093a:260e	Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
 pac7311		093a:260f	SnakeCam
-pac7311		093a:2620	Apollo AC-905
-pac7311		093a:2621	PAC731x
-pac7311		093a:2622	Genius Eye 312
-pac7311		093a:2624	PAC7302
-pac7311		093a:2626	Labtec 2200
-pac7311		093a:2628	Genius iLook 300
-pac7311		093a:2629	Genious iSlim 300
-pac7311		093a:262a	Webcam 300k
-pac7311		093a:262c	Philips SPC 230 NC
+pac7302		093a:2620	Apollo AC-905
+pac7302		093a:2621	PAC731x
+pac7302		093a:2622	Genius Eye 312
+pac7302		093a:2624	PAC7302
+pac7302		093a:2626	Labtec 2200
+pac7302		093a:2628	Genius iLook 300
+pac7302		093a:2629	Genious iSlim 300
+pac7302		093a:262a	Webcam 300k
+pac7302		093a:262c	Philips SPC 230 NC
 jeilinj		0979:0280	Sakar 57379
 zc3xx		0ac8:0302	Z-star Vimicro zc0302
 vc032x		0ac8:0321	Vimicro generic vc0321
@@ -259,6 +265,7 @@
 vc032x		0ac8:c301	Samsung Q1 Ultra Premium
 spca508		0af9:0010	Hama USB Sightcam 100
 spca508		0af9:0011	Hama USB Sightcam 100
+ov519		0b62:0059	iBOT2 Webcam
 sonixb		0c45:6001	Genius VideoCAM NB
 sonixb		0c45:6005	Microdia Sweex Mini Webcam
 sonixb		0c45:6007	Sonix sn9c101 + Tas5110D
@@ -318,8 +325,10 @@
 sn9c20x		0c45:62bb	PC Camera (SN9C202 + OV7660)
 sn9c20x		0c45:62bc	PC Camera (SN9C202 + HV7131R)
 sunplus		0d64:0303	Sunplus FashionCam DXG
+ov519		0e96:c001	TRUST 380 USB2 SPACEC@M
 etoms		102c:6151	Qcam Sangha CIF
 etoms		102c:6251	Qcam xxxxxx VGA
+ov519		1046:9967	W9967CF/W9968CF WebCam IC, Video Blaster WebCam Go
 zc3xx		10fd:0128	Typhoon Webshot II USB 300k 0x0128
 spca561		10fd:7e50	FlyCam Usb 100
 zc3xx		10fd:8050	Typhoon Webshot II USB 300k
@@ -332,7 +341,12 @@
 t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
 vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC
 pac207		2001:f115	D-Link DSB-C120
+sq905c		2770:9050	sq905c
+sq905c		2770:905c	DualCamera
+sq905		2770:9120	Argus Digital Camera DC1512
+sq905c		2770:913d	sq905c
 spca500		2899:012c	Toptro Industrial
+ov519		8020:ef04	ov519
 spca508		8086:0110	Intel Easy PC Camera
 spca500		8086:0630	Intel Pocket PC Camera
 spca506		99fa:8988	Grandtec V.cap
diff --git a/Documentation/video4linux/sh_mobile_ceu_camera.txt b/Documentation/video4linux/sh_mobile_ceu_camera.txt
new file mode 100644
index 0000000..2ae1634
--- /dev/null
+++ b/Documentation/video4linux/sh_mobile_ceu_camera.txt
@@ -0,0 +1,157 @@
+	Cropping and Scaling algorithm, used in the sh_mobile_ceu_camera driver
+	=======================================================================
+
+Terminology
+-----------
+
+sensor scales: horizontal and vertical scales, configured by the sensor driver
+host scales: -"- host driver
+combined scales: sensor_scale * host_scale
+
+
+Generic scaling / cropping scheme
+---------------------------------
+
+-1--
+|
+-2-- -\
+|      --\
+|         --\
++-5-- -\     -- -3--
+|       ---\
+|           --- -4-- -\
+|                      -\
+|                        - -6--
+|
+|                        - -6'-
+|                      -/
+|           --- -4'- -/
+|       ---/
++-5'- -/
+|            -- -3'-
+|         --/
+|      --/
+-2'- -/
+|
+|
+-1'-
+
+Produced by user requests:
+
+S_CROP(left / top = (5) - (1), width / height = (5') - (5))
+S_FMT(width / height = (6') - (6))
+
+Here:
+
+(1) to (1') - whole max width or height
+(1) to (2)  - sensor cropped left or top
+(2) to (2') - sensor cropped width or height
+(3) to (3') - sensor scale
+(3) to (4)  - CEU cropped left or top
+(4) to (4') - CEU cropped width or height
+(5) to (5') - reverse sensor scale applied to CEU cropped width or height
+(2) to (5)  - reverse sensor scale applied to CEU cropped left or top
+(6) to (6') - CEU scale - user window
+
+
+S_FMT
+-----
+
+Do not touch input rectangle - it is already optimal.
+
+1. Calculate current sensor scales:
+
+	scale_s = ((3') - (3)) / ((2') - (2))
+
+2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
+current sensor scales onto input window - this is user S_CROP:
+
+	width_u = (5') - (5) = ((4') - (4)) * scale_s
+
+3. Calculate new combined scales from "effective" input window to requested user
+window:
+
+	scale_comb = width_u / ((6') - (6))
+
+4. Calculate sensor output window by applying combined scales to real input
+window:
+
+	width_s_out = ((2') - (2)) / scale_comb
+
+5. Apply iterative sensor S_FMT for sensor output window.
+
+	subdev->video_ops->s_fmt(.width = width_s_out)
+
+6. Retrieve sensor output window (g_fmt)
+
+7. Calculate new sensor scales:
+
+	scale_s_new = ((3')_new - (3)_new) / ((2') - (2))
+
+8. Calculate new CEU crop - apply sensor scales to previously calculated
+"effective" crop:
+
+	width_ceu = (4')_new - (4)_new = width_u / scale_s_new
+	left_ceu = (4)_new - (3)_new = ((5) - (2)) / scale_s_new
+
+9. Use CEU cropping to crop to the new window:
+
+	ceu_crop(.width = width_ceu, .left = left_ceu)
+
+10. Use CEU scaling to scale to the requested user window:
+
+	scale_ceu = width_ceu / width
+
+
+S_CROP
+------
+
+If old scale applied to new crop is invalid produce nearest new scale possible
+
+1. Calculate current combined scales.
+
+	scale_comb = (((4') - (4)) / ((6') - (6))) * (((2') - (2)) / ((3') - (3)))
+
+2. Apply iterative sensor S_CROP for new input window.
+
+3. If old combined scales applied to new crop produce an impossible user window,
+adjust scales to produce nearest possible window.
+
+	width_u_out = ((5') - (5)) / scale_comb
+
+	if (width_u_out > max)
+		scale_comb = ((5') - (5)) / max;
+	else if (width_u_out < min)
+		scale_comb = ((5') - (5)) / min;
+
+4. Issue G_CROP to retrieve actual input window.
+
+5. Using actual input window and calculated combined scales calculate sensor
+target output window.
+
+	width_s_out = ((3') - (3)) = ((2') - (2)) / scale_comb
+
+6. Apply iterative S_FMT for new sensor target output window.
+
+7. Issue G_FMT to retrieve the actual sensor output window.
+
+8. Calculate sensor scales.
+
+	scale_s = ((3') - (3)) / ((2') - (2))
+
+9. Calculate sensor output subwindow to be cropped on CEU by applying sensor
+scales to the requested window.
+
+	width_ceu = ((5') - (5)) / scale_s
+
+10. Use CEU cropping for above calculated window.
+
+11. Calculate CEU scales from sensor scales from results of (10) and user window
+from (3)
+
+	scale_ceu = calc_scale(((5') - (5)), &width_u_out)
+
+12. Apply CEU scales.
+
+--
+Author: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index b806eda..74d677c 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -561,6 +561,8 @@
 
 There are a few useful helper functions:
 
+- file/video_device private data
+
 You can set/get driver private data in the video_device struct using:
 
 void *video_get_drvdata(struct video_device *vdev);
@@ -575,8 +577,7 @@
 
 returns the video_device belonging to the file struct.
 
-The final helper function combines video_get_drvdata with
-video_devdata:
+The video_drvdata function combines video_get_drvdata with video_devdata:
 
 void *video_drvdata(struct file *file);
 
@@ -584,6 +585,17 @@
 
 struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
 
+- Device node name
+
+The video_device node kernel name can be retrieved using
+
+const char *video_device_node_name(struct video_device *vdev);
+
+The name is used as a hint by userspace tools such as udev. The function
+should be used where possible instead of accessing the video_device::num and
+video_device::minor fields.
+
+
 video buffer helper functions
 -----------------------------
 
diff --git a/Documentation/vm/hwpoison.txt b/Documentation/vm/hwpoison.txt
index 3ffadf8..12f9ba2 100644
--- a/Documentation/vm/hwpoison.txt
+++ b/Documentation/vm/hwpoison.txt
@@ -92,16 +92,62 @@
 
 Testing:
 
-madvise(MADV_POISON, ....)
+madvise(MADV_HWPOISON, ....)
 	(as root)
 	Poison a page in the process for testing
 
 
 hwpoison-inject module through debugfs
-	/sys/debug/hwpoison/corrupt-pfn
 
-Inject hwpoison fault at PFN echoed into this file
+/sys/debug/hwpoison/
 
+corrupt-pfn
+
+Inject hwpoison fault at PFN echoed into this file. This does
+some early filtering to avoid corrupted unintended pages in test suites.
+
+unpoison-pfn
+
+Software-unpoison page at PFN echoed into this file. This
+way a page can be reused again.
+This only works for Linux injected failures, not for real
+memory failures.
+
+Note these injection interfaces are not stable and might change between
+kernel versions
+
+corrupt-filter-dev-major
+corrupt-filter-dev-minor
+
+Only handle memory failures to pages associated with the file system defined
+by block device major/minor.  -1U is the wildcard value.
+This should be only used for testing with artificial injection.
+
+corrupt-filter-memcg
+
+Limit injection to pages owned by memgroup. Specified by inode number
+of the memcg.
+
+Example:
+        mkdir /cgroup/hwpoison
+
+        usemem -m 100 -s 1000 &
+        echo `jobs -p` > /cgroup/hwpoison/tasks
+
+        memcg_ino=$(ls -id /cgroup/hwpoison | cut -f1 -d' ')
+        echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg
+
+        page-types -p `pidof init`   --hwpoison  # shall do nothing
+        page-types -p `pidof usemem` --hwpoison  # poison its pages
+
+corrupt-filter-flags-mask
+corrupt-filter-flags-value
+
+When specified, only poison pages if ((page_flags & mask) == value).
+This allows stress testing of many kinds of pages. The page_flags
+are the same as in /proc/kpageflags. The flag bits are defined in
+include/linux/kernel-page-flags.h and documented in
+Documentation/vm/pagemap.txt
 
 Architecture specific MCE injector
 
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index 7a7d9ba..66e9358 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -1,11 +1,22 @@
 /*
  * page-types: Tool for querying page flags
  *
+ * This program is free software; 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.
+ *
+ * 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 find a copy of v2 of the GNU General Public License somewhere on
+ * your Linux system; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
  * Copyright (C) 2009 Intel corporation
  *
  * Authors: Wu Fengguang <fengguang.wu@intel.com>
- *
- * Released under the General Public License (GPL).
  */
 
 #define _LARGEFILE64_SOURCE
diff --git a/Kbuild b/Kbuild
index f056b4f..e3737ad 100644
--- a/Kbuild
+++ b/Kbuild
@@ -8,7 +8,7 @@
 #####
 # 1) Generate bounds.h
 
-bounds-file := include/linux/bounds.h
+bounds-file := include/generated/bounds.h
 
 always  := $(bounds-file)
 targets := $(bounds-file) kernel/bounds.s
@@ -43,7 +43,7 @@
 # 2) Generate asm-offsets.h
 #
 
-offsets-file := include/asm/asm-offsets.h
+offsets-file := include/generated/asm-offsets.h
 
 always  += $(offsets-file)
 targets += $(offsets-file)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0a32c3e..efd2ef2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2377,6 +2377,15 @@
 S:	Maintained
 F:	drivers/hwmon/hdaps.c
 
+HWPOISON MEMORY FAILURE HANDLING
+M:	Andi Kleen <andi@firstfloor.org>
+L:	linux-mm@kvack.org
+L:	linux-kernel@vger.kernel.org
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
+S:	Maintained
+F:	mm/memory-failure.c
+F:	mm/hwpoison-inject.c
+
 HYPERVISOR VIRTUAL CONSOLE DRIVER
 L:	linuxppc-dev@ozlabs.org
 S:	Odd Fixes
@@ -5425,6 +5434,12 @@
 F:	include/linux/uwb.h
 F:	include/linux/uwb/
 
+UNIFDEF
+M:	Tony Finch <dot@dotat.at>
+W:	http://dotat.at/prog/unifdef
+S:	Maintained
+F:	scripts/unifdef.c
+
 UNIFORM CDROM DRIVER
 M:	Jens Axboe <axboe@kernel.dk>
 W:	http://www.kernel.dk
@@ -5991,9 +6006,9 @@
 F:	sound/soc/codecs/wm8400.*
 
 X.25 NETWORK LAYER
-M:	Henner Eisen <eis@baty.hanse.de>
+M:	Andrew Hendry <andrew.hendry@gmail.com>
 L:	linux-x25@vger.kernel.org
-S:	Maintained
+S:	Odd Fixes
 F:	Documentation/networking/x25*
 F:	include/net/x25*
 F:	net/x25/
diff --git a/Makefile b/Makefile
index 33d4732..8491b21 100644
--- a/Makefile
+++ b/Makefile
@@ -334,10 +334,9 @@
 
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
-LINUXINCLUDE    := -Iinclude \
-                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
-                   -I$(srctree)/arch/$(hdr-arch)/include               \
-                   -include include/linux/autoconf.h
+LINUXINCLUDE    := -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \
+                   $(if $(KBUILD_SRC), -I$(srctree)/include) \
+                   -include include/generated/autoconf.h
 
 KBUILD_CPPFLAGS := -D__KERNEL__
 
@@ -465,7 +464,7 @@
 # Carefully list dependencies so we do not try to build scripts twice
 # in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/auto.conf
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
 	$(Q)$(MAKE) $(build)=$(@)
 
 # Objects we will link into vmlinux / subdirs we need to visit
@@ -492,18 +491,18 @@
 # with it and forgot to run make oldconfig.
 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
-include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
 	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
-# external modules needs include/linux/autoconf.h and include/config/auto.conf
+# external modules needs include/generated/autoconf.h and include/config/auto.conf
 # but do not care if they are up-to-date. Use auto.conf to trigger the test
 PHONY += include/config/auto.conf
 
 include/config/auto.conf:
-	$(Q)test -e include/linux/autoconf.h -a -e $@ || (		\
+	$(Q)test -e include/generated/autoconf.h -a -e $@ || (		\
 	echo;								\
 	echo "  ERROR: Kernel configuration is invalid.";		\
-	echo "         include/linux/autoconf.h or $@ are missing.";	\
+	echo "         include/generated/autoconf.h or $@ are missing.";\
 	echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";	\
 	echo;								\
 	/bin/false)
@@ -877,6 +876,9 @@
 PHONY += $(vmlinux-dirs)
 $(vmlinux-dirs): prepare scripts
 	$(Q)$(MAKE) $(build)=$@
+ifdef CONFIG_MODULES
+	$(Q)$(MAKE) $(modbuiltin)=$@
+endif
 
 # Build the kernel release string
 #
@@ -955,7 +957,6 @@
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
-# 2) Create the include2 directory, used for the second asm symlink
 prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
 	@$(kecho) '  Using $(srctree) as source for kernel'
@@ -964,17 +965,13 @@
 		echo "  in the '$(srctree)' directory.";\
 		/bin/false; \
 	fi;
-	$(Q)if [ ! -d include2 ]; then                                  \
-	    mkdir -p include2;                                          \
-	    ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
-	fi
 endif
 
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile
 
-prepare1: prepare2 include/linux/version.h include/linux/utsrelease.h \
-                   include/asm include/config/auto.conf
+prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \
+                   include/config/auto.conf
 	$(cmd_crmodverdir)
 
 archprepare: prepare1 scripts_basic
@@ -986,42 +983,6 @@
 # All the preparing..
 prepare: prepare0
 
-# The asm symlink changes when $(ARCH) changes.
-# Detect this and ask user to run make mrproper
-# If asm is a stale symlink (point to dir that does not exist) remove it
-define check-symlink
-	set -e;                                                            \
-	if [ -L include/asm ]; then                                        \
-		asmlink=`readlink include/asm | cut -d '-' -f 2`;          \
-		if [ "$$asmlink" != "$(SRCARCH)" ]; then                   \
-			echo "ERROR: the symlink $@ points to asm-$$asmlink but asm-$(SRCARCH) was expected"; \
-			echo "       set ARCH or save .config and run 'make mrproper' to fix it";             \
-			exit 1;                                            \
-		fi;                                                        \
-		test -e $$asmlink || rm include/asm;                       \
-	elif [ -d include/asm ]; then                                      \
-		echo "ERROR: $@ is a directory but a symlink was expected";\
-		exit 1;                                                    \
-	fi
-endef
-
-# We create the target directory of the symlink if it does
-# not exist so the test in check-symlink works and we have a
-# directory for generated filesas used by some architectures.
-define create-symlink
-	if [ ! -L include/asm ]; then                                      \
-			$(kecho) '  SYMLINK $@ -> include/asm-$(SRCARCH)'; \
-			if [ ! -d include/asm-$(SRCARCH) ]; then           \
-				mkdir -p include/asm-$(SRCARCH);           \
-			fi;                                                \
-			ln -fsn asm-$(SRCARCH) $@;                         \
-	fi
-endef
-
-include/asm: FORCE
-	$(Q)$(check-symlink)
-	$(Q)$(create-symlink)
-
 # Generate some files
 # ---------------------------------------------------------------------------
 
@@ -1046,7 +1007,7 @@
 include/linux/version.h: $(srctree)/Makefile FORCE
 	$(call filechk,version.h)
 
-include/linux/utsrelease.h: include/config/kernel.release FORCE
+include/generated/utsrelease.h: include/config/kernel.release FORCE
 	$(call filechk,utsrelease.h)
 
 PHONY += headerdep
@@ -1076,11 +1037,6 @@
 export INSTALL_HDR_PATH = $(objtree)/usr
 
 hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj
-# Find out where the Kbuild file is located to support
-# arch/$(ARCH)/include/asm
-hdr-dir = $(strip                                                         \
-          $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild), \
-               arch/$(hdr-arch)/include/asm, include/asm-$(hdr-arch)))
 
 # If we do an all arch process set dst to asm-$(hdr-arch)
 hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
@@ -1095,10 +1051,10 @@
 
 PHONY += headers_install
 headers_install: __headers
-	$(if $(wildcard $(srctree)/$(hdr-dir)/Kbuild),, \
+	$(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \
 	$(error Headers not exportable for the $(SRCARCH) architecture))
 	$(Q)$(MAKE) $(hdr-inst)=include
-	$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst)
+	$(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -1107,7 +1063,7 @@
 PHONY += headers_check
 headers_check: headers_install
 	$(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1
-	$(Q)$(MAKE) $(hdr-inst)=$(hdr-dir) $(hdr-dst) HDRCHECK=1
+	$(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Modules
@@ -1127,6 +1083,7 @@
 PHONY += modules
 modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
+	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.builtin) > $(objtree)/modules.builtin
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild
@@ -1156,6 +1113,7 @@
 		ln -s $(objtree) $(MODLIB)/build ; \
 	fi
 	@cp -f $(objtree)/modules.order $(MODLIB)/
+	@cp -f $(objtree)/modules.builtin $(MODLIB)/
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
 
 # This depmod is only for convenience to give the initial
@@ -1194,12 +1152,10 @@
                 .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
 
 # Directories & files removed with 'make mrproper'
-MRPROPER_DIRS  += include/config include2 usr/include include/generated
-MRPROPER_FILES += .config .config.old include/asm .version .old_version \
-                  include/linux/autoconf.h include/linux/version.h      \
-                  include/linux/utsrelease.h                            \
-                  include/linux/bounds.h include/asm*/asm-offsets.h     \
-		  Module.symvers Module.markers tags TAGS cscope*
+MRPROPER_DIRS  += include/config usr/include include/generated
+MRPROPER_FILES += .config .config.old .version .old_version             \
+                  include/linux/version.h                               \
+		  Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1218,7 +1174,7 @@
 		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
 		-o -name '*.symtypes' -o -name 'modules.order' \
-		-o -name 'Module.markers' -o -name '.tmp_*.o.*' \
+		-o -name modules.builtin -o -name '.tmp_*.o.*' \
 		-o -name '*.gcno' \) -type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -1416,8 +1372,8 @@
 
 clean:	rm-dirs := $(MODVERDIR)
 clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
-                   $(KBUILD_EXTMOD)/Module.markers \
-                   $(KBUILD_EXTMOD)/modules.order
+                   $(KBUILD_EXTMOD)/modules.order \
+                   $(KBUILD_EXTMOD)/modules.builtin
 clean: $(clean-dirs)
 	$(call cmd,rmdirs)
 	$(call cmd,rmfiles)
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
index 3af21c7..3c8d1b2 100644
--- a/arch/alpha/boot/bootp.c
+++ b/arch/alpha/boot/bootp.c
@@ -9,7 +9,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
diff --git a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c
index 1036b51..ade3f12 100644
--- a/arch/alpha/boot/bootpz.c
+++ b/arch/alpha/boot/bootpz.c
@@ -11,7 +11,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
index 89f3be0..644b7db 100644
--- a/arch/alpha/boot/main.c
+++ b/arch/alpha/boot/main.c
@@ -7,7 +7,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/mm.h>
 
 #include <asm/system.h>
diff --git a/arch/alpha/include/asm/asm-offsets.h b/arch/alpha/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/alpha/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/alpha/include/asm/elf.h b/arch/alpha/include/asm/elf.h
index 5c75c1b..9baae8a 100644
--- a/arch/alpha/include/asm/elf.h
+++ b/arch/alpha/include/asm/elf.h
@@ -81,7 +81,6 @@
 #define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_ALPHA
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	8192
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h
index 21b1117..70145cb 100644
--- a/arch/alpha/include/asm/fcntl.h
+++ b/arch/alpha/include/asm/fcntl.h
@@ -16,7 +16,7 @@
 #define O_NOATIME	04000000
 #define O_CLOEXEC	010000000 /* set close_on_exec */
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fa0cdab..e9da084 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -242,15 +242,8 @@
 
 boot := arch/arm/boot
 
-#	Update machine arch and proc symlinks if something which affects
-#	them changed.  We use .arch to indicate when they were updated
-#	last, otherwise make uses the target directory mtime.
-
-archprepare: maketools
-
-PHONY += maketools FORCE
-maketools: include/linux/version.h FORCE
-	$(Q)$(MAKE) $(build)=arch/arm/tools include/asm-arm/mach-types.h
+archprepare:
+	$(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h
 
 # Convert bzImage to zImage
 bzImage: zImage
@@ -261,9 +254,6 @@
 zinstall install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-CLEAN_FILES += include/asm-arm/mach-types.h \
-	       include/asm-arm/arch include/asm-arm/.arch
-
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5a375e5..bc90364 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -308,15 +308,11 @@
 			memcpy(ptr, buf->safe, size);
 
 			/*
-			 * DMA buffers must have the same cache properties
-			 * as if they were really used for DMA - which means
-			 * data must be written back to RAM.  Note that
-			 * we don't use dmac_flush_range() here for the
-			 * bidirectional case because we know the cache
-			 * lines will be coherent with the data written.
+			 * Since we may have written to a page cache page,
+			 * we need to ensure that the data will be coherent
+			 * with user mappings.
 			 */
-			dmac_clean_range(ptr, ptr + size);
-			outer_clean_range(__pa(ptr), __pa(ptr) + size);
+			__cpuc_flush_kernel_dcache_area(ptr, size);
 		}
 		free_safe_buffer(dev->archdata.dmabounce, buf);
 	}
diff --git a/arch/arm/include/asm/asm-offsets.h b/arch/arm/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/arm/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 73eceb8..730aefc 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -211,7 +211,7 @@
 
 	void (*coherent_kern_range)(unsigned long, unsigned long);
 	void (*coherent_user_range)(unsigned long, unsigned long);
-	void (*flush_kern_dcache_page)(void *);
+	void (*flush_kern_dcache_area)(void *, size_t);
 
 	void (*dma_inv_range)(const void *, const void *);
 	void (*dma_clean_range)(const void *, const void *);
@@ -236,7 +236,7 @@
 #define __cpuc_flush_user_range		cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range	cpu_cache.coherent_kern_range
 #define __cpuc_coherent_user_range	cpu_cache.coherent_user_range
-#define __cpuc_flush_dcache_page	cpu_cache.flush_kern_dcache_page
+#define __cpuc_flush_dcache_area	cpu_cache.flush_kern_dcache_area
 
 /*
  * These are private to the dma-mapping API.  Do not use directly.
@@ -255,14 +255,14 @@
 #define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
 #define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
-#define __cpuc_flush_dcache_page	__glue(_CACHE,_flush_kern_dcache_page)
+#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
 
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
 extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
-extern void __cpuc_flush_dcache_page(void *);
+extern void __cpuc_flush_dcache_area(void *, size_t);
 
 /*
  * These are private to the dma-mapping API.  Do not use directly.
@@ -448,7 +448,7 @@
 {
 	/* highmem pages are always flushed upon kunmap already */
 	if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
-		__cpuc_flush_dcache_page(page_address(page));
+		__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 
 #define flush_dcache_mmap_lock(mapping) \
@@ -465,13 +465,6 @@
  */
 #define flush_icache_page(vma,page)	do { } while (0)
 
-static inline void flush_ioremap_region(unsigned long phys, void __iomem *virt,
-	unsigned offset, size_t size)
-{
-	const void *start = (void __force *)virt + offset;
-	dmac_inv_range(start, start + size);
-}
-
 /*
  * flush_cache_vmap() is used when creating mappings (eg, via vmap,
  * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 6aac3f5..a399bb5 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -101,7 +101,6 @@
 int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
 #define ELF_CORE_COPY_TASK_REGS dump_task_regs
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/arm/include/asm/mach-types.h b/arch/arm/include/asm/mach-types.h
new file mode 100644
index 0000000..948178c
--- /dev/null
+++ b/arch/arm/include/asm/mach-types.h
@@ -0,0 +1 @@
+#include <generated/mach-types.h>
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 0e62770..8214bfe 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -48,27 +48,7 @@
 extern void __aeabi_ulcmp(void);
 
 extern void fpundefinstr(void);
-extern void fp_enter(void);
 
-/*
- * This has a special calling convention; it doesn't
- * modify any of the usual registers, except for LR.
- */
-#define EXPORT_CRC_ALIAS(sym) __CRC_SYMBOL(sym, "")
-
-#define EXPORT_SYMBOL_ALIAS(sym,orig)		\
- EXPORT_CRC_ALIAS(sym)				\
- static const struct kernel_symbol __ksymtab_##sym	\
-  __used __attribute__((section("__ksymtab"))) =	\
-    { (unsigned long)&orig, #sym };
-
-/*
- * floating point math emulator support.
- * These symbols will never change their calling convention...
- */
-EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
-EXPORT_SYMBOL_ALIAS(fp_printk,printk);
-EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
 
 EXPORT_SYMBOL(__backtrace);
 
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 71151bd..4957e13e 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -65,11 +65,11 @@
 	__init_end = .;
 #endif
 
-	/DISCARD/ : {			/* Exit code and data		*/
-		EXIT_TEXT
-		EXIT_DATA
-		*(.exitcall.exit)
-		*(.discard)
+	/*
+	 * unwind exit sections must be discarded before the rest of the
+	 * unwind sections get included.
+	 */
+	/DISCARD/ : {
 		*(.ARM.exidx.exit.text)
 		*(.ARM.extab.exit.text)
 #ifndef CONFIG_HOTPLUG_CPU
@@ -238,6 +238,9 @@
 
 	STABS_DEBUG
 	.comment 0 : { *(.comment) }
+
+	/* Default discards */
+	DISCARDS
 }
 
 /*
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index fbe6fa0..53dd2a9 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -70,9 +70,19 @@
 	{}
 };
 
+static struct resource nand_resource[] = {
+	[0] = {
+		.start = MM_ADDR_IO_NAND,
+		.end = MM_ADDR_IO_NAND + 0x1000 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
 static struct platform_device nand_device = {
 	.name = "bcm-nand",
 	.id = -1,
+	.resource = nand_resource,
+	.num_resources	= ARRAY_SIZE(nand_resource),
 };
 
 static struct platform_device *devices[] __initdata = {
diff --git a/arch/arm/mach-bcmring/include/mach/reg_nand.h b/arch/arm/mach-bcmring/include/mach/reg_nand.h
new file mode 100644
index 0000000..387376f
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/reg_nand.h
@@ -0,0 +1,66 @@
+/*****************************************************************************
+* Copyright 2001 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/*
+*
+*****************************************************************************
+*
+*  REG_NAND.h
+*
+*  PURPOSE:
+*
+*     This file contains definitions for the nand registers:
+*
+*  NOTES:
+*
+*****************************************************************************/
+
+#if !defined(__ASM_ARCH_REG_NAND_H)
+#define __ASM_ARCH_REG_NAND_H
+
+/* ---- Include Files ---------------------------------------------------- */
+#include <csp/reg.h>
+#include <mach/reg_umi.h>
+
+/* ---- Constants and Types ---------------------------------------------- */
+
+#define HW_NAND_BASE       MM_IO_BASE_NAND	/* NAND Flash */
+
+/* DMA accesses by the bootstrap need hard nonvirtual addresses */
+#define REG_NAND_CMD            __REG16(HW_NAND_BASE + 0)
+#define REG_NAND_ADDR           __REG16(HW_NAND_BASE + 4)
+
+#define REG_NAND_PHYS_DATA16   (HW_NAND_BASE + 8)
+#define REG_NAND_PHYS_DATA8    (HW_NAND_BASE + 8)
+#define REG_NAND_DATA16         __REG16(REG_NAND_PHYS_DATA16)
+#define REG_NAND_DATA8          __REG8(REG_NAND_PHYS_DATA8)
+
+/* use appropriate offset to make sure it start at the 1K boundary */
+#define REG_NAND_PHYS_DATA_DMA   (HW_NAND_BASE + 0x400)
+#define REG_NAND_DATA_DMA         __REG32(REG_NAND_PHYS_DATA_DMA)
+
+/* Linux DMA requires physical address of the data register */
+#define REG_NAND_DATA16_PADDR    HW_IO_VIRT_TO_PHYS(REG_NAND_PHYS_DATA16)
+#define REG_NAND_DATA8_PADDR     HW_IO_VIRT_TO_PHYS(REG_NAND_PHYS_DATA8)
+#define REG_NAND_DATA_PADDR      HW_IO_VIRT_TO_PHYS(REG_NAND_PHYS_DATA_DMA)
+
+#define NAND_BUS_16BIT()        (0)
+#define NAND_BUS_8BIT()         (!NAND_BUS_16BIT())
+
+/* Register offsets */
+#define REG_NAND_CMD_OFFSET     (0)
+#define REG_NAND_ADDR_OFFSET    (4)
+#define REG_NAND_DATA8_OFFSET   (8)
+
+#endif
diff --git a/arch/arm/mach-bcmring/include/mach/reg_umi.h b/arch/arm/mach-bcmring/include/mach/reg_umi.h
new file mode 100644
index 0000000..06a3554
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/reg_umi.h
@@ -0,0 +1,237 @@
+/*****************************************************************************
+* Copyright 2005 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/*
+*
+*****************************************************************************
+*
+*  REG_UMI.h
+*
+*  PURPOSE:
+*
+*     This file contains definitions for the nand registers:
+*
+*  NOTES:
+*
+*****************************************************************************/
+
+#if !defined(__ASM_ARCH_REG_UMI_H)
+#define __ASM_ARCH_REG_UMI_H
+
+/* ---- Include Files ---------------------------------------------------- */
+#include <csp/reg.h>
+#include <mach/csp/mm_io.h>
+
+/* ---- Constants and Types ---------------------------------------------- */
+
+/* Unified Memory Interface Ctrl Register */
+#define HW_UMI_BASE       MM_IO_BASE_UMI
+
+/* Flash bank 0 timing and control register */
+#define REG_UMI_FLASH0_TCR         __REG32(HW_UMI_BASE  + 0x00)
+/* Flash bank 1 timing and control register */
+#define REG_UMI_FLASH1_TCR         __REG32(HW_UMI_BASE  + 0x04)
+/* Flash bank 2 timing and control register */
+#define REG_UMI_FLASH2_TCR         __REG32(HW_UMI_BASE  + 0x08)
+/* MMD interface and control register */
+#define REG_UMI_MMD_ICR            __REG32(HW_UMI_BASE  + 0x0c)
+/* NAND timing and control register */
+#define REG_UMI_NAND_TCR           __REG32(HW_UMI_BASE  + 0x18)
+/* NAND ready/chip select register */
+#define REG_UMI_NAND_RCSR          __REG32(HW_UMI_BASE  + 0x1c)
+/* NAND ECC control & status register */
+#define REG_UMI_NAND_ECC_CSR       __REG32(HW_UMI_BASE  + 0x20)
+/* NAND ECC data register XXB2B1B0 */
+#define REG_UMI_NAND_ECC_DATA      __REG32(HW_UMI_BASE  + 0x24)
+/* BCH ECC Parameter N */
+#define REG_UMI_BCH_N              __REG32(HW_UMI_BASE  + 0x40)
+/* BCH ECC Parameter T */
+#define REG_UMI_BCH_K              __REG32(HW_UMI_BASE  + 0x44)
+/* BCH ECC Parameter K */
+#define REG_UMI_BCH_T              __REG32(HW_UMI_BASE  + 0x48)
+/* BCH ECC Contro Status */
+#define REG_UMI_BCH_CTRL_STATUS    __REG32(HW_UMI_BASE  + 0x4C)
+/* BCH WR ECC 31:0 */
+#define REG_UMI_BCH_WR_ECC_0       __REG32(HW_UMI_BASE  + 0x50)
+/* BCH WR ECC 63:32 */
+#define REG_UMI_BCH_WR_ECC_1       __REG32(HW_UMI_BASE  + 0x54)
+/* BCH WR ECC 95:64 */
+#define REG_UMI_BCH_WR_ECC_2       __REG32(HW_UMI_BASE  + 0x58)
+/* BCH WR ECC 127:96 */
+#define REG_UMI_BCH_WR_ECC_3       __REG32(HW_UMI_BASE  + 0x5c)
+/* BCH WR ECC 155:128 */
+#define REG_UMI_BCH_WR_ECC_4       __REG32(HW_UMI_BASE  + 0x60)
+/* BCH Read Error Location 1,0 */
+#define REG_UMI_BCH_RD_ERR_LOC_1_0 __REG32(HW_UMI_BASE  + 0x64)
+/* BCH Read Error Location 3,2 */
+#define REG_UMI_BCH_RD_ERR_LOC_3_2 __REG32(HW_UMI_BASE  + 0x68)
+/* BCH Read Error Location 5,4 */
+#define REG_UMI_BCH_RD_ERR_LOC_5_4 __REG32(HW_UMI_BASE  + 0x6c)
+/* BCH Read Error Location 7,6 */
+#define REG_UMI_BCH_RD_ERR_LOC_7_6 __REG32(HW_UMI_BASE  + 0x70)
+/* BCH Read Error Location 9,8 */
+#define REG_UMI_BCH_RD_ERR_LOC_9_8 __REG32(HW_UMI_BASE  + 0x74)
+/* BCH Read Error Location 11,10 */
+#define REG_UMI_BCH_RD_ERR_LOC_B_A __REG32(HW_UMI_BASE  + 0x78)
+
+/* REG_UMI_FLASH0/1/2_TCR, REG_UMI_SRAM0/1_TCR bits */
+/* Enable wait pin during burst write or read */
+#define REG_UMI_TCR_WAITEN              0x80000000
+/* Enable mem ctrlr to work iwth ext mem of lower freq than AHB clk */
+#define REG_UMI_TCR_LOWFREQ             0x40000000
+/* 1=synch write, 0=async write */
+#define REG_UMI_TCR_MEMTYPE_SYNCWRITE   0x20000000
+/* 1=synch read, 0=async read */
+#define REG_UMI_TCR_MEMTYPE_SYNCREAD    0x10000000
+/* 1=page mode read, 0=normal mode read */
+#define REG_UMI_TCR_MEMTYPE_PAGEREAD    0x08000000
+/* page size/burst size (wrap only) */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_MASK   0x07000000
+/* 4 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_4      0x00000000
+/* 8 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_8      0x01000000
+/* 16 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_16     0x02000000
+/* 32 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_32     0x03000000
+/* 64 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_64     0x04000000
+/* 128 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_128    0x05000000
+/* 256 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_256    0x06000000
+/* 512 word */
+#define REG_UMI_TCR_MEMTYPE_PGSZ_512    0x07000000
+/* Page read access cycle / Burst write latency (n+2 / n+1) */
+#define REG_UMI_TCR_TPRC_TWLC_MASK      0x00f80000
+/* Bus turnaround cycle (n) */
+#define REG_UMI_TCR_TBTA_MASK           0x00070000
+/* Write pulse width cycle (n+1) */
+#define REG_UMI_TCR_TWP_MASK            0x0000f800
+/* Write recovery cycle (n+1) */
+#define REG_UMI_TCR_TWR_MASK            0x00000600
+/* Write address setup cycle (n+1) */
+#define REG_UMI_TCR_TAS_MASK            0x00000180
+/* Output enable delay cycle (n) */
+#define REG_UMI_TCR_TOE_MASK            0x00000060
+/* Read access cycle / Burst read latency (n+2 / n+1) */
+#define REG_UMI_TCR_TRC_TLC_MASK        0x0000001f
+
+/* REG_UMI_MMD_ICR bits */
+/* Flash write protection pin control */
+#define REG_UMI_MMD_ICR_FLASH_WP            0x8000
+/* Extend hold time for sram0, sram1 csn (39 MHz operation) */
+#define REG_UMI_MMD_ICR_XHCS                0x4000
+/* Enable SDRAM 2 interface control */
+#define REG_UMI_MMD_ICR_SDRAM2EN            0x2000
+/* Enable merge of flash banks 0/1 to 512 MBit bank */
+#define REG_UMI_MMD_ICR_INST512             0x1000
+/* Enable merge of flash banks 1/2 to 512 MBit bank */
+#define REG_UMI_MMD_ICR_DATA512             0x0800
+/* Enable SDRAM interface control */
+#define REG_UMI_MMD_ICR_SDRAMEN             0x0400
+/* Polarity of busy state of Burst Wait Signal */
+#define REG_UMI_MMD_ICR_WAITPOL             0x0200
+/* Enable burst clock stopped when not accessing external burst flash/sram */
+#define REG_UMI_MMD_ICR_BCLKSTOP            0x0100
+/* Enable the peri1_csn to replace flash1_csn in 512 Mb flash mode */
+#define REG_UMI_MMD_ICR_PERI1EN             0x0080
+/* Enable the peri2_csn to replace sdram_csn */
+#define REG_UMI_MMD_ICR_PERI2EN             0x0040
+/* Enable the peri3_csn to replace sdram2_csn */
+#define REG_UMI_MMD_ICR_PERI3EN             0x0020
+/* Enable sram bank1 for H/W controlled MRS */
+#define REG_UMI_MMD_ICR_MRSB1               0x0010
+/* Enable sram bank0 for H/W controlled MRS */
+#define REG_UMI_MMD_ICR_MRSB0               0x0008
+/* Polarity for assert3ed state of H/W controlled MRS */
+#define REG_UMI_MMD_ICR_MRSPOL              0x0004
+/* 0: S/W controllable ZZ/MRS/CRE/P-Mode pin */
+/* 1: H/W controlled ZZ/MRS/CRE/P-Mode, same timing as CS */
+#define REG_UMI_MMD_ICR_MRSMODE             0x0002
+/* MRS state for S/W controlled mode */
+#define REG_UMI_MMD_ICR_MRSSTATE            0x0001
+
+/* REG_UMI_NAND_TCR bits */
+/* Enable software to control CS */
+#define REG_UMI_NAND_TCR_CS_SWCTRL          0x80000000
+/* 16-bit nand wordsize if set */
+#define REG_UMI_NAND_TCR_WORD16             0x40000000
+/* Bus turnaround cycle (n) */
+#define REG_UMI_NAND_TCR_TBTA_MASK          0x00070000
+/* Write pulse width cycle (n+1) */
+#define REG_UMI_NAND_TCR_TWP_MASK           0x0000f800
+/* Write recovery cycle (n+1) */
+#define REG_UMI_NAND_TCR_TWR_MASK           0x00000600
+/* Write address setup cycle (n+1) */
+#define REG_UMI_NAND_TCR_TAS_MASK           0x00000180
+/* Output enable delay cycle (n) */
+#define REG_UMI_NAND_TCR_TOE_MASK           0x00000060
+/* Read access cycle (n+2) */
+#define REG_UMI_NAND_TCR_TRC_TLC_MASK       0x0000001f
+
+/* REG_UMI_NAND_RCSR bits */
+/* Status: Ready=1, Busy=0 */
+#define REG_UMI_NAND_RCSR_RDY               0x02
+/* Keep CS asserted during operation */
+#define REG_UMI_NAND_RCSR_CS_ASSERTED       0x01
+
+/* REG_UMI_NAND_ECC_CSR bits */
+/* Interrupt status - read-only */
+#define REG_UMI_NAND_ECC_CSR_NANDINT        0x80000000
+/* Read: Status of ECC done, Write: clear ECC interrupt */
+#define REG_UMI_NAND_ECC_CSR_ECCINT_RAW     0x00800000
+/* Read: Status of R/B, Write: clear R/B interrupt */
+#define REG_UMI_NAND_ECC_CSR_RBINT_RAW      0x00400000
+/* 1 = Enable ECC Interrupt */
+#define REG_UMI_NAND_ECC_CSR_ECCINT_ENABLE  0x00008000
+/* 1 = Assert interrupt at rising edge of R/B_ */
+#define REG_UMI_NAND_ECC_CSR_RBINT_ENABLE   0x00004000
+/* Calculate ECC by 0=512 bytes, 1=256 bytes */
+#define REG_UMI_NAND_ECC_CSR_256BYTE        0x00000080
+/* Enable ECC in hardware */
+#define REG_UMI_NAND_ECC_CSR_ECC_ENABLE     0x00000001
+
+/* REG_UMI_BCH_CTRL_STATUS bits */
+/* Shift to Indicate Number of correctable errors detected */
+#define REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR_SHIFT 20
+/* Indicate Number of correctable errors detected */
+#define REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR 0x00F00000
+/* Indicate Errors detected during read but uncorrectable */
+#define REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR    0x00080000
+/* Indicate Errors detected during read and are correctable */
+#define REG_UMI_BCH_CTRL_STATUS_CORR_ERR      0x00040000
+/* Flag indicates BCH's ECC status of read process are valid */
+#define REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID  0x00020000
+/* Flag indicates BCH's ECC status of write process are valid */
+#define REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID  0x00010000
+/* Pause ECC calculation */
+#define REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC 0x00000010
+/* Enable Interrupt */
+#define REG_UMI_BCH_CTRL_STATUS_INT_EN        0x00000004
+/* Enable ECC during read */
+#define REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN     0x00000002
+/* Enable ECC during write */
+#define REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN     0x00000001
+/* Mask for location */
+#define REG_UMI_BCH_ERR_LOC_MASK              0x00001FFF
+/* location within a byte */
+#define REG_UMI_BCH_ERR_LOC_BYTE              0x00000007
+/* location within a word */
+#define REG_UMI_BCH_ERR_LOC_WORD              0x00000018
+/* location within a page (512 byte) */
+#define REG_UMI_BCH_ERR_LOC_PAGE              0x00001FE0
+#define REG_UMI_BCH_ERR_LOC_ADDR(index)     (__REG32(HW_UMI_BASE + 0x64 + (index / 2)*4) >> ((index % 2) * 16))
+#endif
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 62b98bf..07de8db 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -339,6 +339,15 @@
 	.version	= MMC_CTLR_VERSION_2,
 };
 
+static void da850_panel_power_ctrl(int val)
+{
+	/* lcd backlight */
+	gpio_set_value(DA850_LCD_BL_PIN, val);
+
+	/* lcd power */
+	gpio_set_value(DA850_LCD_PWR_PIN, val);
+}
+
 static int da850_lcd_hw_init(void)
 {
 	int status;
@@ -356,17 +365,11 @@
 	gpio_direction_output(DA850_LCD_BL_PIN, 0);
 	gpio_direction_output(DA850_LCD_PWR_PIN, 0);
 
-	/* disable lcd backlight */
-	gpio_set_value(DA850_LCD_BL_PIN, 0);
+	/* Switch off panel power and backlight */
+	da850_panel_power_ctrl(0);
 
-	/* disable lcd power */
-	gpio_set_value(DA850_LCD_PWR_PIN, 0);
-
-	/* enable lcd power */
-	gpio_set_value(DA850_LCD_PWR_PIN, 1);
-
-	/* enable lcd backlight */
-	gpio_set_value(DA850_LCD_BL_PIN, 1);
+	/* Switch on panel power and backlight */
+	da850_panel_power_ctrl(1);
 
 	return 0;
 }
@@ -674,6 +677,7 @@
 		pr_warning("da850_evm_init: lcd initialization failed: %d\n",
 				ret);
 
+	sharp_lk043t1dg01_pdata.panel_power_ctrl = da850_panel_power_ctrl,
 	ret = da8xx_register_lcdc(&sharp_lk043t1dg01_pdata);
 	if (ret)
 		pr_warning("da850_evm_init: lcdc registration failed: %d\n",
diff --git a/arch/arm/mach-davinci/include/mach/nand.h b/arch/arm/mach-davinci/include/mach/nand.h
index b520c4b..b2ad809 100644
--- a/arch/arm/mach-davinci/include/mach/nand.h
+++ b/arch/arm/mach-davinci/include/mach/nand.h
@@ -79,6 +79,10 @@
 
 	/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
 	unsigned		options;
+
+	/* Main and mirror bbt descriptor overrides */
+	struct nand_bbt_descr	*bbt_td;
+	struct nand_bbt_descr	*bbt_md;
 };
 
 #endif	/* __ARCH_ARM_DAVINCI_NAND_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
index 83f31cd..62d1742 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
@@ -5,9 +5,6 @@
 #ifndef __ASM_ARCH_EP93XX_KEYPAD_H
 #define __ASM_ARCH_EP93XX_KEYPAD_H
 
-#define MAX_MATRIX_KEY_ROWS		(8)
-#define MAX_MATRIX_KEY_COLS		(8)
-
 /* flags for the ep93xx_keypad driver */
 #define EP93XX_KEYPAD_DISABLE_3_KEY	(1<<0)	/* disable 3-key reset */
 #define EP93XX_KEYPAD_DIAG_MODE		(1<<1)	/* diagnostic mode */
@@ -18,8 +15,6 @@
 
 /**
  * struct ep93xx_keypad_platform_data - platform specific device structure
- * @matrix_key_rows:		number of rows in the keypad matrix
- * @matrix_key_cols:		number of columns in the keypad matrix
  * @matrix_key_map:		array of keycodes defining the keypad matrix
  * @matrix_key_map_size:	ARRAY_SIZE(matrix_key_map)
  * @debounce:			debounce start count; terminal count is 0xff
@@ -27,8 +22,6 @@
  * @flags:			see above
  */
 struct ep93xx_keypad_platform_data {
-	unsigned int	matrix_key_rows;
-	unsigned int	matrix_key_cols;
 	unsigned int	*matrix_key_map;
 	int		matrix_key_map_size;
 	unsigned int	debounce;
@@ -36,7 +29,7 @@
 	unsigned int	flags;
 };
 
-/* macro for creating the matrix_key_map table */
-#define KEY(row, col, val)	(((row) << 28) | ((col) << 24) | (val))
+#define EP93XX_MATRIX_ROWS		(8)
+#define EP93XX_MATRIX_COLS		(8)
 
 #endif	/* __ASM_ARCH_EP93XX_KEYPAD_H */
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 8bf09ae..f6c6196 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -52,6 +52,12 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell OpenRD Base Board.
 
+config MACH_NETSPACE_V2
+	bool "LaCie Network Space v2 NAS Board"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  LaCie Network Space v2 NAS.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 9f2f67b..d4d7f53 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -8,5 +8,6 @@
 obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_TS41X)		+= ts41x-setup.o tsx1x-common.o
 obj-$(CONFIG_MACH_OPENRD_BASE)		+= openrd_base-setup.o
+obj-$(CONFIG_MACH_NETSPACE_V2)		+= netspace_v2-setup.o
 
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
new file mode 100644
index 0000000..9a06406
--- /dev/null
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -0,0 +1,325 @@
+/*
+ * arch/arm/mach-kirkwood/netspace_v2-setup.c
+ *
+ * LaCie Network Space v2 board setup
+ *
+ * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com>
+ * Copyright (C) 2009 Benoît Canet <benoit.canet@gmail.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/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/kirkwood.h>
+#include <plat/time.h>
+#include "common.h"
+#include "mpp.h"
+
+/*****************************************************************************
+ * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005)
+ ****************************************************************************/
+
+static struct mtd_partition netspace_v2_flash_parts[] = {
+	{
+		.name = "u-boot",
+		.size = MTDPART_SIZ_FULL,
+		.offset = 0,
+		.mask_flags = MTD_WRITEABLE, /* force read-only */
+	},
+};
+
+static const struct flash_platform_data netspace_v2_flash = {
+	.type		= "mx25l4005a",
+	.name		= "spi_flash",
+	.parts		= netspace_v2_flash_parts,
+	.nr_parts	= ARRAY_SIZE(netspace_v2_flash_parts),
+};
+
+static struct spi_board_info __initdata netspace_v2_spi_slave_info[] = {
+	{
+		.modalias	= "m25p80",
+		.platform_data	= &netspace_v2_flash,
+		.irq		= -1,
+		.max_speed_hz	= 20000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+	},
+};
+
+/*****************************************************************************
+ * Ethernet
+ ****************************************************************************/
+
+static struct mv643xx_eth_platform_data netspace_v2_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+/*****************************************************************************
+ * I2C devices
+ ****************************************************************************/
+
+static struct at24_platform_data at24c04 = {
+	.byte_len	= SZ_4K / 8,
+	.page_size	= 16,
+};
+
+/*
+ * i2c addr | chip         | description
+ * 0x50     | HT24LC04     | eeprom (512B)
+ */
+
+static struct i2c_board_info __initdata netspace_v2_i2c_info[] = {
+	{
+		I2C_BOARD_INFO("24c04", 0x50),
+		.platform_data  = &at24c04,
+	}
+};
+
+/*****************************************************************************
+ * SATA
+ ****************************************************************************/
+
+static struct mv_sata_platform_data netspace_v2_sata_data = {
+	.n_ports	= 2,
+};
+
+#define NETSPACE_V2_GPIO_SATA0_POWER	16
+#define NETSPACE_V2_GPIO_SATA1_POWER	17
+
+static void __init netspace_v2_sata_power_init(void)
+{
+	int err;
+
+	err = gpio_request(NETSPACE_V2_GPIO_SATA0_POWER, "SATA0 power");
+	if (err == 0) {
+		err = gpio_direction_output(NETSPACE_V2_GPIO_SATA0_POWER, 1);
+		if (err)
+			gpio_free(NETSPACE_V2_GPIO_SATA0_POWER);
+	}
+	if (err)
+		pr_err("netspace_v2: failed to setup SATA0 power\n");
+}
+
+/*****************************************************************************
+ * GPIO keys
+ ****************************************************************************/
+
+#define NETSPACE_V2_PUSH_BUTTON		32
+
+static struct gpio_keys_button netspace_v2_buttons[] = {
+	[0] = {
+		.code		= KEY_POWER,
+		.gpio		= NETSPACE_V2_PUSH_BUTTON,
+		.desc		= "Power push button",
+		.active_low	= 0,
+	},
+};
+
+static struct gpio_keys_platform_data netspace_v2_button_data = {
+	.buttons	= netspace_v2_buttons,
+	.nbuttons	= ARRAY_SIZE(netspace_v2_buttons),
+};
+
+static struct platform_device netspace_v2_gpio_buttons = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data 	= &netspace_v2_button_data,
+	},
+};
+
+/*****************************************************************************
+ * GPIO LEDs
+ ****************************************************************************/
+
+/*
+ * The blue front LED is wired to a CPLD and can blink in relation with the
+ * SATA activity.
+ *
+ * The following array detail the different LED registers and the combination
+ * of their possible values:
+ *
+ *  cmd_led   |  slow_led  | /SATA active | LED state
+ *            |            |              |
+ *     1      |     0      |      x       |  off
+ *     -      |     1      |      x       |  on
+ *     0      |     0      |      1       |  on
+ *     0      |     0      |      0       |  blink (rate 300ms)
+ */
+
+#define NETSPACE_V2_GPIO_RED_LED	12
+#define NETSPACE_V2_GPIO_BLUE_LED_SLOW	29
+#define NETSPACE_V2_GPIO_BLUE_LED_CMD	30
+
+
+static struct gpio_led netspace_v2_gpio_led_pins[] = {
+	{
+		.name	= "ns_v2:red:fail",
+		.gpio	= NETSPACE_V2_GPIO_RED_LED,
+	},
+};
+
+static struct gpio_led_platform_data netspace_v2_gpio_leds_data = {
+	.num_leds	= ARRAY_SIZE(netspace_v2_gpio_led_pins),
+	.leds		= netspace_v2_gpio_led_pins,
+};
+
+static struct platform_device netspace_v2_gpio_leds = {
+	.name		= "leds-gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &netspace_v2_gpio_leds_data,
+	},
+};
+
+static void __init netspace_v2_gpio_leds_init(void)
+{
+	platform_device_register(&netspace_v2_gpio_leds);
+
+	/*
+	 * Configure the front blue LED to blink in relation with the SATA
+	 * activity.
+	 */
+	if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_SLOW,
+			 "SATA blue LED slow") != 0)
+		return;
+	if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_SLOW, 0) != 0)
+		goto err_free_1;
+	if (gpio_request(NETSPACE_V2_GPIO_BLUE_LED_CMD,
+			 "SATA blue LED command") != 0)
+		goto err_free_1;
+	if (gpio_direction_output(NETSPACE_V2_GPIO_BLUE_LED_CMD, 0) != 0)
+		goto err_free_2;
+
+	return;
+
+err_free_2:
+	gpio_free(NETSPACE_V2_GPIO_BLUE_LED_CMD);
+err_free_1:
+	gpio_free(NETSPACE_V2_GPIO_BLUE_LED_SLOW);
+	pr_err("netspace_v2: failed to configure SATA blue LED\n");
+}
+
+/*****************************************************************************
+ * Timer
+ ****************************************************************************/
+
+static void netspace_v2_timer_init(void)
+{
+	kirkwood_tclk = 166666667;
+	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+}
+
+struct sys_timer netspace_v2_timer = {
+	.init = netspace_v2_timer_init,
+};
+
+/*****************************************************************************
+ * General Setup
+ ****************************************************************************/
+
+static unsigned int netspace_v2_mpp_config[] __initdata = {
+	MPP0_SPI_SCn,
+	MPP1_SPI_MOSI,
+	MPP2_SPI_SCK,
+	MPP3_SPI_MISO,
+	MPP4_NF_IO6,
+	MPP5_NF_IO7,
+	MPP6_SYSRST_OUTn,
+	MPP8_TW_SDA,
+	MPP9_TW_SCK,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP12_GPO,		/* Red led */
+	MPP14_GPIO,		/* USB fuse */
+	MPP16_GPIO,		/* SATA 0 power */
+	MPP18_NF_IO0,
+	MPP19_NF_IO1,
+	MPP20_SATA1_ACTn,
+	MPP21_SATA0_ACTn,
+	MPP24_GPIO,		/* USB mode select */
+	MPP25_GPIO,		/* Fan rotation fail */
+	MPP26_GPIO,		/* USB device vbus */
+	MPP28_GPIO,		/* USB enable host vbus */
+	MPP29_GPIO,		/* Blue led (slow register) */
+	MPP30_GPIO,		/* Blue led (command register) */
+	MPP31_GPIO,		/* Board power off */
+	MPP32_GPIO, 		/* Power button (0 = Released, 1 = Pushed) */
+	0
+};
+
+#define NETSPACE_V2_GPIO_POWER_OFF	31
+
+static void netspace_v2_power_off(void)
+{
+	gpio_set_value(NETSPACE_V2_GPIO_POWER_OFF, 1);
+}
+
+static void __init netspace_v2_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(netspace_v2_mpp_config);
+
+	netspace_v2_sata_power_init();
+
+	kirkwood_ehci_init();
+	kirkwood_ge00_init(&netspace_v2_ge00_data);
+	kirkwood_sata_init(&netspace_v2_sata_data);
+	kirkwood_uart0_init();
+	spi_register_board_info(netspace_v2_spi_slave_info,
+				ARRAY_SIZE(netspace_v2_spi_slave_info));
+	kirkwood_spi_init();
+	kirkwood_i2c_init();
+	i2c_register_board_info(0, netspace_v2_i2c_info,
+				ARRAY_SIZE(netspace_v2_i2c_info));
+
+	netspace_v2_gpio_leds_init();
+	platform_device_register(&netspace_v2_gpio_buttons);
+
+	if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
+	    gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
+		pm_power_off = netspace_v2_power_off;
+	else
+		pr_err("netspace_v2: failed to configure power-off GPIO\n");
+}
+
+MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= netspace_v2_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &netspace_v2_timer,
+MACHINE_END
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 1163944..9438bf6 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <asm/sizes.h>
@@ -149,7 +150,7 @@
 	}
 };
 
-static struct flash_platform_data nhk8815_onenand_data = {
+static struct onenand_platform_data nhk8815_onenand_data = {
 	.parts		= nhk8815_onenand_partitions,
 	.nr_parts	= ARRAY_SIZE(nhk8815_onenand_partitions),
 };
@@ -163,7 +164,7 @@
 };
 
 static struct platform_device nhk8815_onenand_device = {
-	.name		= "onenand",
+	.name		= "onenand-flash",
 	.id		= -1,
 	.dev		= {
 		.platform_data	= &nhk8815_onenand_data,
@@ -174,10 +175,10 @@
 
 static void __init nhk8815_onenand_init(void)
 {
-#ifdef CONFIG_ONENAND
+#ifdef CONFIG_MTD_ONENAND
        /* Set up SMCS0 for OneNand */
-       writel(0x000030db, FSMC_BCR0);
-       writel(0x02100551, FSMC_BTR0);
+	writel(0x000030db, FSMC_BCR(0));
+	writel(0x02100551, FSMC_BTR(0));
 #endif
 }
 
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index e6d8e10..8a0837e 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -110,6 +110,8 @@
 	bool "CompuLab CM-X300 modules"
 	select PXA3xx
 	select CPU_PXA300
+	select CPU_PXA310
+	select HAVE_PWM
 
 config ARCH_GUMSTIX
 	bool "Gumstix XScale 255 boards"
@@ -240,7 +242,6 @@
 	select PXA3xx
 	select CPU_PXA300
 	select CPU_PXA310
-	select HAVE_PWM
 
 config MACH_COLIBRI320
 	bool "Toradex Colibri PXA320"
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 3395463..8e10db1 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -4,7 +4,6 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 
-#include <mach/hardware.h>
 #include <mach/udc.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
@@ -14,6 +13,7 @@
 #include <mach/pxa2xx_spi.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
+#include <mach/hardware.h>
 #include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
diff --git a/arch/arm/mach-s3c2410/include/mach/spi.h b/arch/arm/mach-s3c2410/include/mach/spi.h
index 193b39d..4d95883 100644
--- a/arch/arm/mach-s3c2410/include/mach/spi.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi.h
@@ -18,6 +18,8 @@
 	unsigned int		 num_cs;	/* total chipselects */
 	int			 bus_num;       /* bus number to use. */
 
+	unsigned int		 use_fiq:1;	/* use fiq */
+
 	void (*gpio_setup)(struct s3c2410_spi_info *spi, int enable);
 	void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
diff --git a/arch/arm/mach-u300/include/mach/coh901318.h b/arch/arm/mach-u300/include/mach/coh901318.h
new file mode 100644
index 0000000..f4cfee9
--- /dev/null
+++ b/arch/arm/mach-u300/include/mach/coh901318.h
@@ -0,0 +1,281 @@
+/*
+ *
+ * include/linux/coh901318.h
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * DMA driver for COH 901 318
+ * Author: Per Friden <per.friden@stericsson.com>
+ */
+
+#ifndef COH901318_H
+#define COH901318_H
+
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+
+#define MAX_DMA_PACKET_SIZE_SHIFT 11
+#define MAX_DMA_PACKET_SIZE (1 << MAX_DMA_PACKET_SIZE_SHIFT)
+
+/**
+ * struct coh901318_lli - linked list item for DMAC
+ * @control: control settings for DMAC
+ * @src_addr: transfer source address
+ * @dst_addr: transfer destination address
+ * @link_addr:  physical address to next lli
+ * @virt_link_addr: virtual addres of next lli (only used by pool_free)
+ * @phy_this: physical address of current lli (only used by pool_free)
+ */
+struct coh901318_lli {
+	u32 control;
+	dma_addr_t src_addr;
+	dma_addr_t dst_addr;
+	dma_addr_t link_addr;
+
+	void *virt_link_addr;
+	dma_addr_t phy_this;
+};
+/**
+ * struct coh901318_params - parameters for DMAC configuration
+ * @config: DMA config register
+ * @ctrl_lli_last: DMA control register for the last lli in the list
+ * @ctrl_lli: DMA control register for an lli
+ * @ctrl_lli_chained: DMA control register for a chained lli
+ */
+struct coh901318_params {
+	u32 config;
+	u32 ctrl_lli_last;
+	u32 ctrl_lli;
+	u32 ctrl_lli_chained;
+};
+/**
+ * struct coh_dma_channel - dma channel base
+ * @name: ascii name of dma channel
+ * @number: channel id number
+ * @desc_nbr_max: number of preallocated descriptortors
+ * @priority_high: prio of channel, 0 low otherwise high.
+ * @param: configuration parameters
+ * @dev_addr: physical address of periphal connected to channel
+ */
+struct coh_dma_channel {
+	const char name[32];
+	const int number;
+	const int desc_nbr_max;
+	const int priority_high;
+	const struct coh901318_params param;
+	const dma_addr_t dev_addr;
+};
+
+/**
+ * dma_access_memory_state_t - register dma for memory access
+ *
+ * @dev: The dma device
+ * @active:  1 means dma intends to access memory
+ *           0 means dma wont access memory
+ */
+typedef void (*dma_access_memory_state_t)(struct device *dev,
+					  bool active);
+
+/**
+ * struct powersave - DMA power save structure
+ * @lock: lock protecting data in this struct
+ * @started_channels: bit mask indicating active dma channels
+ */
+struct powersave {
+	spinlock_t lock;
+	u64 started_channels;
+};
+/**
+ * struct coh901318_platform - platform arch structure
+ * @chans_slave: specifying dma slave channels
+ * @chans_memcpy: specifying dma memcpy channels
+ * @access_memory_state: requesting DMA memeory access (on / off)
+ * @chan_conf: dma channel configurations
+ * @max_channels: max number of dma chanenls
+ */
+struct coh901318_platform {
+	const int *chans_slave;
+	const int *chans_memcpy;
+	const dma_access_memory_state_t access_memory_state;
+	const struct coh_dma_channel *chan_conf;
+	const int max_channels;
+};
+
+/**
+ * coh901318_get_bytes_left() - Get number of bytes left on a current transfer
+ * @chan: dma channel handle
+ * return number of bytes left, or negative on error
+ */
+u32 coh901318_get_bytes_left(struct dma_chan *chan);
+
+/**
+ * coh901318_stop() - Stops dma transfer
+ * @chan: dma channel handle
+ * return 0 on success otherwise negative value
+ */
+void coh901318_stop(struct dma_chan *chan);
+
+/**
+ * coh901318_continue() - Resumes a stopped dma transfer
+ * @chan: dma channel handle
+ * return 0 on success otherwise negative value
+ */
+void coh901318_continue(struct dma_chan *chan);
+
+/**
+ * coh901318_filter_id() - DMA channel filter function
+ * @chan: dma channel handle
+ * @chan_id: id of dma channel to be filter out
+ *
+ * In dma_request_channel() it specifies what channel id to be requested
+ */
+bool coh901318_filter_id(struct dma_chan *chan, void *chan_id);
+
+/*
+ * DMA Controller - this access the static mappings of the coh901318 dma.
+ *
+ */
+
+#define COH901318_MOD32_MASK					(0x1F)
+#define COH901318_WORD_MASK					(0xFFFFFFFF)
+/* INT_STATUS - Interrupt Status Registers 32bit (R/-) */
+#define COH901318_INT_STATUS1					(0x0000)
+#define COH901318_INT_STATUS2					(0x0004)
+/* TC_INT_STATUS - Terminal Count Interrupt Status Registers 32bit (R/-) */
+#define COH901318_TC_INT_STATUS1				(0x0008)
+#define COH901318_TC_INT_STATUS2				(0x000C)
+/* TC_INT_CLEAR - Terminal Count Interrupt Clear Registers 32bit (-/W) */
+#define COH901318_TC_INT_CLEAR1					(0x0010)
+#define COH901318_TC_INT_CLEAR2					(0x0014)
+/* RAW_TC_INT_STATUS - Raw Term Count Interrupt Status Registers 32bit (R/-) */
+#define COH901318_RAW_TC_INT_STATUS1				(0x0018)
+#define COH901318_RAW_TC_INT_STATUS2				(0x001C)
+/* BE_INT_STATUS - Bus Error Interrupt Status Registers 32bit (R/-) */
+#define COH901318_BE_INT_STATUS1				(0x0020)
+#define COH901318_BE_INT_STATUS2				(0x0024)
+/* BE_INT_CLEAR - Bus Error Interrupt Clear Registers 32bit (-/W) */
+#define COH901318_BE_INT_CLEAR1					(0x0028)
+#define COH901318_BE_INT_CLEAR2					(0x002C)
+/* RAW_BE_INT_STATUS - Raw Term Count Interrupt Status Registers 32bit (R/-) */
+#define COH901318_RAW_BE_INT_STATUS1				(0x0030)
+#define COH901318_RAW_BE_INT_STATUS2				(0x0034)
+
+/*
+ * CX_CFG - Channel Configuration Registers 32bit (R/W)
+ */
+#define COH901318_CX_CFG					(0x0100)
+#define COH901318_CX_CFG_SPACING				(0x04)
+/* Channel enable activates tha dma job */
+#define COH901318_CX_CFG_CH_ENABLE				(0x00000001)
+#define COH901318_CX_CFG_CH_DISABLE				(0x00000000)
+/* Request Mode */
+#define COH901318_CX_CFG_RM_MASK				(0x00000006)
+#define COH901318_CX_CFG_RM_MEMORY_TO_MEMORY			(0x0 << 1)
+#define COH901318_CX_CFG_RM_PRIMARY_TO_MEMORY			(0x1 << 1)
+#define COH901318_CX_CFG_RM_MEMORY_TO_PRIMARY			(0x1 << 1)
+#define COH901318_CX_CFG_RM_PRIMARY_TO_SECONDARY		(0x3 << 1)
+#define COH901318_CX_CFG_RM_SECONDARY_TO_PRIMARY		(0x3 << 1)
+/* Linked channel request field. RM must == 11 */
+#define COH901318_CX_CFG_LCRF_SHIFT				3
+#define COH901318_CX_CFG_LCRF_MASK				(0x000001F8)
+#define COH901318_CX_CFG_LCR_DISABLE				(0x00000000)
+/* Terminal Counter Interrupt Request Mask */
+#define COH901318_CX_CFG_TC_IRQ_ENABLE				(0x00000200)
+#define COH901318_CX_CFG_TC_IRQ_DISABLE				(0x00000000)
+/* Bus Error interrupt Mask */
+#define COH901318_CX_CFG_BE_IRQ_ENABLE				(0x00000400)
+#define COH901318_CX_CFG_BE_IRQ_DISABLE				(0x00000000)
+
+/*
+ * CX_STAT - Channel Status Registers 32bit (R/-)
+ */
+#define COH901318_CX_STAT					(0x0200)
+#define COH901318_CX_STAT_SPACING				(0x04)
+#define COH901318_CX_STAT_RBE_IRQ_IND				(0x00000008)
+#define COH901318_CX_STAT_RTC_IRQ_IND				(0x00000004)
+#define COH901318_CX_STAT_ACTIVE				(0x00000002)
+#define COH901318_CX_STAT_ENABLED				(0x00000001)
+
+/*
+ * CX_CTRL - Channel Control Registers 32bit (R/W)
+ */
+#define COH901318_CX_CTRL					(0x0400)
+#define COH901318_CX_CTRL_SPACING				(0x10)
+/* Transfer Count Enable */
+#define COH901318_CX_CTRL_TC_ENABLE				(0x00001000)
+#define COH901318_CX_CTRL_TC_DISABLE				(0x00000000)
+/* Transfer Count Value 0 - 4095 */
+#define COH901318_CX_CTRL_TC_VALUE_MASK				(0x00000FFF)
+/* Burst count */
+#define COH901318_CX_CTRL_BURST_COUNT_MASK			(0x0000E000)
+#define COH901318_CX_CTRL_BURST_COUNT_64_BYTES			(0x7 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_48_BYTES			(0x6 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_32_BYTES			(0x5 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_16_BYTES			(0x4 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_8_BYTES			(0x3 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_4_BYTES			(0x2 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_2_BYTES			(0x1 << 13)
+#define COH901318_CX_CTRL_BURST_COUNT_1_BYTE			(0x0 << 13)
+/* Source bus size  */
+#define COH901318_CX_CTRL_SRC_BUS_SIZE_MASK			(0x00030000)
+#define COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS			(0x2 << 16)
+#define COH901318_CX_CTRL_SRC_BUS_SIZE_16_BITS			(0x1 << 16)
+#define COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS			(0x0 << 16)
+/* Source address increment */
+#define COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE			(0x00040000)
+#define COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE			(0x00000000)
+/* Destination Bus Size */
+#define COH901318_CX_CTRL_DST_BUS_SIZE_MASK			(0x00180000)
+#define COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS			(0x2 << 19)
+#define COH901318_CX_CTRL_DST_BUS_SIZE_16_BITS			(0x1 << 19)
+#define COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS			(0x0 << 19)
+/* Destination address increment */
+#define COH901318_CX_CTRL_DST_ADDR_INC_ENABLE			(0x00200000)
+#define COH901318_CX_CTRL_DST_ADDR_INC_DISABLE			(0x00000000)
+/* Master Mode (Master2 is only connected to MSL) */
+#define COH901318_CX_CTRL_MASTER_MODE_MASK			(0x00C00000)
+#define COH901318_CX_CTRL_MASTER_MODE_M2R_M1W			(0x3 << 22)
+#define COH901318_CX_CTRL_MASTER_MODE_M1R_M2W			(0x2 << 22)
+#define COH901318_CX_CTRL_MASTER_MODE_M2RW			(0x1 << 22)
+#define COH901318_CX_CTRL_MASTER_MODE_M1RW			(0x0 << 22)
+/* Terminal Count flag to PER enable */
+#define COH901318_CX_CTRL_TCP_ENABLE				(0x01000000)
+#define COH901318_CX_CTRL_TCP_DISABLE				(0x00000000)
+/* Terminal Count flags to CPU enable */
+#define COH901318_CX_CTRL_TC_IRQ_ENABLE				(0x02000000)
+#define COH901318_CX_CTRL_TC_IRQ_DISABLE			(0x00000000)
+/* Hand shake to peripheral */
+#define COH901318_CX_CTRL_HSP_ENABLE				(0x04000000)
+#define COH901318_CX_CTRL_HSP_DISABLE				(0x00000000)
+#define COH901318_CX_CTRL_HSS_ENABLE				(0x08000000)
+#define COH901318_CX_CTRL_HSS_DISABLE				(0x00000000)
+/* DMA mode */
+#define COH901318_CX_CTRL_DDMA_MASK				(0x30000000)
+#define COH901318_CX_CTRL_DDMA_LEGACY				(0x0 << 28)
+#define COH901318_CX_CTRL_DDMA_DEMAND_DMA1			(0x1 << 28)
+#define COH901318_CX_CTRL_DDMA_DEMAND_DMA2			(0x2 << 28)
+/* Primary Request Data Destination */
+#define COH901318_CX_CTRL_PRDD_MASK				(0x40000000)
+#define COH901318_CX_CTRL_PRDD_DEST				(0x1 << 30)
+#define COH901318_CX_CTRL_PRDD_SOURCE				(0x0 << 30)
+
+/*
+ * CX_SRC_ADDR - Channel Source Address Registers 32bit (R/W)
+ */
+#define COH901318_CX_SRC_ADDR					(0x0404)
+#define COH901318_CX_SRC_ADDR_SPACING				(0x10)
+
+/*
+ * CX_DST_ADDR - Channel Destination Address Registers 32bit R/W
+ */
+#define COH901318_CX_DST_ADDR					(0x0408)
+#define COH901318_CX_DST_ADDR_SPACING				(0x10)
+
+/*
+ * CX_LNK_ADDR - Channel Link Address Registers 32bit (R/W)
+ */
+#define COH901318_CX_LNK_ADDR					(0x040C)
+#define COH901318_CX_LNK_ADDR_SPACING				(0x10)
+#define COH901318_CX_LNK_LINK_IMMEDIATE				(0x00000001)
+#endif /* COH901318_H */
diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S
index b63a8f7..a89444a 100644
--- a/arch/arm/mm/cache-fa.S
+++ b/arch/arm/mm/cache-fa.S
@@ -127,15 +127,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(kaddr)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure that the data held in the page kaddr is written back
  *	to the page in question.
  *
- *	- kaddr   - kernel address (guaranteed to be page aligned)
+ *	- addr	- kernel address
+ *	- size	- size of region
  */
-ENTRY(fa_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(fa_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -213,7 +214,7 @@
 	.long	fa_flush_user_cache_range
 	.long	fa_coherent_kern_range
 	.long	fa_coherent_user_range
-	.long	fa_flush_kern_dcache_page
+	.long	fa_flush_kern_dcache_area
 	.long	fa_dma_inv_range
 	.long	fa_dma_clean_range
 	.long	fa_dma_flush_range
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 747f9a9..cb8fc65 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -28,69 +28,120 @@
 static void __iomem *l2x0_base;
 static DEFINE_SPINLOCK(l2x0_lock);
 
-static inline void sync_writel(unsigned long val, unsigned long reg,
-			       unsigned long complete_mask)
+static inline void cache_wait(void __iomem *reg, unsigned long mask)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&l2x0_lock, flags);
-	writel(val, l2x0_base + reg);
 	/* wait for the operation to complete */
-	while (readl(l2x0_base + reg) & complete_mask)
+	while (readl(reg) & mask)
 		;
-	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static inline void cache_sync(void)
 {
-	sync_writel(0, L2X0_CACHE_SYNC, 1);
+	void __iomem *base = l2x0_base;
+	writel(0, base + L2X0_CACHE_SYNC);
+	cache_wait(base + L2X0_CACHE_SYNC, 1);
 }
 
 static inline void l2x0_inv_all(void)
 {
+	unsigned long flags;
+
 	/* invalidate all ways */
-	sync_writel(0xff, L2X0_INV_WAY, 0xff);
+	spin_lock_irqsave(&l2x0_lock, flags);
+	writel(0xff, l2x0_base + L2X0_INV_WAY);
+	cache_wait(l2x0_base + L2X0_INV_WAY, 0xff);
 	cache_sync();
+	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_inv_range(unsigned long start, unsigned long end)
 {
-	unsigned long addr;
+	void __iomem *base = l2x0_base;
+	unsigned long flags;
 
+	spin_lock_irqsave(&l2x0_lock, flags);
 	if (start & (CACHE_LINE_SIZE - 1)) {
 		start &= ~(CACHE_LINE_SIZE - 1);
-		sync_writel(start, L2X0_CLEAN_INV_LINE_PA, 1);
+		cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+		writel(start, base + L2X0_CLEAN_INV_LINE_PA);
 		start += CACHE_LINE_SIZE;
 	}
 
 	if (end & (CACHE_LINE_SIZE - 1)) {
 		end &= ~(CACHE_LINE_SIZE - 1);
-		sync_writel(end, L2X0_CLEAN_INV_LINE_PA, 1);
+		cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+		writel(end, base + L2X0_CLEAN_INV_LINE_PA);
 	}
 
-	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-		sync_writel(addr, L2X0_INV_LINE_PA, 1);
+	while (start < end) {
+		unsigned long blk_end = start + min(end - start, 4096UL);
+
+		while (start < blk_end) {
+			cache_wait(base + L2X0_INV_LINE_PA, 1);
+			writel(start, base + L2X0_INV_LINE_PA);
+			start += CACHE_LINE_SIZE;
+		}
+
+		if (blk_end < end) {
+			spin_unlock_irqrestore(&l2x0_lock, flags);
+			spin_lock_irqsave(&l2x0_lock, flags);
+		}
+	}
+	cache_wait(base + L2X0_INV_LINE_PA, 1);
 	cache_sync();
+	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_clean_range(unsigned long start, unsigned long end)
 {
-	unsigned long addr;
+	void __iomem *base = l2x0_base;
+	unsigned long flags;
 
+	spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
-	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-		sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
+	while (start < end) {
+		unsigned long blk_end = start + min(end - start, 4096UL);
+
+		while (start < blk_end) {
+			cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
+			writel(start, base + L2X0_CLEAN_LINE_PA);
+			start += CACHE_LINE_SIZE;
+		}
+
+		if (blk_end < end) {
+			spin_unlock_irqrestore(&l2x0_lock, flags);
+			spin_lock_irqsave(&l2x0_lock, flags);
+		}
+	}
+	cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
 	cache_sync();
+	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 static void l2x0_flush_range(unsigned long start, unsigned long end)
 {
-	unsigned long addr;
+	void __iomem *base = l2x0_base;
+	unsigned long flags;
 
+	spin_lock_irqsave(&l2x0_lock, flags);
 	start &= ~(CACHE_LINE_SIZE - 1);
-	for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
-		sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
+	while (start < end) {
+		unsigned long blk_end = start + min(end - start, 4096UL);
+
+		while (start < blk_end) {
+			cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
+			writel(start, base + L2X0_CLEAN_INV_LINE_PA);
+			start += CACHE_LINE_SIZE;
+		}
+
+		if (blk_end < end) {
+			spin_unlock_irqrestore(&l2x0_lock, flags);
+			spin_lock_irqsave(&l2x0_lock, flags);
+		}
+	}
+	cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
 	cache_sync();
+	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
 void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index 8a4abeb..2a48273 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -72,14 +72,15 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *page, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v3_flush_kern_dcache_page)
+ENTRY(v3_flush_kern_dcache_area)
 	/* FALLTHROUGH */
 
 /*
@@ -129,7 +130,7 @@
 	.long	v3_flush_user_cache_range
 	.long	v3_coherent_kern_range
 	.long	v3_coherent_user_range
-	.long	v3_flush_kern_dcache_page
+	.long	v3_flush_kern_dcache_area
 	.long	v3_dma_inv_range
 	.long	v3_dma_clean_range
 	.long	v3_dma_flush_range
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index 3668611..5c7da3e 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -82,14 +82,15 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v4_flush_kern_dcache_page)
+ENTRY(v4_flush_kern_dcache_area)
 	/* FALLTHROUGH */
 
 /*
@@ -141,7 +142,7 @@
 	.long	v4_flush_user_cache_range
 	.long	v4_coherent_kern_range
 	.long	v4_coherent_user_range
-	.long	v4_flush_kern_dcache_page
+	.long	v4_flush_kern_dcache_area
 	.long	v4_dma_inv_range
 	.long	v4_dma_clean_range
 	.long	v4_dma_flush_range
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 2ebc1b3..3dbedf1e 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -114,15 +114,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v4wb_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(v4wb_flush_kern_dcache_area)
+	add	r1, r0, r1
 	/* fall through */
 
 /*
@@ -224,7 +225,7 @@
 	.long	v4wb_flush_user_cache_range
 	.long	v4wb_coherent_kern_range
 	.long	v4wb_coherent_user_range
-	.long	v4wb_flush_kern_dcache_page
+	.long	v4wb_flush_kern_dcache_area
 	.long	v4wb_dma_inv_range
 	.long	v4wb_dma_clean_range
 	.long	v4wb_dma_flush_range
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index c54fa2c..b3b7410 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -117,17 +117,18 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v4wt_flush_kern_dcache_page)
+ENTRY(v4wt_flush_kern_dcache_area)
 	mov	r2, #0
 	mcr	p15, 0, r2, c7, c5, 0		@ invalidate I cache
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 	/* fallthrough */
 
 /*
@@ -180,7 +181,7 @@
 	.long	v4wt_flush_user_cache_range
 	.long	v4wt_coherent_kern_range
 	.long	v4wt_coherent_user_range
-	.long	v4wt_flush_kern_dcache_page
+	.long	v4wt_flush_kern_dcache_area
 	.long	v4wt_dma_inv_range
 	.long	v4wt_dma_clean_range
 	.long	v4wt_dma_flush_range
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 295e25d..4ba0a24 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -159,15 +159,16 @@
 ENDPROC(v6_coherent_kern_range)
 
 /*
- *	v6_flush_kern_dcache_page(kaddr)
+ *	v6_flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure that the data held in the page kaddr is written back
  *	to the page in question.
  *
- *	- kaddr   - kernel address (guaranteed to be page aligned)
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v6_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(v6_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:
 #ifdef HARVARD_CACHE
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line
@@ -271,7 +272,7 @@
 	.long	v6_flush_user_cache_range
 	.long	v6_coherent_kern_range
 	.long	v6_coherent_user_range
-	.long	v6_flush_kern_dcache_page
+	.long	v6_flush_kern_dcache_area
 	.long	v6_dma_inv_range
 	.long	v6_dma_clean_range
 	.long	v6_dma_flush_range
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index e1bd975..9073db8 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -186,16 +186,17 @@
 ENDPROC(v7_coherent_user_range)
 
 /*
- *	v7_flush_kern_dcache_page(kaddr)
+ *	v7_flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure that the data held in the page kaddr is written back
  *	to the page in question.
  *
- *	- kaddr   - kernel address (guaranteed to be page aligned)
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(v7_flush_kern_dcache_page)
+ENTRY(v7_flush_kern_dcache_area)
 	dcache_line_size r2, r3
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 1:
 	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line / unified line
 	add	r0, r0, r2
@@ -203,7 +204,7 @@
 	blo	1b
 	dsb
 	mov	pc, lr
-ENDPROC(v7_flush_kern_dcache_page)
+ENDPROC(v7_flush_kern_dcache_area)
 
 /*
  *	v7_dma_inv_range(start,end)
@@ -279,7 +280,7 @@
 	.long	v7_flush_user_cache_range
 	.long	v7_coherent_kern_range
 	.long	v7_coherent_user_range
-	.long	v7_flush_kern_dcache_page
+	.long	v7_flush_kern_dcache_area
 	.long	v7_dma_inv_range
 	.long	v7_dma_clean_range
 	.long	v7_dma_flush_range
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 329594e..6f3a4b7 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -131,7 +131,7 @@
 	 */
 	if (addr)
 #endif
-		__cpuc_flush_dcache_page(addr);
+		__cpuc_flush_dcache_area(addr, PAGE_SIZE);
 
 	/*
 	 * If this is a page cache page, and we have an aliasing VIPT cache,
@@ -258,5 +258,5 @@
 	 * in this mapping of the page.  FIXME: this is overkill
 	 * since we actually ask for a write-back and invalidate.
 	 */
-	__cpuc_flush_dcache_page(page_address(page));
+	__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index 30f82fb..2be1ec7 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -79,7 +79,7 @@
 	unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
 
 	if (kvaddr >= (void *)FIXADDR_START) {
-		__cpuc_flush_dcache_page((void *)vaddr);
+		__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
 		BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
 		set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 900811c..374a831 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -61,7 +61,7 @@
 
 void flush_dcache_page(struct page *page)
 {
-	__cpuc_flush_dcache_page(page_address(page));
+	__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index d9fb4b9..8012e24 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -231,17 +231,18 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- page	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm1020_flush_kern_dcache_page)
+ENTRY(arm1020_flush_kern_dcache_area)
 	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	mcr	p15, 0, ip, c7, c10, 4		@ drain WB
 	add	r0, r0, #CACHE_DLINESIZE
@@ -335,7 +336,7 @@
 	.long	arm1020_flush_user_cache_range
 	.long	arm1020_coherent_kern_range
 	.long	arm1020_coherent_user_range
-	.long	arm1020_flush_kern_dcache_page
+	.long	arm1020_flush_kern_dcache_area
 	.long	arm1020_dma_inv_range
 	.long	arm1020_dma_clean_range
 	.long	arm1020_dma_flush_range
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 7453b75..41fe25d 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -225,17 +225,18 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- page	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm1020e_flush_kern_dcache_page)
+ENTRY(arm1020e_flush_kern_dcache_area)
 	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -321,7 +322,7 @@
 	.long	arm1020e_flush_user_cache_range
 	.long	arm1020e_coherent_kern_range
 	.long	arm1020e_coherent_user_range
-	.long	arm1020e_flush_kern_dcache_page
+	.long	arm1020e_flush_kern_dcache_area
 	.long	arm1020e_dma_inv_range
 	.long	arm1020e_dma_clean_range
 	.long	arm1020e_dma_flush_range
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 8eb72d7..20a5b1b 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -214,17 +214,18 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- page	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm1022_flush_kern_dcache_page)
+ENTRY(arm1022_flush_kern_dcache_area)
 	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -310,7 +311,7 @@
 	.long	arm1022_flush_user_cache_range
 	.long	arm1022_coherent_kern_range
 	.long	arm1022_coherent_user_range
-	.long	arm1022_flush_kern_dcache_page
+	.long	arm1022_flush_kern_dcache_area
 	.long	arm1022_dma_inv_range
 	.long	arm1022_dma_clean_range
 	.long	arm1022_dma_flush_range
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 3b59f0d..96aedb1 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -208,17 +208,18 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- page	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm1026_flush_kern_dcache_page)
+ENTRY(arm1026_flush_kern_dcache_area)
 	mov	ip, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-	add	r1, r0, #PAGE_SZ
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -304,7 +305,7 @@
 	.long	arm1026_flush_user_cache_range
 	.long	arm1026_coherent_kern_range
 	.long	arm1026_coherent_user_range
-	.long	arm1026_flush_kern_dcache_page
+	.long	arm1026_flush_kern_dcache_area
 	.long	arm1026_dma_inv_range
 	.long	arm1026_dma_clean_range
 	.long	arm1026_dma_flush_range
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 2b7c197..471669e 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -207,15 +207,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm920_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(arm920_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -293,7 +294,7 @@
 	.long	arm920_flush_user_cache_range
 	.long	arm920_coherent_kern_range
 	.long	arm920_coherent_user_range
-	.long	arm920_flush_kern_dcache_page
+	.long	arm920_flush_kern_dcache_area
 	.long	arm920_dma_inv_range
 	.long	arm920_dma_clean_range
 	.long	arm920_dma_flush_range
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 06a1aa4..ee111b0 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -209,15 +209,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm922_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(arm922_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -295,7 +296,7 @@
 	.long	arm922_flush_user_cache_range
 	.long	arm922_coherent_kern_range
 	.long	arm922_coherent_user_range
-	.long	arm922_flush_kern_dcache_page
+	.long	arm922_flush_kern_dcache_area
 	.long	arm922_dma_inv_range
 	.long	arm922_dma_clean_range
 	.long	arm922_dma_flush_range
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index cb53435..8deb5bd 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -251,15 +251,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm925_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(arm925_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -346,7 +347,7 @@
 	.long	arm925_flush_user_cache_range
 	.long	arm925_coherent_kern_range
 	.long	arm925_coherent_user_range
-	.long	arm925_flush_kern_dcache_page
+	.long	arm925_flush_kern_dcache_area
 	.long	arm925_dma_inv_range
 	.long	arm925_dma_clean_range
 	.long	arm925_dma_flush_range
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 1c48487..64db6e2 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -214,15 +214,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm926_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(arm926_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -309,7 +310,7 @@
 	.long	arm926_flush_user_cache_range
 	.long	arm926_coherent_kern_range
 	.long	arm926_coherent_user_range
-	.long	arm926_flush_kern_dcache_page
+	.long	arm926_flush_kern_dcache_area
 	.long	arm926_dma_inv_range
 	.long	arm926_dma_clean_range
 	.long	arm926_dma_flush_range
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 5b0f846..8196b9f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -141,14 +141,15 @@
 	/* FALLTHROUGH */
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(arm940_flush_kern_dcache_page)
+ENTRY(arm940_flush_kern_dcache_area)
 	mov	ip, #0
 	mov	r1, #(CACHE_DSEGMENTS - 1) << 4	@ 4 segments
 1:	orr	r3, r1, #(CACHE_DENTRIES - 1) << 26 @ 64 entries
@@ -238,7 +239,7 @@
 	.long	arm940_flush_user_cache_range
 	.long	arm940_coherent_kern_range
 	.long	arm940_coherent_user_range
-	.long	arm940_flush_kern_dcache_page
+	.long	arm940_flush_kern_dcache_area
 	.long	arm940_dma_inv_range
 	.long	arm940_dma_clean_range
 	.long	arm940_dma_flush_range
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 40c0449..9a95123 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -183,16 +183,17 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  * (same as arm926)
  */
-ENTRY(arm946_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(arm946_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -280,7 +281,7 @@
 	.long	arm946_flush_user_cache_range
 	.long	arm946_coherent_kern_range
 	.long	arm946_coherent_user_range
-	.long	arm946_flush_kern_dcache_page
+	.long	arm946_flush_kern_dcache_area
 	.long	arm946_dma_inv_range
 	.long	arm946_dma_clean_range
 	.long	arm946_dma_flush_range
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index d0d7795..dbc3938 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -226,16 +226,17 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
 	.align	5
-ENTRY(feroceon_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(feroceon_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -246,7 +247,7 @@
 	mov	pc, lr
 
 	.align	5
-ENTRY(feroceon_range_flush_kern_dcache_page)
+ENTRY(feroceon_range_flush_kern_dcache_area)
 	mrs	r2, cpsr
 	add	r1, r0, #PAGE_SZ - CACHE_DLINESIZE	@ top addr is inclusive
 	orr	r3, r2, #PSR_I_BIT
@@ -372,7 +373,7 @@
 	.long	feroceon_flush_user_cache_range
 	.long	feroceon_coherent_kern_range
 	.long	feroceon_coherent_user_range
-	.long	feroceon_flush_kern_dcache_page
+	.long	feroceon_flush_kern_dcache_area
 	.long	feroceon_dma_inv_range
 	.long	feroceon_dma_clean_range
 	.long	feroceon_dma_flush_range
@@ -383,7 +384,7 @@
 	.long	feroceon_flush_user_cache_range
 	.long	feroceon_coherent_kern_range
 	.long	feroceon_coherent_user_range
-	.long	feroceon_range_flush_kern_dcache_page
+	.long	feroceon_range_flush_kern_dcache_area
 	.long	feroceon_range_dma_inv_range
 	.long	feroceon_range_dma_clean_range
 	.long	feroceon_range_dma_flush_range
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 52b5fd7..9674d36 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -186,15 +186,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(mohawk_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(mohawk_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean+invalidate D entry
 	add	r0, r0, #CACHE_DLINESIZE
 	cmp	r0, r1
@@ -273,7 +274,7 @@
 	.long	mohawk_flush_user_cache_range
 	.long	mohawk_coherent_kern_range
 	.long	mohawk_coherent_user_range
-	.long	mohawk_flush_kern_dcache_page
+	.long	mohawk_flush_kern_dcache_area
 	.long	mohawk_dma_inv_range
 	.long	mohawk_dma_clean_range
 	.long	mohawk_dma_flush_range
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index ac5c800..3e6210b 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -27,8 +27,7 @@
 EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
-EXPORT_SYMBOL(__cpuc_flush_dcache_page);
-EXPORT_SYMBOL(dmac_inv_range);  /* because of flush_ioremap_region() */
+EXPORT_SYMBOL(__cpuc_flush_dcache_area);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 5485c82..395cc90 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -254,10 +254,9 @@
 	.long	0x560f5810
 	.long	0xff0ffff0
 	.long   PMD_TYPE_SECT | \
-		PMD_SECT_BUFFERABLE | \
-		PMD_SECT_CACHEABLE | \
 		PMD_SECT_AP_WRITE | \
-		PMD_SECT_AP_READ
+		PMD_SECT_AP_READ | \
+		PMD_FLAGS
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_XN | \
 		PMD_SECT_AP_WRITE | \
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index fab134e..96456f5 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -226,15 +226,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache.
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(xsc3_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(xsc3_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c14, 1		@ clean/invalidate L1 D line
 	add	r0, r0, #CACHELINESIZE
 	cmp	r0, r1
@@ -309,7 +310,7 @@
 	.long	xsc3_flush_user_cache_range
 	.long	xsc3_coherent_kern_range
 	.long	xsc3_coherent_user_range
-	.long	xsc3_flush_kern_dcache_page
+	.long	xsc3_flush_kern_dcache_area
 	.long	xsc3_dma_inv_range
 	.long	xsc3_dma_clean_range
 	.long	xsc3_dma_flush_range
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index f056c28..93df472 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -284,15 +284,16 @@
 	mov	pc, lr
 
 /*
- *	flush_kern_dcache_page(void *page)
+ *	flush_kern_dcache_area(void *addr, size_t size)
  *
  *	Ensure no D cache aliasing occurs, either with itself or
  *	the I cache
  *
- *	- addr	- page aligned address
+ *	- addr	- kernel address
+ *	- size	- region size
  */
-ENTRY(xscale_flush_kern_dcache_page)
-	add	r1, r0, #PAGE_SZ
+ENTRY(xscale_flush_kern_dcache_area)
+	add	r1, r0, r1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
 	add	r0, r0, #CACHELINESIZE
@@ -368,7 +369,7 @@
 	.long	xscale_flush_user_cache_range
 	.long	xscale_coherent_kern_range
 	.long	xscale_coherent_user_range
-	.long	xscale_flush_kern_dcache_page
+	.long	xscale_flush_kern_dcache_area
 	.long	xscale_dma_inv_range
 	.long	xscale_dma_clean_range
 	.long	xscale_dma_flush_range
@@ -392,7 +393,7 @@
 	.long	xscale_flush_user_cache_range
 	.long	xscale_coherent_kern_range
 	.long	xscale_coherent_user_range
-	.long	xscale_flush_kern_dcache_page
+	.long	xscale_flush_kern_dcache_area
 	.long	xscale_dma_flush_range
 	.long	xscale_dma_clean_range
 	.long	xscale_dma_flush_range
diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h
index 2b972df..5d2d21d 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_nand.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_nand.h
@@ -22,6 +22,7 @@
 
 struct mxc_nand_platform_data {
 	int width;	/* data bus width in bytes */
-	int hw_ecc;	/* 0 if supress hardware ECC */
+	int hw_ecc:1;	/* 0 if supress hardware ECC */
+	int flash_bbt:1; /* set to 1 to use a flash based bbt */
 };
 #endif /* __ASM_ARCH_NAND_H */
diff --git a/arch/arm/plat-s3c/include/plat/nand.h b/arch/arm/plat-s3c/include/plat/nand.h
index 0659859..226147b 100644
--- a/arch/arm/plat-s3c/include/plat/nand.h
+++ b/arch/arm/plat-s3c/include/plat/nand.h
@@ -17,6 +17,7 @@
  *			Setting this flag will allow the kernel to
  *			look for it at boot time and also skip the NAND
  *			scan.
+ * @options:		Default value to set into 'struct nand_chip' options.
  * @nr_chips:		Number of chips in this set
  * @nr_partitions:	Number of partitions pointed to by @partitions
  * @name:		Name of set (optional)
@@ -31,6 +32,7 @@
 	unsigned int		disable_ecc:1;
 	unsigned int		flash_bbt:1;
 
+	unsigned int		options;
 	int			nr_chips;
 	int			nr_partitions;
 	char			*name;
diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
index 1dbaa29..635cb18 100644
--- a/arch/arm/tools/Makefile
+++ b/arch/arm/tools/Makefile
@@ -4,7 +4,7 @@
 # Copyright (C) 2001 Russell King
 #
 
-include/asm-arm/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
+include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
 	@echo '  Generating $@'
 	@mkdir -p $(dir $@)
 	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/arm/tools/gen-mach-types b/arch/arm/tools/gen-mach-types
index ce319ef..04fef71 100644
--- a/arch/arm/tools/gen-mach-types
+++ b/arch/arm/tools/gen-mach-types
@@ -1,6 +1,6 @@
 #!/bin/awk
 #
-# Awk script to generate include/asm-arm/mach-types.h
+# Awk script to generate include/generated/mach-types.h
 #
 BEGIN	{ nr = 0 }
 /^#/	{ next }
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 07b976d..c3a74ce 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Wed Nov 25 22:14:58 2009
+# Last update: Wed Dec 16 20:06:34 2009
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1776,6 +1776,7 @@
 wdg002			MACH_WDG002		WDG002			1785
 sg560adsl		MACH_SG560ADSL		SG560ADSL		1786
 nextio_n2800_ica	MACH_NEXTIO_N2800_ICA	NEXTIO_N2800_ICA	1787
+dove_db			MACH_DOVE_DB		DOVE_DB			1788
 marvell_newdb		MACH_MARVELL_NEWDB	MARVELL_NEWDB		1789
 vandihud		MACH_VANDIHUD		VANDIHUD		1790
 magx_e8			MACH_MAGX_E8		MAGX_E8			1791
@@ -2536,3 +2537,44 @@
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
 esyx			MACH_ESYX		ESYX			2551
 bulldog			MACH_BULLDOG		BULLDOG			2553
+derell_me2000		MACH_DERELL_ME2000	DERELL_ME2000		2554
+bcmring_base		MACH_BCMRING_BASE	BCMRING_BASE		2555
+bcmring_evm		MACH_BCMRING_EVM	BCMRING_EVM		2556
+bcmring_evm_jazz	MACH_BCMRING_EVM_JAZZ	BCMRING_EVM_JAZZ	2557
+bcmring_sp		MACH_BCMRING_SP		BCMRING_SP		2558
+bcmring_sv		MACH_BCMRING_SV		BCMRING_SV		2559
+bcmring_sv_jazz		MACH_BCMRING_SV_JAZZ	BCMRING_SV_JAZZ		2560
+bcmring_tablet		MACH_BCMRING_TABLET	BCMRING_TABLET		2561
+bcmring_vp		MACH_BCMRING_VP		BCMRING_VP		2562
+bcmring_evm_seikor	MACH_BCMRING_EVM_SEIKOR	BCMRING_EVM_SEIKOR	2563
+bcmring_sp_wqvga	MACH_BCMRING_SP_WQVGA	BCMRING_SP_WQVGA	2564
+bcmring_custom		MACH_BCMRING_CUSTOM	BCMRING_CUSTOM		2565
+acer_s200		MACH_ACER_S200		ACER_S200		2566
+bt270			MACH_BT270		BT270			2567
+iseo			MACH_ISEO		ISEO			2568
+cezanne			MACH_CEZANNE		CEZANNE			2569
+lucca			MACH_LUCCA		LUCCA			2570
+supersmart		MACH_SUPERSMART		SUPERSMART		2571
+magnolia2		MACH_MAGNOLIA2		MAGNOLIA2		2573
+emxx			MACH_EMXX		EMXX			2574
+outlaw			MACH_OUTLAW		OUTLAW			2575
+riot_bei2		MACH_RIOT_BEI2		RIOT_BEI2		2576
+riot_vox		MACH_RIOT_VOX		RIOT_VOX		2577
+riot_x37		MACH_RIOT_X37		RIOT_X37		2578
+mega25mx		MACH_MEGA25MX		MEGA25MX		2579
+benzina2		MACH_BENZINA2		BENZINA2		2580
+ignite			MACH_IGNITE		IGNITE			2581
+foggia			MACH_FOGGIA		FOGGIA			2582
+arezzo			MACH_AREZZO		AREZZO			2583
+leica_skywalker		MACH_LEICA_SKYWALKER	LEICA_SKYWALKER		2584
+jacinto2_jamr		MACH_JACINTO2_JAMR	JACINTO2_JAMR		2585
+gts_nova		MACH_GTS_NOVA		GTS_NOVA		2586
+p3600			MACH_P3600		P3600			2587
+dlt2			MACH_DLT2		DLT2			2588
+df3120			MACH_DF3120		DF3120			2589
+ecucore_9g20		MACH_ECUCORE_9G20	ECUCORE_9G20		2590
+nautel_lpc3240		MACH_NAUTEL_LPC3240	NAUTEL_LPC3240		2591
+glacier			MACH_GLACIER		GLACIER			2592
+phrazer_bulldog		MACH_PHRAZER_BULLDOG	PHRAZER_BULLDOG		2593
+omap3_bulldog		MACH_OMAP3_BULLDOG	OMAP3_BULLDOG		2594
+pca101			MACH_PCA101		PCA101			2595
diff --git a/arch/avr32/include/asm/asm-offsets.h b/arch/avr32/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/avr32/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/avr32/include/asm/elf.h b/arch/avr32/include/asm/elf.h
index d5d1d41..3b3159b 100644
--- a/arch/avr32/include/asm/elf.h
+++ b/arch/avr32/include/asm/elf.h
@@ -77,7 +77,6 @@
 #endif
 #define ELF_ARCH	EM_AVR32
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index ae6a60f..53c1e1d 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -5,6 +5,10 @@
 
 mainmenu "Blackfin Kernel Configuration"
 
+config SYMBOL_PREFIX
+	string
+	default "_"
+
 config MMU
 	def_bool n
 
@@ -28,6 +32,9 @@
 	select HAVE_OPROFILE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 
+config GENERIC_CSUM
+	def_bool y
+
 config GENERIC_BUG
 	def_bool y
 	depends on BUG
@@ -173,7 +180,7 @@
 	help
 	  BF539 Processor Support.
 
-config BF542
+config BF542_std
 	bool "BF542"
 	help
 	  BF542 Processor Support.
@@ -183,7 +190,7 @@
 	help
 	  BF542 Processor Support.
 
-config BF544
+config BF544_std
 	bool "BF544"
 	help
 	  BF544 Processor Support.
@@ -193,7 +200,7 @@
 	help
 	  BF544 Processor Support.
 
-config BF547
+config BF547_std
 	bool "BF547"
 	help
 	  BF547 Processor Support.
@@ -203,7 +210,7 @@
 	help
 	  BF547 Processor Support.
 
-config BF548
+config BF548_std
 	bool "BF548"
 	help
 	  BF548 Processor Support.
@@ -213,7 +220,7 @@
 	help
 	  BF548 Processor Support.
 
-config BF549
+config BF549_std
 	bool "BF549"
 	help
 	  BF549 Processor Support.
@@ -307,31 +314,11 @@
 
 endchoice
 
-config BF51x
-	bool
-	depends on (BF512 || BF514 || BF516 || BF518)
-	default y
-
-config BF52x
-	bool
-	depends on (BF522 || BF523 || BF524 || BF525 || BF526 || BF527)
-	default y
-
 config BF53x
 	bool
 	depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
 	default y
 
-config BF54xM
-	bool
-	depends on (BF542M || BF544M || BF547M || BF548M || BF549M)
-	default y
-
-config BF54x
-	bool
-	depends on (BF542 || BF544 || BF547 || BF548 || BF549 || BF54xM)
-	default y
-
 config MEM_GENERIC_BOARD
 	bool
 	depends on GENERIC_BOARD
@@ -913,6 +900,12 @@
 	bool "Enable 2M DMA region"
 config DMA_UNCACHED_1M
 	bool "Enable 1M DMA region"
+config DMA_UNCACHED_512K
+	bool "Enable 512K DMA region"
+config DMA_UNCACHED_256K
+	bool "Enable 256K DMA region"
+config DMA_UNCACHED_128K
+	bool "Enable 128K DMA region"
 config DMA_UNCACHED_NONE
 	bool "Disable DMA region"
 endchoice
@@ -1274,6 +1267,8 @@
 
 source "drivers/Kconfig"
 
+source "drivers/firmware/Kconfig"
+
 source "fs/Kconfig"
 
 source "arch/blackfin/Kconfig.debug"
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index f063b77..d4c7177 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -16,6 +16,7 @@
 KBUILD_CFLAGS           += $(call cc-option,-mno-fdpic)
 KBUILD_AFLAGS           += $(call cc-option,-mno-fdpic)
 CFLAGS_MODULE    += -mlong-calls
+LDFLAGS_MODULE   += -m elf32bfin
 KALLSYMS         += --symbol-prefix=_
 
 KBUILD_DEFCONFIG := BF537-STAMP_defconfig
@@ -137,7 +138,7 @@
 
 INSTALL_PATH ?= /tftpboot
 boot := arch/$(ARCH)/boot
-BOOT_TARGETS = vmImage vmImage.bz2 vmImage.gz vmImage.lzma
+BOOT_TARGETS = vmImage vmImage.bin vmImage.bz2 vmImage.gz vmImage.lzma
 PHONY += $(BOOT_TARGETS) install
 KBUILD_IMAGE := $(boot)/vmImage
 
@@ -151,6 +152,7 @@
 
 define archhelp
   echo  '* vmImage         - Alias to selected kernel format (vmImage.gz by default)'
+  echo  '  vmImage.bin     - Uncompressed Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.bin)'
   echo  '  vmImage.bz2     - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.bz2)'
   echo  '* vmImage.gz      - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.gz)'
   echo  '  vmImage.lzma    - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage.lzma)'
diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile
index fd9ccc5..e9c48c6 100644
--- a/arch/blackfin/boot/Makefile
+++ b/arch/blackfin/boot/Makefile
@@ -8,7 +8,7 @@
 
 MKIMAGE := $(srctree)/scripts/mkuboot.sh
 
-targets := vmImage vmImage.bz2 vmImage.gz vmImage.lzma
+targets := vmImage vmImage.bin vmImage.bz2 vmImage.gz vmImage.lzma
 extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma
 
 quiet_cmd_uimage = UIMAGE  $@
@@ -29,6 +29,9 @@
 $(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,lzma)
 
+$(obj)/vmImage.bin: $(obj)/vmlinux.bin
+	$(call if_changed,uimage,none)
+
 $(obj)/vmImage.bz2: $(obj)/vmlinux.bin.bz2
 	$(call if_changed,uimage,bzip2)
 
@@ -38,6 +41,7 @@
 $(obj)/vmImage.lzma: $(obj)/vmlinux.bin.lzma
 	$(call if_changed,uimage,lzma)
 
+suffix-y                      := bin
 suffix-$(CONFIG_KERNEL_GZIP)  := gz
 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
 suffix-$(CONFIG_KERNEL_LZMA)  := lzma
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index 9905b26..e315594 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -316,6 +317,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -438,17 +440,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
-CONFIG_NET_DSA=y
-# CONFIG_NET_DSA_TAG_DSA is not set
-# CONFIG_NET_DSA_TAG_EDSA is not set
-# CONFIG_NET_DSA_TAG_TRAILER is not set
-CONFIG_NET_DSA_TAG_STPID=y
-# CONFIG_NET_DSA_MV88E6XXX is not set
-# CONFIG_NET_DSA_MV88E6060 is not set
-# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
-# CONFIG_NET_DSA_MV88E6131 is not set
-# CONFIG_NET_DSA_MV88E6123_61_65 is not set
-CONFIG_NET_DSA_KSZ8893M=y
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 9dc6820..075e0fd 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -321,6 +322,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 77e35d4..6d1a623 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -321,6 +322,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 4c04480..50f9a23 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -283,6 +284,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index c99bbcd..6c60c82 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -283,6 +284,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 092ffda..2908595 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -290,6 +291,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -704,10 +706,7 @@
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index fa698a8..09ea249 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -301,6 +302,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index f773ad1..eb3e98b 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -1,22 +1,29 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.10
-# Thu May 21 05:50:01 2009
+# Linux kernel version: 2.6.31.5
+# Mon Nov  2 22:02:56 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -26,22 +33,40 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -62,17 +87,28 @@
 # CONFIG_TIMERFD is not set
 # CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -80,11 +116,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
+# CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -94,13 +127,12 @@
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 # CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_DEADLINE is not set
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -137,7 +169,7 @@
 # CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
 # CONFIG_BF547M is not set
-CONFIG_BF548=y
+CONFIG_BF548_std=y
 # CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
 # CONFIG_BF549M is not set
@@ -195,7 +227,7 @@
 #
 # BF548 Specific Configuration
 #
-# CONFIG_DEB_DMA_URGENT is not set
+CONFIG_DEB_DMA_URGENT=y
 # CONFIG_BF548_ATAPI_ALTERNATIVE_PORT is not set
 
 #
@@ -352,10 +384,11 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 CONFIG_DMA_UNCACHED_2M=y
@@ -366,14 +399,13 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+# CONFIG_BFIN_L2_ICACHEABLE is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
-CONFIG_BFIN_EXTMEM_WRITEBACK=y
-# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
-# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_EXTMEM_WRITEBACK is not set
+CONFIG_BFIN_EXTMEM_WRITETHROUGH=y
 # CONFIG_BFIN_L2_DCACHEABLE is not set
 
 #
@@ -382,7 +414,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -441,11 +473,6 @@
 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_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -469,13 +496,11 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
@@ -493,7 +518,10 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -548,14 +576,10 @@
 # CONFIG_MCS_FIR is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS is not set
 CONFIG_WIRELESS_EXT=y
-CONFIG_WIRELESS_EXT_SYSFS=y
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+CONFIG_LIB80211=m
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -578,6 +602,7 @@
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
@@ -653,7 +678,6 @@
 # CONFIG_MTD_NAND_VERIFY_WRITE is not set
 # CONFIG_MTD_NAND_ECC_SMC is not set
 # CONFIG_MTD_NAND_MUSEUM_IDS is not set
-# CONFIG_MTD_NAND_BFIN is not set
 CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_BF5XX=y
 CONFIG_MTD_NAND_BF5XX_HWECC=y
@@ -665,6 +689,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -682,10 +711,20 @@
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_AD525X_DPOT is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -709,10 +748,6 @@
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -729,6 +764,7 @@
 # CONFIG_SCSI_SRP_ATTRS is not set
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_PMP=y
@@ -744,13 +780,34 @@
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_SMC91X is not set
-CONFIG_SMSC911X=y
 # CONFIG_DM9000 is not set
 # CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -759,6 +816,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -771,13 +830,16 @@
 # CONFIG_LIBERTAS_USB is not set
 CONFIG_LIBERTAS_SDIO=m
 CONFIG_POWEROF2_BLOCKSIZE_ONLY=y
+# CONFIG_LIBERTAS_SPI is not set
 # CONFIG_LIBERTAS_DEBUG is not set
 # CONFIG_USB_ZD1201 is not set
-# CONFIG_USB_NET_RNDIS_WLAN is not set
-# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_HOSTAP is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -813,28 +875,31 @@
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
-CONFIG_KEYBOARD_BFIN=y
-# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_BFIN=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
 CONFIG_TOUCHSCREEN_AD7877=m
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
-# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
 # CONFIG_TOUCHSCREEN_MK712 is not set
@@ -844,6 +909,8 @@
 # CONFIG_TOUCHSCREEN_WM97XX is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 CONFIG_INPUT_MISC=y
 # CONFIG_INPUT_ATI_REMOTE is not set
 # CONFIG_INPUT_ATI_REMOTE2 is not set
@@ -852,7 +919,11 @@
 # CONFIG_INPUT_YEALINK is not set
 # CONFIG_INPUT_CM109 is not set
 # CONFIG_INPUT_UINPUT is not set
-# CONFIG_CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_BFIN_ROTARY is not set
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_PCF8574 is not set
 
 #
 # Hardware I/O ports
@@ -863,16 +934,13 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
 CONFIG_BFIN_DMA_INTERFACE=m
 # CONFIG_BFIN_PPI is not set
 # CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=m
-# CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_BFIN_TWI_LCD is not set
-CONFIG_SIMPLE_GPIO=m
 CONFIG_VT=y
 CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
@@ -890,6 +958,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -903,6 +972,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_BFIN_OTP=y
 # CONFIG_BFIN_OTP_WRITE_ENABLE is not set
@@ -951,14 +1021,9 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -975,13 +1040,18 @@
 # CONFIG_SPI_BFIN_LOCK is not set
 # CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
@@ -997,6 +1067,7 @@
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
@@ -1038,28 +1109,19 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1096,6 +1158,7 @@
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
 # CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -1132,6 +1195,7 @@
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
 CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
 # CONFIG_SND_SEQUENCER is not set
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=y
@@ -1142,6 +1206,11 @@
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
@@ -1152,7 +1221,6 @@
 #
 # ALSA Blackfin devices
 #
-# CONFIG_SND_BLACKFIN_AD1836 is not set
 # CONFIG_SND_BFIN_AD73322 is not set
 CONFIG_SND_USB=y
 # CONFIG_SND_USB_AUDIO is not set
@@ -1160,15 +1228,17 @@
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_AC97_BUS=y
 # CONFIG_SND_BF5XX_I2S is not set
+# CONFIG_SND_BF5XX_TDM is not set
 CONFIG_SND_BF5XX_AC97=y
 CONFIG_SND_BF5XX_MMAP_SUPPORT=y
 # CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
-CONFIG_SND_BF5XX_SOC_SPORT=y
-CONFIG_SND_BF5XX_SOC_AC97=y
-CONFIG_SND_BF5XX_SOC_AD1980=y
-CONFIG_SND_BF5XX_SPORT_NUM=0
 CONFIG_SND_BF5XX_HAVE_COLD_RESET=y
 CONFIG_SND_BF5XX_RESET_GPIO_NUM=19
+CONFIG_SND_BF5XX_SOC_AD1980=y
+CONFIG_SND_BF5XX_SOC_SPORT=y
+CONFIG_SND_BF5XX_SOC_AC97=y
+CONFIG_SND_BF5XX_SPORT_NUM=0
+CONFIG_SND_SOC_I2C_AND_SPI=y
 # CONFIG_SND_SOC_ALL_CODECS is not set
 CONFIG_SND_SOC_AD1980=y
 # CONFIG_SOUND_PRIME is not set
@@ -1188,30 +1258,34 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 CONFIG_HID_A4TECH=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
+# CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
+# CONFIG_HID_KENSINGTON is not set
 CONFIG_HID_LOGITECH=y
 # CONFIG_LOGITECH_FF is not set
 # CONFIG_LOGIRUMBLEPAD2_FF is not set
 CONFIG_HID_MICROSOFT=y
 CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
 CONFIG_HID_PANTHERLORD=y
 # CONFIG_PANTHERLORD_FF is not set
 CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -1237,6 +1311,7 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 # CONFIG_USB_ISP1362_HCD is not set
@@ -1267,18 +1342,17 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1314,7 +1388,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1326,6 +1399,13 @@
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+CONFIG_NOP_USB_XCEIV=y
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
@@ -1380,6 +1460,7 @@
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1411,10 +1492,21 @@
 #
 CONFIG_RTC_DRV_BFIN=y
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_SIGMA is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1427,9 +1519,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1439,6 +1533,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=m
@@ -1467,10 +1566,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1489,17 +1585,8 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1508,6 +1595,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -1522,7 +1610,6 @@
 CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -1596,11 +1683,15 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1608,16 +1699,21 @@
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_NOMMU_REGIONS is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
@@ -1625,17 +1721,16 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-
-#
-# Tracers
-#
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
@@ -1657,17 +1752,15 @@
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
-CONFIG_SECURITY=y
+# CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_NETWORK is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_CRYPTO=y
 
 #
@@ -1746,6 +1839,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -1753,11 +1847,13 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
@@ -1767,6 +1863,8 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/BF561-ACVILON_defconfig b/arch/blackfin/configs/BF561-ACVILON_defconfig
new file mode 100644
index 0000000..b9b0f93
--- /dev/null
+++ b/arch/blackfin/configs/BF561-ACVILON_defconfig
@@ -0,0 +1,1643 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31.4
+# Sat Oct 24 12:15:32 2009
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_BUG=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=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 is not set
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+CONFIG_EPOLL=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_MMAP_ALLOW_UNINITIALIZED is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
+CONFIG_BF561=y
+# CONFIG_SMP is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=5
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+CONFIG_BF_REV_0_5=y
+# CONFIG_BF_REV_0_6 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_TIMER0=10
+CONFIG_IRQ_TIMER1=10
+CONFIG_IRQ_TIMER2=10
+CONFIG_IRQ_TIMER3=10
+CONFIG_IRQ_TIMER4=10
+CONFIG_IRQ_TIMER5=10
+CONFIG_IRQ_TIMER6=10
+CONFIG_IRQ_TIMER7=10
+CONFIG_IRQ_SPI_ERROR=7
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+CONFIG_BFIN561_ACVILON=y
+
+#
+# BF561 Specific Configuration
+#
+
+#
+# Core B Support
+#
+# CONFIG_BF561_COREB is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA1_ERROR=7
+CONFIG_IRQ_DMA2_ERROR=7
+CONFIG_IRQ_IMDMA_ERROR=7
+CONFIG_IRQ_PPI0_ERROR=7
+CONFIG_IRQ_PPI1_ERROR=7
+CONFIG_IRQ_UART_ERROR=7
+CONFIG_IRQ_RESERVED_ERROR=7
+CONFIG_IRQ_DMA1_0=8
+CONFIG_IRQ_DMA1_1=8
+CONFIG_IRQ_DMA1_2=8
+CONFIG_IRQ_DMA1_3=8
+CONFIG_IRQ_DMA1_4=8
+CONFIG_IRQ_DMA1_5=8
+CONFIG_IRQ_DMA1_6=8
+CONFIG_IRQ_DMA1_7=8
+CONFIG_IRQ_DMA1_8=8
+CONFIG_IRQ_DMA1_9=8
+CONFIG_IRQ_DMA1_10=8
+CONFIG_IRQ_DMA1_11=8
+CONFIG_IRQ_DMA2_0=9
+CONFIG_IRQ_DMA2_1=9
+CONFIG_IRQ_DMA2_2=9
+CONFIG_IRQ_DMA2_3=9
+CONFIG_IRQ_DMA2_4=9
+CONFIG_IRQ_DMA2_5=9
+CONFIG_IRQ_DMA2_6=9
+CONFIG_IRQ_DMA2_7=9
+CONFIG_IRQ_DMA2_8=9
+CONFIG_IRQ_DMA2_9=9
+CONFIG_IRQ_DMA2_10=9
+CONFIG_IRQ_DMA2_11=9
+CONFIG_IRQ_TIMER8=10
+CONFIG_IRQ_TIMER9=10
+CONFIG_IRQ_TIMER10=10
+CONFIG_IRQ_TIMER11=10
+CONFIG_IRQ_PROG0_INTA=11
+CONFIG_IRQ_PROG0_INTB=11
+CONFIG_IRQ_PROG1_INTA=11
+CONFIG_IRQ_PROG1_INTB=11
+CONFIG_IRQ_PROG2_INTA=11
+CONFIG_IRQ_PROG2_INTB=11
+CONFIG_IRQ_DMA1_WRRD0=8
+CONFIG_IRQ_DMA1_WRRD1=8
+CONFIG_IRQ_DMA2_WRRD0=9
+CONFIG_IRQ_DMA2_WRRD1=9
+CONFIG_IRQ_IMDMA_WRRD0=12
+CONFIG_IRQ_IMDMA_WRRD1=12
+CONFIG_IRQ_WDTIMER=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=12000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=600000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# 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_SCHED_HRTICK=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
+CONFIG_CYCLES_CLOCKSOURCE=y
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Misc
+#
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL 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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BFIN_GPTIMERS=y
+CONFIG_DMA_UNCACHED_4M=y
+# CONFIG_DMA_UNCACHED_2M is not set
+# CONFIG_DMA_UNCACHED_1M is not set
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+# CONFIG_BFIN_L2_ICACHEABLE is not set
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+CONFIG_BFIN_EXTMEM_DCACHEABLE=y
+CONFIG_BFIN_EXTMEM_WRITEBACK=y
+# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
+# CONFIG_BFIN_L2_DCACHEABLE is not set
+
+#
+# Memory Protection Unit
+#
+# CONFIG_MPU is not set
+
+#
+# Asynchronous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+CONFIG_C_B0PEN=y
+CONFIG_C_B1PEN=y
+CONFIG_C_B2PEN=y
+# CONFIG_C_B3PEN is not set
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x99b2
+CONFIG_BANK_1=0x3350
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xAAC2
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+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_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=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
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_UCLINUX is not set
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+CONFIG_MTD_BLOCK2MTD=y
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# 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
+# 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=y
+
+#
+# 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_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_BFIN_DMA_INTERFACE is not set
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
+CONFIG_BFIN_SIMPLE_TIMER=y
+# CONFIG_BFIN_SPI_ADC is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TWI_LCD is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOPCA=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_PCA_PLATFORM=y
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+CONFIG_GPIO_PCF857X=y
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+CONFIG_SENSORS_LM75=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_SPI=y
+
+#
+# ALSA Blackfin devices
+#
+# CONFIG_SND_BFIN_AD73322 is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_BF5XX_I2S=y
+# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
+# CONFIG_SND_BF5XX_SOC_AD73311 is not set
+# CONFIG_SND_BF5XX_SOC_ADAU1371 is not set
+# CONFIG_SND_BF5XX_SOC_ADAU1761 is not set
+# CONFIG_SND_BF5XX_TDM is not set
+# CONFIG_SND_BF5XX_AC97 is not set
+CONFIG_SND_BF5XX_SOC_SPORT=y
+CONFIG_SND_BF5XX_SPORT_NUM=1
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_CONSOLE is not set
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=y
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=y
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_SIGMA is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS 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_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=866
+CONFIG_FAT_DEFAULT_IOCHARSET="cp1251"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+# CONFIG_JFFS2_ZLIB is not set
+CONFIG_JFFS2_LZO=y
+# CONFIG_JFFS2_RTIME is not set
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp1251"
+# 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=y
+# 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=y
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_KOI8_R=y
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_NOMMU_REGIONS is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
+CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_ROOTPLUG is not set
+# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 0313cd1..e3ecdcc 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -1,22 +1,29 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.10
-# Thu May 21 05:50:01 2009
+# Linux kernel version: 2.6.31.5
+# Mon Nov  2 21:59:31 2009
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -26,22 +33,40 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -62,17 +87,28 @@
 # CONFIG_TIMERFD is not set
 # CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -80,11 +116,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
+# CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -94,13 +127,12 @@
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 # CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_DEADLINE is not set
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -170,6 +202,7 @@
 CONFIG_BFIN561_EZKIT=y
 # CONFIG_BFIN561_TEPLA is not set
 # CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_ACVILON is not set
 
 #
 # BF561 Specific Configuration
@@ -317,10 +350,11 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -331,14 +365,13 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+# CONFIG_BFIN_L2_ICACHEABLE is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
-# CONFIG_BFIN_L2_ICACHEABLE is not set
 # CONFIG_BFIN_L2_DCACHEABLE is not set
 
 #
@@ -347,7 +380,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -407,11 +440,6 @@
 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_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -435,13 +463,11 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
@@ -459,7 +485,10 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -503,13 +532,8 @@
 #
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -530,6 +554,7 @@
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
@@ -603,6 +628,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -619,9 +649,14 @@
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -645,9 +680,11 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
-# CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
 # CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -656,6 +693,8 @@
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -664,7 +703,10 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -708,15 +750,12 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
 CONFIG_BFIN_DMA_INTERFACE=m
 # CONFIG_BFIN_PPI is not set
 # CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
-# CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_SIMPLE_GPIO=m
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_BFIN_JTAG_COMM=m
@@ -730,6 +769,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -740,6 +780,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
@@ -763,13 +804,18 @@
 # CONFIG_SPI_BFIN_LOCK is not set
 # CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
@@ -782,9 +828,6 @@
 #
 # I2C GPIO expanders:
 #
-# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCF857X is not set
 
 #
 # PCI GPIO expanders:
@@ -822,23 +865,9 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -862,7 +891,6 @@
 #
 # Special HID drivers
 #
-CONFIG_HID_COMPAT=y
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
@@ -870,10 +898,20 @@
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+
+#
 # File systems
 #
 # CONFIG_EXT2_FS is not set
@@ -882,9 +920,11 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -894,6 +934,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -915,10 +960,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -937,17 +979,8 @@
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_9BYTE_TAGS is not set
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -956,6 +989,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -966,7 +1000,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -1034,11 +1067,15 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 CONFIG_SCHED_DEBUG=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
@@ -1046,16 +1083,21 @@
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_NOMMU_REGIONS is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_FRAME_POINTER is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
@@ -1063,17 +1105,19 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_FAULT_INJECTION is not set
-
-#
-# Tracers
-#
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_BRANCH_PROFILE_NONE is not set
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_VERBOSE=y
@@ -1095,16 +1139,15 @@
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
-CONFIG_SECURITY=y
+# CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_NETWORK is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_CRYPTO=y
 
 #
@@ -1183,6 +1226,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -1190,11 +1234,13 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
@@ -1204,6 +1250,8 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig
index 5d944ff..9e65d88 100644
--- a/arch/blackfin/configs/BlackStamp_defconfig
+++ b/arch/blackfin/configs/BlackStamp_defconfig
@@ -66,6 +66,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -275,6 +276,7 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index 648a31d..4432150 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -1,12 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
@@ -15,6 +16,9 @@
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -25,55 +29,72 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=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_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -81,11 +102,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -101,7 +119,6 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
@@ -265,7 +282,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -315,10 +335,12 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -329,10 +351,9 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
@@ -343,7 +364,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -361,7 +382,7 @@
 # EBIU_AMBCTL Control
 #
 CONFIG_BANK_0=0x7BB0
-CONFIG_BANK_1=0x5554
+CONFIG_BANK_1=0x7BB0
 CONFIG_BANK_2=0x7BB0
 CONFIG_BANK_3=0xFFC0
 
@@ -386,7 +407,6 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
@@ -400,11 +420,6 @@
 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_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -428,7 +443,6 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -452,7 +466,9 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -463,13 +479,8 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -484,22 +495,21 @@
 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
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
 #
-CONFIG_MTD_CHAR=m
+CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
@@ -512,9 +522,9 @@
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
@@ -526,9 +536,11 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
@@ -538,7 +550,7 @@
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 # CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_GPIO_ADDR=y
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -562,6 +574,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -586,12 +603,46 @@
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=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_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -613,6 +664,9 @@
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -623,9 +677,11 @@
 CONFIG_BFIN_RX_DESC_NUM=20
 CONFIG_BFIN_MAC_RMII=y
 # CONFIG_SMC91X is not set
-# CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
 # CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -633,6 +689,7 @@
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -641,7 +698,10 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 
 #
 # USB Network Adapters
@@ -674,17 +734,13 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
-# CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-# CONFIG_BF5xx_EPPI is not set
-# CONFIG_BFIN_SPORT is not set
-# CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
 CONFIG_BFIN_DMA_INTERFACE=m
-CONFIG_SIMPLE_GPIO=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BFIN_SPI_ADC is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TWI_LCD is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_BFIN_JTAG_COMM is not set
@@ -698,6 +754,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -710,6 +767,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_BFIN_OTP=y
 # CONFIG_BFIN_OTP_WRITE_ENABLE is not set
@@ -758,13 +816,9 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -772,7 +826,6 @@
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 CONFIG_SPI=y
-# CONFIG_SPI_DEBUG is not set
 CONFIG_SPI_MASTER=y
 
 #
@@ -780,17 +833,17 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_SPI_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
-# CONFIG_DEBUG_GPIO is not set
 CONFIG_GPIO_SYSFS=y
 
 #
@@ -803,6 +856,7 @@
 # CONFIG_GPIO_MAX732X is not set
 # CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
@@ -829,11 +883,13 @@
 # CONFIG_SENSORS_ADT7462 is not set
 # CONFIG_SENSORS_ADT7470 is not set
 # CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
 # CONFIG_SENSORS_ATXP1 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -849,11 +905,16 @@
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -885,6 +946,12 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -892,10 +959,14 @@
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
 # CONFIG_REGULATOR is not set
 
 #
@@ -931,20 +1002,20 @@
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
-CONFIG_USB=y
+CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
-# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 CONFIG_USB_OTG_BLACKLIST_HUB=y
-CONFIG_USB_MON=y
+CONFIG_USB_MON=m
 # CONFIG_USB_WUSB is not set
 # CONFIG_USB_WUSB_CBAF is not set
 
@@ -952,24 +1023,24 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 # CONFIG_USB_ISP1362_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
 # CONFIG_USB_HWA_HCD is not set
-CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC=m
 CONFIG_USB_MUSB_SOC=y
 
 #
 # Blackfin high speed USB Support
 #
-CONFIG_USB_MUSB_HOST=y
-# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_HOST is not set
+CONFIG_USB_MUSB_PERIPHERAL=y
 # CONFIG_USB_MUSB_OTG is not set
-CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
 CONFIG_MUSB_PIO_ONLY=y
-CONFIG_MUSB_DMA_POLL=y
 # CONFIG_USB_MUSB_DEBUG is not set
 
 #
@@ -981,18 +1052,31 @@
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
 
 #
 # USB port drivers
@@ -1013,7 +1097,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1021,9 +1104,50 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
-# CONFIG_USB_GADGET is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2272 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 # CONFIG_MMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
@@ -1090,6 +1214,7 @@
 #
 CONFIG_RTC_DRV_BFIN=y
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -1102,9 +1227,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1114,6 +1240,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -1122,8 +1253,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1135,10 +1269,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1146,9 +1277,19 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -1157,6 +1298,7 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -1167,7 +1309,6 @@
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
@@ -1182,9 +1323,9 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+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
@@ -1208,7 +1349,7 @@
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1235,55 +1376,34 @@
 # 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_FRAME_POINTER is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
 #
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_KGDB_TESTCASE is not set
 CONFIG_DEBUG_VERBOSE=y
-CONFIG_DEBUG_MMRS=y
-# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_MMRS is not set
 # CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
@@ -1293,9 +1413,10 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 # CONFIG_CPLB_INFO is not set
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
@@ -1304,9 +1425,9 @@
 CONFIG_SECURITY=y
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+# CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
 #
@@ -1385,6 +1506,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -1392,20 +1514,24 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
index ae665b9..df56639 100644
--- a/arch/blackfin/configs/CM-BF533_defconfig
+++ b/arch/blackfin/configs/CM-BF533_defconfig
@@ -1,94 +1,110 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
 # General setup
 #
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODULE_FORCE_LOAD is not set
+# CONFIG_MODULE_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
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -96,7 +112,7 @@
 CONFIG_IOSCHED_NOOP=y
 # CONFIG_IOSCHED_AS is not set
 # CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_CFQ is not set
 # CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 # CONFIG_DEFAULT_CFQ is not set
@@ -105,6 +121,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -113,6 +130,10 @@
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -125,28 +146,38 @@
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 # CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=6
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
 # CONFIG_BF_REV_0_2 is not set
 CONFIG_BF_REV_0_3=y
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
 # CONFIG_BFIN533_EZKIT is not set
 # CONFIG_BFIN533_STAMP is not set
+# CONFIG_BLACKSTAMP is not set
 CONFIG_BFIN533_BLUETECHNIX_CM=y
 # CONFIG_H8606_HVSISTEMAS is not set
-# CONFIG_GENERIC_BF533_BOARD is not set
+# CONFIG_BFIN532_IP0X is not set
 
 #
 # BF533/2/1 Specific Configuration
@@ -188,6 +219,7 @@
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
@@ -207,13 +239,20 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=32
-CONFIG_MEM_ADD_WIDTH=9
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -240,6 +279,12 @@
 CONFIG_CACHELINE_ALIGNED_L1=y
 CONFIG_SYSCALL_TAB_L1=y
 CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -248,12 +293,16 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -262,10 +311,9 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
@@ -276,7 +324,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -301,12 +349,8 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+# CONFIG_PCCARD is not set
 
 #
 # Executable file formats
@@ -315,22 +359,19 @@
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -339,45 +380,13 @@
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP 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 is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
+# CONFIG_INET is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -385,31 +394,23 @@
 # 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_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -418,20 +419,22 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -444,12 +447,15 @@
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
+CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -460,6 +466,11 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
@@ -468,12 +479,16 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -489,36 +504,25 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI 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=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -526,34 +530,19 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_SMSC911X is not set
-# CONFIG_DM9000 is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
 # CONFIG_NETDEV_1000 is not set
-# CONFIG_AX88180 is not set
 # CONFIG_NETDEV_10000 is not set
 
 #
@@ -561,22 +550,17 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
 # CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
 # CONFIG_PHONE is not set
 
 #
@@ -593,16 +577,15 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
-# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_DMA_INTERFACE is not set
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
-# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_BFIN_SPI_ADC is not set
+# CONFIG_BFIN_SPORT is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -613,6 +596,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -623,176 +607,141 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
 
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_GPIOLIB is not set
 # 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
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_FB is not set
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# USB support
+# MMC/SD/SDIO Card Drivers
 #
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB_ARCH_HAS_EHCI is not set
-# CONFIG_USB is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# Enable Host or Gadget support to see Inventra options
+# MMC/SD/SDIO Host Controller Drivers
 #
-
-#
-# 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_MMC_SDHCI is not set
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
+# CONFIG_EXT4_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
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -801,8 +750,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
+CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -813,12 +765,8 @@
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -826,60 +774,106 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD 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
+# CONFIG_NILFS2_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-# CONFIG_DLM is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -888,34 +882,39 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_TOMOYO is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index d74b6f4..22e565c 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -1,13 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28.10
-# Wed Jun  3 06:27:41 2009
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
@@ -16,6 +16,9 @@
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -26,21 +29,40 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
@@ -49,7 +71,8 @@
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
@@ -65,12 +88,13 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -78,11 +102,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -98,7 +119,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -181,7 +201,8 @@
 CONFIG_IRQ_WATCH=13
 CONFIG_IRQ_SPI=10
 # CONFIG_BFIN537_STAMP is not set
-CONFIG_BFIN537_BLUETECHNIX_CM=y
+CONFIG_BFIN537_BLUETECHNIX_CM_E=y
+# CONFIG_BFIN537_BLUETECHNIX_CM_U is not set
 # CONFIG_BFIN537_BLUETECHNIX_TCM is not set
 # CONFIG_PNAV10 is not set
 # CONFIG_CAMSIG_MINOTAUR is not set
@@ -283,10 +304,12 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -297,10 +320,9 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
@@ -311,7 +333,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -337,6 +359,7 @@
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 
 #
 # Executable file formats
@@ -366,11 +389,6 @@
 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_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -394,7 +412,6 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
@@ -418,7 +435,9 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -429,8 +448,8 @@
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -441,16 +460,21 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 
 #
@@ -486,22 +510,26 @@
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
 CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
-# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
 
 #
 # Mapping drivers for chip access
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
 CONFIG_MTD_GPIO_ADDR=y
-CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -517,6 +545,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -533,9 +566,14 @@
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -549,6 +587,7 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -570,6 +609,9 @@
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
@@ -580,8 +622,11 @@
 CONFIG_BFIN_RX_DESC_NUM=20
 # CONFIG_BFIN_MAC_RMII is not set
 # CONFIG_SMC91X is not set
-# CONFIG_SMSC911X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -598,7 +643,10 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
@@ -622,15 +670,12 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
 CONFIG_BFIN_DMA_INTERFACE=m
 # CONFIG_BFIN_PPI is not set
 # CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
 # CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=y
-# CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_SIMPLE_GPIO is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_BFIN_JTAG_COMM is not set
@@ -644,6 +689,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -656,6 +702,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
@@ -668,7 +715,23 @@
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
-# CONFIG_SPI is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
@@ -688,15 +751,21 @@
 #
 # SPI GPIO expanders:
 #
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VT1211 is not set
@@ -758,21 +827,74 @@
 # CONFIG_USB is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
-# Enable Host or Gadget support to see Inventra options
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+CONFIG_USB_GADGET_NET2272=y
+CONFIG_USB_NET2272=m
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# OTG and related infrastructure
 #
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=m
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -789,9 +911,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -801,6 +924,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -809,8 +937,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -822,10 +953,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -833,9 +961,19 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_YAFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -844,14 +982,70 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
 # CONFIG_DLM is not set
 
 #
@@ -867,14 +1061,28 @@
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
 #
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_DEBUG_VERBOSE=y
@@ -888,9 +1096,10 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
@@ -899,8 +1108,9 @@
 CONFIG_SECURITY=y
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+# CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
 #
@@ -979,6 +1189,7 @@
 # Compression
 #
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
 # CONFIG_CRYPTO_LZO is not set
 
 #
@@ -986,19 +1197,24 @@
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
index 7fc8dfa1..efcc90d 100644
--- a/arch/blackfin/configs/CM-BF537U_defconfig
+++ b/arch/blackfin/configs/CM-BF537U_defconfig
@@ -1,94 +1,111 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.16
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
 # General setup
 #
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 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
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -105,6 +122,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -113,6 +131,10 @@
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -125,22 +147,31 @@
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 CONFIG_BF537=y
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=2
+CONFIG_BF_REV_MAX=3
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
 CONFIG_BF_REV_0_2=y
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
 CONFIG_MEM_MT48LC16M16A2TG_75=y
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_RTC=8
@@ -150,7 +181,6 @@
 CONFIG_IRQ_SPORT1_RX=9
 CONFIG_IRQ_SPORT1_TX=9
 CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
 CONFIG_IRQ_UART0_RX=10
 CONFIG_IRQ_UART0_TX=10
 CONFIG_IRQ_UART1_RX=10
@@ -169,11 +199,13 @@
 CONFIG_IRQ_MEM_DMA0=13
 CONFIG_IRQ_MEM_DMA1=13
 CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_SPI=10
 # CONFIG_BFIN537_STAMP is not set
-CONFIG_BFIN537_BLUETECHNIX_CM=y
+# CONFIG_BFIN537_BLUETECHNIX_CM_E is not set
+CONFIG_BFIN537_BLUETECHNIX_CM_U=y
+# CONFIG_BFIN537_BLUETECHNIX_TCM is not set
 # CONFIG_PNAV10 is not set
 # CONFIG_CAMSIG_MINOTAUR is not set
-# CONFIG_GENERIC_BF537_BOARD is not set
 
 #
 # BF537 Specific Configuration
@@ -196,6 +228,7 @@
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
@@ -215,13 +248,20 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=32
-CONFIG_MEM_ADD_WIDTH=9
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -248,6 +288,12 @@
 CONFIG_CACHELINE_ALIGNED_L1=y
 CONFIG_SYSCALL_TAB_L1=y
 CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -256,12 +302,16 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -270,10 +320,9 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
@@ -284,7 +333,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -309,12 +358,8 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+# CONFIG_PCCARD is not set
 
 #
 # Executable file formats
@@ -323,22 +368,19 @@
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -347,10 +389,6 @@
 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
@@ -369,15 +407,13 @@
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
 # CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -386,6 +422,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -395,29 +432,23 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -426,20 +457,22 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -452,12 +485,15 @@
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
+CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -468,20 +504,29 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
-# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
 
 #
 # Mapping drivers for chip access
 #
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_GPIO_ADDR=y
+# CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -497,36 +542,36 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI 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=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 
 #
-# Misc devices
+# EEPROM support
 #
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
@@ -534,35 +579,20 @@
 #
 # CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_BFIN_MAC is not set
-# CONFIG_SMSC911X is not set
-# CONFIG_DM9000 is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_ETHERNET is not set
 # CONFIG_NETDEV_1000 is not set
-# CONFIG_AX88180 is not set
 # CONFIG_NETDEV_10000 is not set
 
 #
@@ -570,22 +600,17 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
 # CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
 # CONFIG_PHONE is not set
 
 #
@@ -602,16 +627,15 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 CONFIG_BFIN_SPORT=y
-# CONFIG_BFIN_TIMER_LATENCY is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -622,6 +646,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -634,165 +659,201 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
 # CAN, the car bus and industrial fieldbus
 #
 # CONFIG_CAN4LINUX is not set
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
 
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 
 #
-# SPI support
+# Memory mapped GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
 
 #
-# Dallas's 1-wire bus
+# I2C GPIO expanders:
 #
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SHT15 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_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
 # Graphics support
 #
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_FB is not set
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
-# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
 # CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
 CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
 # CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
 CONFIG_USB_GADGET_NET2272=y
 CONFIG_USB_NET2272=y
 # CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
 # CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_AT91 is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
-# CONFIG_USB_ETH is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_MMC is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
 
 #
-# LED devices
+# OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -802,25 +863,29 @@
 # CONFIG_EXT2_FS_POSIX_ACL is not set
 # CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS 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_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -829,8 +894,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -841,12 +909,8 @@
 CONFIG_SYSFS=y
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -854,18 +918,29 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
 # CONFIG_SMB_FS is not set
@@ -873,41 +948,94 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
 # CONFIG_DLM is not set
 
 #
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -916,34 +1044,40 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_TOMOYO is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index acca4e5..7f579cf 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.4
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -16,6 +16,9 @@
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -26,79 +29,100 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
-CONFIG_UID16=y
+# CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
+CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 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
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_AS is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_AS is not set
 # CONFIG_DEFAULT_DEADLINE is not set
 # CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -107,6 +131,10 @@
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -119,19 +147,29 @@
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 # CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
-CONFIG_BF548=y
+# CONFIG_BF547M is not set
+CONFIG_BF548_std=y
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
-CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_2 is not set
 # CONFIG_BF_REV_0_3 is not set
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
-# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_0_6 is not set
+CONFIG_BF_REV_ANY=y
 # CONFIG_BF_REV_NONE is not set
 CONFIG_BF54x=y
 CONFIG_IRQ_PLL_WAKEUP=7
@@ -140,15 +178,12 @@
 CONFIG_IRQ_SPORT0_TX=9
 CONFIG_IRQ_SPORT1_RX=9
 CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_SPI0=10
 CONFIG_IRQ_UART0_RX=10
 CONFIG_IRQ_UART0_TX=10
 CONFIG_IRQ_UART1_RX=10
 CONFIG_IRQ_UART1_TX=10
 CONFIG_IRQ_CNT=8
-CONFIG_IRQ_USB_INT0=11
-CONFIG_IRQ_USB_INT1=11
-CONFIG_IRQ_USB_INT2=11
-CONFIG_IRQ_USB_DMA=11
 CONFIG_IRQ_TIMER0=11
 CONFIG_IRQ_TIMER1=11
 CONFIG_IRQ_TIMER2=11
@@ -157,9 +192,21 @@
 CONFIG_IRQ_TIMER5=11
 CONFIG_IRQ_TIMER6=11
 CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
 CONFIG_IRQ_TIMER8=11
 CONFIG_IRQ_TIMER9=11
 CONFIG_IRQ_TIMER10=11
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
 # CONFIG_BFIN548_EZKIT is not set
 CONFIG_BFIN548_BLUETECHNIX_CM=y
 
@@ -167,6 +214,7 @@
 # BF548 Specific Configuration
 #
 # CONFIG_DEB_DMA_URGENT is not set
+# CONFIG_BF548_ATAPI_ALTERNATIVE_PORT is not set
 
 #
 # Interrupt Priority Assignment
@@ -182,7 +230,6 @@
 CONFIG_IRQ_SPI0_ERR=7
 CONFIG_IRQ_UART0_ERR=7
 CONFIG_IRQ_EPPI0=8
-CONFIG_IRQ_SPI0=10
 CONFIG_IRQ_PINT0=12
 CONFIG_IRQ_PINT1=12
 CONFIG_IRQ_MDMAS0=13
@@ -197,18 +244,10 @@
 CONFIG_IRQ_UART1_ERR=7
 CONFIG_IRQ_UART2_ERR=7
 CONFIG_IRQ_CAN0_ERR=7
-CONFIG_IRQ_SPORT2_RX=9
-CONFIG_IRQ_SPORT2_TX=9
-CONFIG_IRQ_SPORT3_RX=9
-CONFIG_IRQ_SPORT3_TX=9
 CONFIG_IRQ_EPPI1=9
 CONFIG_IRQ_EPPI2=9
-CONFIG_IRQ_SPI1=10
-CONFIG_IRQ_SPI2=10
 CONFIG_IRQ_ATAPI_RX=10
 CONFIG_IRQ_ATAPI_TX=10
-CONFIG_IRQ_TWI0=11
-CONFIG_IRQ_TWI1=11
 CONFIG_IRQ_CAN0_RX=11
 CONFIG_IRQ_CAN0_TX=11
 CONFIG_IRQ_MDMAS2=13
@@ -255,6 +294,7 @@
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
@@ -274,16 +314,12 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 # CONFIG_GENERIC_TIME is not set
-# CONFIG_TICK_ONESHOT is not set
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=64
-# CONFIG_MEM_MT46V32M16_6T is not set
-CONFIG_MEM_MT46V32M16_5B=y
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -310,6 +346,12 @@
 CONFIG_CACHELINE_ALIGNED_L1=y
 # CONFIG_SYSCALL_TAB_L1 is not set
 # CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -318,13 +360,16 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -333,14 +378,13 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+# CONFIG_BFIN_L2_ICACHEABLE is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
-CONFIG_BFIN_EXTMEM_WRITEBACK=y
-# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
-# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_EXTMEM_WRITEBACK
+CONFIG_BFIN_EXTMEM_WRITETHROUGH=y
 # CONFIG_BFIN_L2_DCACHEABLE is not set
 
 #
@@ -349,7 +393,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -369,7 +413,7 @@
 CONFIG_BANK_0=0x7BB0
 CONFIG_BANK_1=0x5554
 CONFIG_BANK_2=0x7BB0
-CONFIG_BANK_3=0x99B2
+CONFIG_BANK_3=0x99B3
 CONFIG_EBIU_MBSCTLVAL=0x0
 CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
@@ -377,7 +421,6 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
 
@@ -388,23 +431,19 @@
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 # CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
 CONFIG_NET=y
 
 #
@@ -417,6 +456,7 @@
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -435,19 +475,16 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -456,6 +493,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -465,24 +503,21 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -501,10 +536,12 @@
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -539,6 +576,7 @@
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
 CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
@@ -549,9 +587,8 @@
 #
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_GPIO_ADDR is not set
 # CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
@@ -575,6 +612,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -587,31 +629,31 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
+CONFIG_SCSI=m
 CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
-# CONFIG_SCSI_PROC_FS is not set
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
 #
-CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SD=m
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 # CONFIG_CHR_DEV_SCH is not set
 
@@ -632,29 +674,54 @@
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_SMC91X is not set
-CONFIG_SMSC911X=y
 # CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMSC911X=y
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -666,6 +733,10 @@
 # CONFIG_WLAN_80211 is not set
 
 #
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -676,7 +747,6 @@
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -711,6 +781,7 @@
 # CONFIG_KEYBOARD_GPIO is not set
 # CONFIG_KEYBOARD_BFIN is not set
 # CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_ADP5588 is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
@@ -726,19 +797,16 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_OTP=y
-# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+# CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
-# CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_TWI_LCD is not set
-# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_BFIN_TWI_LCD is not set
 # CONFIG_VT is not set
-# CONFIG_DEVKMEM is not set
+CONFIG_DEVKMEM=y
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -749,10 +817,11 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
-CONFIG_SERIAL_BFIN_DMA=y
-# CONFIG_SERIAL_BFIN_PIO is not set
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
 # CONFIG_SERIAL_BFIN_UART0 is not set
 CONFIG_SERIAL_BFIN_UART1=y
 # CONFIG_BFIN_UART1_CTSRTS is not set
@@ -762,7 +831,10 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
 
 #
 # CAN, the car bus and industrial fieldbus
@@ -770,61 +842,53 @@
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
+CONFIG_I2C_HELPER_AUTO=y
 
 #
 # I2C Hardware Bus support
 #
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
 CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_TINY_USB is not set
 
 #
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_EEPROM_LEGACY is not set
 # CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
-# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
-
-CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
-
-#
-# SPI support
-#
 CONFIG_SPI=y
 CONFIG_SPI_MASTER=y
 
@@ -832,64 +896,23 @@
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 
@@ -903,25 +926,43 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
-# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -935,80 +976,75 @@
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
+# CONFIG_HID_SUPPORT is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
-CONFIG_USB=y
+CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
 #
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
 # CONFIG_USB_SL811_HCD is not set
 # CONFIG_USB_R8A66597_HCD is not set
-CONFIG_USB_MUSB_HDRC=y
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
 CONFIG_USB_MUSB_SOC=y
 
 #
-# Blackfin BF54x, BF525 and BF527 high speed USB support
+# Blackfin high speed USB Support
 #
-CONFIG_USB_MUSB_HOST=y
-# CONFIG_USB_MUSB_PERIPHERAL is not set
+# CONFIG_USB_MUSB_HOST is not set
+CONFIG_USB_MUSB_PERIPHERAL=y
 # CONFIG_USB_MUSB_OTG is not set
-CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
 # CONFIG_MUSB_PIO_ONLY is not set
-# CONFIG_USB_INVENTRA_DMA is not set
+CONFIG_USB_INVENTRA_DMA=y
 # CONFIG_USB_TI_CPPI_DMA is not set
-CONFIG_USB_MUSB_LOGLEVEL=0
+# CONFIG_USB_MUSB_DEBUG is not set
 
 #
 # USB Device Class drivers
 #
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
-CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
 # CONFIG_USB_STORAGE_USBAT is not set
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1016,6 +1052,7 @@
 # CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1023,15 +1060,10 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
 
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -1040,7 +1072,7 @@
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
 # CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
@@ -1048,7 +1080,6 @@
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -1056,38 +1087,75 @@
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2272 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+# CONFIG_USB_ETH_RNDIS is not set
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+# CONFIG_USB_CDC_COMPOSITE is not set
 
 #
-# USB DSL modem support
+# OTG and related infrastructure
 #
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-CONFIG_MMC=y
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=m
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
 #
-CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK=m
 CONFIG_MMC_BLOCK_BOUNCE=y
 # CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
 #
-CONFIG_SDH_BFIN=y
+# CONFIG_MMC_SDHCI is not set
+CONFIG_SDH_BFIN=m
+# CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND is not set
+# CONFIG_SDH_BFIN_ENABLE_SDIO_IRQ is not set
 # CONFIG_MMC_SPI is not set
-# CONFIG_SPI_MMC is not set
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_DEBUG is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
 
 #
 # RTC interfaces
@@ -1111,66 +1179,74 @@
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
 
 #
 # SPI RTC drivers
 #
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
 # CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
 
 #
 # Platform RTC drivers
 #
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
 # CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 
 #
 # on-CPU RTC drivers
 #
-CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+CONFIG_RTC_DRV_BFIN=m
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
 #
-# CONFIG_EXT2_FS is not set
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_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
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
+# CONFIG_ISO9660_FS is not set
 # CONFIG_UDF_FS is not set
 
 #
@@ -1194,10 +1270,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -1205,17 +1278,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 CONFIG_JFFS2_FS_WRITEBUFFER=y
 # CONFIG_JFFS2_FS_WBUF_VERIFY is not set
@@ -1227,34 +1290,30 @@
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
+# CONFIG_NFSD is not set
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-CONFIG_CIFS=y
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
@@ -1267,24 +1326,8 @@
 #
 # Partition Types
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-# CONFIG_SYSV68_PARTITION is not set
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
@@ -1326,9 +1369,6 @@
 CONFIG_NLS_KOI8_U=m
 CONFIG_NLS_UTF8=m
 # CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
@@ -1336,14 +1376,39 @@
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
-CONFIG_DEBUG_MMRS=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
+# CONFIG_DEBUG_MMRS is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1352,33 +1417,125 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
-# CONFIG_SECURITY_ROOTPLUG is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index bae4ee6..a6df01d 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -1,15 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.4
-# Tue Apr  1 10:50:11 2008
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -17,6 +16,9 @@
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -27,62 +29,83 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_EVENTFD=y
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_NP2 is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
 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
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
 # IO Schedulers
@@ -99,6 +122,7 @@
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
 
 #
 # Blackfin Processor Options
@@ -107,6 +131,10 @@
 #
 # Processor and Board Settings
 #
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
 # CONFIG_BF522 is not set
 # CONFIG_BF523 is not set
 # CONFIG_BF524 is not set
@@ -119,30 +147,47 @@
 # CONFIG_BF534 is not set
 # CONFIG_BF536 is not set
 # CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 CONFIG_BF561=y
+# CONFIG_SMP is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=5
 # CONFIG_BF_REV_0_0 is not set
 # CONFIG_BF_REV_0_1 is not set
 # CONFIG_BF_REV_0_2 is not set
 CONFIG_BF_REV_0_3=y
 # CONFIG_BF_REV_0_4 is not set
 # CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
 # CONFIG_BF_REV_ANY is not set
 # CONFIG_BF_REV_NONE is not set
-CONFIG_BFIN_DUAL_CORE=y
 CONFIG_MEM_MT48LC8M32B2B5_7=y
 CONFIG_IRQ_PLL_WAKEUP=7
 CONFIG_IRQ_SPORT0_ERROR=7
 CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_TIMER0=10
+CONFIG_IRQ_TIMER1=10
+CONFIG_IRQ_TIMER2=10
+CONFIG_IRQ_TIMER3=10
+CONFIG_IRQ_TIMER4=10
+CONFIG_IRQ_TIMER5=10
+CONFIG_IRQ_TIMER6=10
+CONFIG_IRQ_TIMER7=10
 CONFIG_IRQ_SPI_ERROR=7
 # CONFIG_BFIN561_EZKIT is not set
 # CONFIG_BFIN561_TEPLA is not set
 CONFIG_BFIN561_BLUETECHNIX_CM=y
-# CONFIG_GENERIC_BF561_BOARD is not set
 
 #
 # BF561 Specific Configuration
@@ -151,12 +196,7 @@
 #
 # Core B Support
 #
-
-#
-# Core B Support
-#
 CONFIG_BF561_COREB=y
-# CONFIG_BF561_COREB_RESET is not set
 
 #
 # Interrupt Priority Assignment
@@ -196,14 +236,6 @@
 CONFIG_IRQ_DMA2_9=9
 CONFIG_IRQ_DMA2_10=9
 CONFIG_IRQ_DMA2_11=9
-CONFIG_IRQ_TIMER0=10
-CONFIG_IRQ_TIMER1=10
-CONFIG_IRQ_TIMER2=10
-CONFIG_IRQ_TIMER3=10
-CONFIG_IRQ_TIMER4=10
-CONFIG_IRQ_TIMER5=10
-CONFIG_IRQ_TIMER6=10
-CONFIG_IRQ_TIMER7=10
 CONFIG_IRQ_TIMER8=10
 CONFIG_IRQ_TIMER9=10
 CONFIG_IRQ_TIMER10=10
@@ -226,6 +258,7 @@
 # Board customizations
 #
 # CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
 
 #
 # Clock/PLL Setup
@@ -245,19 +278,20 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 
 #
-# Memory Setup
+# Misc
 #
-CONFIG_MAX_MEM_SIZE=32
-CONFIG_BOOT_LOAD=0x1000
 CONFIG_BFIN_SCRATCH_REG_RETN=y
 # CONFIG_BFIN_SCRATCH_REG_RETE is not set
 # CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -284,6 +318,12 @@
 CONFIG_CACHELINE_ALIGNED_L1=y
 CONFIG_SYSCALL_TAB_L1=y
 CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
 CONFIG_RAMKERNEL=y
 # CONFIG_ROMKERNEL is not set
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -292,14 +332,16 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
-CONFIG_LARGE_ALLOCS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
+# CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -308,15 +350,16 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
+# CONFIG_BFIN_L2_ICACHEABLE is not set
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
-CONFIG_BFIN_EXTMEM_WRITEBACK=y
-# CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
-# CONFIG_BFIN_L2_ICACHEABLE is not set
+# CONFIG_BFIN_EXTMEM_WRITEBACK is not set
+CONFIG_BFIN_EXTMEM_WRITETHROUGH=y
 # CONFIG_BFIN_L2_DCACHEABLE is not set
+# CONFIG_BFIN_L2_WRITEBACK is not set
+# CONFIG_BFIN_L2_WRITETHROUGH is not set
 
 #
 # Memory Protection Unit
@@ -324,7 +367,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -353,8 +396,8 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-# CONFIG_PCI is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 
 #
 # Executable file formats
@@ -363,18 +406,19 @@
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
 CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
 
 #
-# Networking
+# CPU Frequency scaling
 #
+# CONFIG_CPU_FREQ is not set
 CONFIG_NET=y
 
 #
@@ -383,10 +427,6 @@
 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
@@ -407,14 +447,11 @@
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-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_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -423,6 +460,7 @@
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
@@ -432,24 +470,21 @@
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN 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_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -460,16 +495,22 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
 
 #
 # User Modules And Translation Layers
@@ -487,8 +528,10 @@
 #
 # RAM/ROM/Flash chip drivers
 #
-# CONFIG_MTD_CFI is not set
+CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
 CONFIG_MTD_MAP_BANK_WIDTH_1=y
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
 CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -499,20 +542,29 @@
 CONFIG_MTD_CFI_I2=y
 # CONFIG_MTD_CFI_I4 is not set
 # CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
-# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
 #
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
@@ -528,6 +580,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -539,14 +596,21 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
-# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE0 is not set
-# CONFIG_BFIN_IDE_ADDRESS_MAPPING_MODE1 is not set
 
 #
 # SCSI device support
@@ -558,26 +622,50 @@
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_SMC91X=y
-# CONFIG_SMSC911X is not set
+# CONFIG_SMC91X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+CONFIG_SMSC911X=m
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
 # CONFIG_NETDEV_1000 is not set
-# CONFIG_AX88180 is not set
 # CONFIG_NETDEV_10000 is not set
 
 #
@@ -585,10 +673,13 @@
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -609,16 +700,15 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
 # CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPI_ADC is not set
 # CONFIG_BFIN_SPORT is not set
-# CONFIG_BFIN_TIMER_LATENCY is not set
-# CONFIG_SIMPLE_GPIO is not set
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -629,6 +719,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -639,6 +730,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
@@ -647,54 +739,100 @@
 # CONFIG_CAN4LINUX is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
 
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 
 #
-# SPI support
+# Memory mapped GPIO expanders:
 #
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADCXX is not set
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SHT15 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_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
 # Sonics Silicon Backplane
 #
-CONFIG_SSB_POSSIBLE=y
 # CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
 #
+# CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
 # CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
 # CONFIG_DAB is not set
 
 #
@@ -709,42 +847,85 @@
 # Display device support
 #
 # CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
 # CONFIG_SOUND is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 # CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
-# Enable Host or Gadget support to see Inventra options
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+CONFIG_USB_GADGET_NET2272=y
+CONFIG_USB_NET2272=m
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+# CONFIG_USB_CDC_COMPOSITE is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# USB Gadget Support
+# MMC/SD/SDIO Card Drivers
 #
-# CONFIG_USB_GADGET is not set
-# CONFIG_MMC is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_STAGING is not set
 
 #
 # File systems
@@ -754,25 +935,29 @@
 # CONFIG_EXT2_FS_POSIX_ACL is not set
 # CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS 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_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -781,8 +966,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -794,10 +982,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -805,14 +990,28 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
@@ -827,11 +1026,47 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
 # CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
@@ -839,14 +1074,40 @@
 # CONFIG_PRINTK_TIME is not set
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
 CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_DOUBLEFAULT is not set
 CONFIG_DEBUG_HUNT_FOR_ZERO=y
 CONFIG_DEBUG_BFIN_HWTRACE_ON=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -855,33 +1116,40 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
-# CONFIG_DUAL_CORE_TEST_MODULE is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_SECURITY_TOMOYO is not set
 # CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=m
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
index a6a7c8e..bc7fae3 100644
--- a/arch/blackfin/configs/H8606_defconfig
+++ b/arch/blackfin/configs/H8606_defconfig
@@ -67,6 +67,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
@@ -249,6 +250,7 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_LARGE_ALLOCS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index 1ec9ae2..a7e49d6 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -68,6 +68,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
@@ -261,6 +262,7 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_LARGE_ALLOCS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
 # CONFIG_DMA_UNCACHED_2M is not set
 CONFIG_DMA_UNCACHED_1M=y
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index ff377fa..67d1276 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -63,6 +63,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
@@ -285,6 +286,7 @@
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=y
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index 814f9ca..52bfa6b 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -72,6 +72,7 @@
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_RT_MUTEXES=y
 CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
@@ -271,6 +272,7 @@
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_LARGE_ALLOCS=y
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_DMA_UNCACHED_2M=y
 # CONFIG_DMA_UNCACHED_1M is not set
 # CONFIG_DMA_UNCACHED_NONE is not set
@@ -700,7 +702,7 @@
 # CONFIG_INPUT_YEALINK is not set
 CONFIG_INPUT_UINPUT=y
 # CONFIG_BF53X_PFBUTTONS is not set
-# CONFIG_TWI_KEYPAD is not set
+# CONFIG_INPUT_PCF8574 is not set
 
 #
 # Hardware I/O ports
diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig
index 375e75a..60adfad 100644
--- a/arch/blackfin/configs/TCM-BF537_defconfig
+++ b/arch/blackfin/configs/TCM-BF537_defconfig
@@ -1,13 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Jan  6 09:22:17 2009
+# Linux kernel version: 2.6.30.5
 #
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 CONFIG_BLACKFIN=y
+CONFIG_GENERIC_BUG=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
@@ -16,6 +16,9 @@
 CONFIG_GENERIC_GPIO=y
 CONFIG_FORCE_MAX_ZONEORDER=14
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -26,49 +29,72 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 # CONFIG_UID16 is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 # CONFIG_ELF_CORE is not set
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 # CONFIG_AIO is not set
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -76,11 +102,8 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -96,7 +119,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -128,10 +150,15 @@
 # CONFIG_BF538 is not set
 # CONFIG_BF539 is not set
 # CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
 # CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
 # CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
 # CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
 # CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
 # CONFIG_BF561 is not set
 CONFIG_BF_REV_MIN=2
 CONFIG_BF_REV_MAX=3
@@ -173,11 +200,11 @@
 CONFIG_IRQ_WATCH=13
 CONFIG_IRQ_SPI=10
 # CONFIG_BFIN537_STAMP is not set
-# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM_E is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM_U is not set
 CONFIG_BFIN537_BLUETECHNIX_TCM=y
 # CONFIG_PNAV10 is not set
 # CONFIG_CAMSIG_MINOTAUR is not set
-# CONFIG_GENERIC_BF537_BOARD is not set
 
 #
 # BF537 Specific Configuration
@@ -223,7 +250,10 @@
 # CONFIG_SCHED_HRTICK is not set
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_TICKSOURCE_GPTMR0 is not set
+CONFIG_TICKSOURCE_CORETMR=y
 # CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_GPTMR0_CLOCKSOURCE is not set
 # CONFIG_NO_HZ is not set
 # CONFIG_HIGH_RES_TIMERS is not set
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -273,10 +303,12 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 # CONFIG_BFIN_GPTIMERS is not set
 # CONFIG_DMA_UNCACHED_4M is not set
 # CONFIG_DMA_UNCACHED_2M is not set
@@ -287,10 +319,9 @@
 # Cache Support
 #
 CONFIG_BFIN_ICACHE=y
-# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_DCACHE=y
 # CONFIG_BFIN_DCACHE_BANKA is not set
-CONFIG_BFIN_EXTMEM_ICACHEABLE=y
 CONFIG_BFIN_EXTMEM_DCACHEABLE=y
 CONFIG_BFIN_EXTMEM_WRITEBACK=y
 # CONFIG_BFIN_EXTMEM_WRITETHROUGH is not set
@@ -301,7 +332,7 @@
 # CONFIG_MPU is not set
 
 #
-# Asynchonous Memory Configuration
+# Asynchronous Memory Configuration
 #
 
 #
@@ -327,6 +358,7 @@
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 
 #
 # Executable file formats
@@ -343,13 +375,83 @@
 #
 # CONFIG_PM is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
 
 #
 # CPU Frequency scaling
 #
 # CONFIG_CPU_FREQ is not set
-# CONFIG_NET is not set
+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_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=y
+# CONFIG_INET_DIAG is not set
+# 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_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -358,15 +460,21 @@
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AR7_PARTS is not set
 
 #
@@ -402,9 +510,10 @@
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+# CONFIG_MTD_PSD4256G is not set
 CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
-# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ROM=m
 # CONFIG_MTD_ABSENT is not set
 
 #
@@ -413,7 +522,7 @@
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 # CONFIG_MTD_PHYSMAP is not set
 CONFIG_MTD_GPIO_ADDR=y
-CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_UCLINUX is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -436,6 +545,11 @@
 # CONFIG_MTD_ONENAND is not set
 
 #
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
@@ -443,15 +557,23 @@
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -464,6 +586,74 @@
 # CONFIG_SCSI_NETLINK is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
 # CONFIG_PHONE is not set
 
 #
@@ -480,15 +670,12 @@
 #
 # Character devices
 #
-# CONFIG_AD9960 is not set
-# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PPIFCD is not set
-# CONFIG_BFIN_SIMPLE_TIMER is not set
-# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
-# CONFIG_BFIN_TIMER_LATENCY is not set
 CONFIG_BFIN_DMA_INTERFACE=m
-# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_BFIN_PPI is not set
+# CONFIG_BFIN_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BFIN_SPI_ADC is not set
+CONFIG_BFIN_SPORT=y
 # CONFIG_VT is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_BFIN_JTAG_COMM is not set
@@ -502,6 +689,7 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_MAX3100 is not set
 CONFIG_SERIAL_BFIN=y
 CONFIG_SERIAL_BFIN_CONSOLE=y
 CONFIG_SERIAL_BFIN_DMA=y
@@ -514,6 +702,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_BFIN_SPORT is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 # CONFIG_LEGACY_PTYS is not set
 
 #
@@ -534,39 +723,17 @@
 #
 CONFIG_SPI_BFIN=y
 # CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BFIN_SPORT is not set
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
 
 #
 # SPI Protocol Masters
 #
-# CONFIG_EEPROM_AT25 is not set
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-CONFIG_GPIOLIB=y
-# CONFIG_DEBUG_GPIO is not set
-CONFIG_GPIO_SYSFS=y
-
-#
-# Memory mapped GPIO expanders:
-#
-
-#
-# I2C GPIO expanders:
-#
-# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCF857X is not set
-
-#
-# PCI GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
@@ -580,6 +747,12 @@
 #
 # CONFIG_SOFT_WATCHDOG is not set
 CONFIG_BFIN_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -588,7 +761,7 @@
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
 
 #
 # Multimedia devices
@@ -598,6 +771,7 @@
 # Multimedia core support
 #
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
 # CONFIG_VIDEO_MEDIA is not set
 
 #
@@ -618,13 +792,81 @@
 #
 # CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_DEBUG_FS is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+CONFIG_USB_GADGET_NET2272=y
+CONFIG_USB_NET2272=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=m
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -641,8 +883,10 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -652,6 +896,11 @@
 # CONFIG_FUSE_FS is not set
 
 #
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
 # CD-ROM/DVD Filesystems
 #
 # CONFIG_ISO9660_FS is not set
@@ -660,8 +909,11 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -673,10 +925,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -684,9 +933,19 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -695,13 +954,62 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
+# CONFIG_DLM is not set
 
 #
 # Kernel hacking
@@ -714,12 +1022,30 @@
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_SECTION_MISMATCH=y
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_DEBUG_VERBOSE=y
@@ -733,9 +1059,10 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
+CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
 CONFIG_ACCESS_CHECK=y
+# CONFIG_BFIN_ISRAM_SELF_TEST is not set
 
 #
 # Security options
@@ -744,20 +1071,110 @@
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
-# CONFIG_CRC32 is not set
-# CONFIG_CRC7 is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
-CONFIG_PLIST=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_LZMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/blackfin/include/asm/asm-offsets.h b/arch/blackfin/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/blackfin/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h
index 10064f9..e6485c3 100644
--- a/arch/blackfin/include/asm/bfin-global.h
+++ b/arch/blackfin/include/asm/bfin-global.h
@@ -11,9 +11,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <asm/sections.h>
-#include <asm/ptrace.h>
-#include <asm/user.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
 
@@ -23,6 +20,12 @@
 # define DMA_UNCACHED_REGION (2 * 1024 * 1024)
 #elif defined(CONFIG_DMA_UNCACHED_1M)
 # define DMA_UNCACHED_REGION (1024 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_512K)
+# define DMA_UNCACHED_REGION (512 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_256K)
+# define DMA_UNCACHED_REGION (256 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_128K)
+# define DMA_UNCACHED_REGION (128 * 1024)
 #else
 # define DMA_UNCACHED_REGION (0)
 #endif
@@ -35,6 +38,7 @@
 extern unsigned long sclk_to_usecs(unsigned long sclk);
 extern unsigned long usecs_to_sclk(unsigned long usecs);
 
+struct pt_regs;
 extern void dump_bfin_process(struct pt_regs *regs);
 extern void dump_bfin_mem(struct pt_regs *regs);
 extern void dump_bfin_trace_buffer(void);
diff --git a/arch/blackfin/include/asm/bfin-lq035q1.h b/arch/blackfin/include/asm/bfin-lq035q1.h
new file mode 100644
index 0000000..57bc21a
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin-lq035q1.h
@@ -0,0 +1,28 @@
+/*
+ * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
+ *
+ * Copyright 2008-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef BFIN_LQ035Q1_H
+#define BFIN_LQ035Q1_H
+
+#define LQ035_RL	(0 << 8)	/* Right -> Left Scan */
+#define LQ035_LR	(1 << 8)	/* Left -> Right Scan */
+#define LQ035_TB	(1 << 9)	/* Top -> Botton Scan */
+#define LQ035_BT	(0 << 9)	/* Botton -> Top Scan */
+#define LQ035_BGR	(1 << 11)	/* Use BGR format */
+#define LQ035_RGB	(0 << 11)	/* Use RGB format */
+#define LQ035_NORM	(1 << 13)	/* Reversal */
+#define LQ035_REV	(0 << 13)	/* Reversal */
+
+struct bfin_lq035q1fb_disp_info {
+
+	unsigned	mode;
+	/* GPIOs */
+	int		use_bl;
+	unsigned 	gpio_bl;
+};
+
+#endif /* BFIN_LQ035Q1_H */
diff --git a/arch/blackfin/include/asm/bug.h b/arch/blackfin/include/asm/bug.h
index 6f4548a..75f6dc3 100644
--- a/arch/blackfin/include/asm/bug.h
+++ b/arch/blackfin/include/asm/bug.h
@@ -47,7 +47,7 @@
 #define BUG()								\
 	do {								\
 		_BUG_OR_WARN(0);					\
-		for (;;);						\
+		unreachable();						\
 	} while (0)
 
 #define WARN_ON(condition)							\
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h
index 417eaac..2666ff8 100644
--- a/arch/blackfin/include/asm/cacheflush.h
+++ b/arch/blackfin/include/asm/cacheflush.h
@@ -10,6 +10,7 @@
 #define _BLACKFIN_CACHEFLUSH_H
 
 #include <asm/blackfin.h>	/* for SSYNC() */
+#include <asm/sections.h>	/* for _ramend */
 
 extern void blackfin_icache_flush_range(unsigned long start_address, unsigned long end_address);
 extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
diff --git a/arch/blackfin/include/asm/checksum.h b/arch/blackfin/include/asm/checksum.h
index a23415b..623cc7f 100644
--- a/arch/blackfin/include/asm/checksum.h
+++ b/arch/blackfin/include/asm/checksum.h
@@ -9,63 +9,12 @@
 #define _BFIN_CHECKSUM_H
 
 /*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-__wsum csum_partial_copy(const void *src, void *dst,
-			       int len, __wsum sum);
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-
-extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-					  int len, __wsum sum, int *csum_err);
-
-#define csum_partial_copy_nocheck(src, dst, len, sum)	\
-	csum_partial_copy((src), (dst), (len), (sum))
-
-__sum16 ip_fast_csum(unsigned char *iph, unsigned int ihl);
-
-/*
- *	Fold a partial checksum
- */
-
-static inline __sum16 csum_fold(__wsum sum)
-{
-	while (sum >> 16)
-		sum = (sum & 0xffff) + (sum >> 16);
-	return ((~(sum << 16)) >> 16);
-}
-
-/*
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
 
 static inline __wsum
-csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+__csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
 		   unsigned short proto, __wsum sum)
 {
 	unsigned int carry;
@@ -88,19 +37,8 @@
 
 	return (sum);
 }
+#define csum_tcpudp_nofold __csum_tcpudp_nofold
 
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-		  unsigned short proto, __wsum sum)
-{
-	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
-}
+#include <asm-generic/checksum.h>
 
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-
-extern __sum16 ip_compute_csum(const void *buff, int len);
-
-#endif				/* _BFIN_CHECKSUM_H */
+#endif
diff --git a/arch/blackfin/include/asm/clocks.h b/arch/blackfin/include/asm/clocks.h
index f80dad5..6f0b618 100644
--- a/arch/blackfin/include/asm/clocks.h
+++ b/arch/blackfin/include/asm/clocks.h
@@ -9,6 +9,8 @@
 #ifndef _BFIN_CLOCKS_H
 #define _BFIN_CLOCKS_H
 
+#include <asm/dpmc.h>
+
 #ifdef CONFIG_CCLK_DIV_1
 # define CONFIG_CCLK_ACT_DIV   CCLK_DIV1
 # define CONFIG_CCLK_DIV 1
diff --git a/arch/blackfin/include/asm/dma-mapping.h b/arch/blackfin/include/asm/dma-mapping.h
index 7a23d82..f9172ff 100644
--- a/arch/blackfin/include/asm/dma-mapping.h
+++ b/arch/blackfin/include/asm/dma-mapping.h
@@ -7,9 +7,9 @@
 #ifndef _BLACKFIN_DMA_MAPPING_H
 #define _BLACKFIN_DMA_MAPPING_H
 
-#include <asm/scatterlist.h>
+#include <asm/cacheflush.h>
+struct scatterlist;
 
-void dma_alloc_init(unsigned long start, unsigned long end);
 void *dma_alloc_coherent(struct device *dev, size_t size,
 			 dma_addr_t *dma_handle, gfp_t gfp);
 void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
@@ -20,13 +20,51 @@
  */
 #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)
+#define dma_supported(d, m)         (1)
+#define dma_get_cache_alignment()   (32)
+#define dma_is_consistent(d, h)     (1)
 
-static inline
-int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	*dev->dma_mask = dma_mask;
+
+	return 0;
+}
+
+static inline int
+dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 	return 0;
 }
 
+extern void
+__dma_sync(dma_addr_t addr, size_t size, enum dma_data_direction dir);
+static inline void
+_dma_sync(dma_addr_t addr, size_t size, enum dma_data_direction dir)
+{
+	if (!__builtin_constant_p(dir)) {
+		__dma_sync(addr, size, dir);
+		return;
+	}
+
+	switch (dir) {
+	case DMA_NONE:
+		BUG();
+	case DMA_TO_DEVICE:		/* writeback only */
+		flush_dcache_range(addr, addr + size);
+		break;
+	case DMA_FROM_DEVICE: /* invalidate only */
+	case DMA_BIDIRECTIONAL: /* flush and invalidate */
+		/* Blackfin has no dedicated invalidate (it includes a flush) */
+		invalidate_dcache_range(addr, addr + size);
+		break;
+	}
+}
+
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.
  * The 32-bit bus address to use is returned.
@@ -34,8 +72,13 @@
  * Once the device is given the dma address, the device owns this memory
  * until either pci_unmap_single or pci_dma_sync_single is performed.
  */
-extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-				 enum dma_data_direction direction);
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+	       enum dma_data_direction dir)
+{
+	_dma_sync((dma_addr_t)ptr, size, dir);
+	return (dma_addr_t) ptr;
+}
 
 static inline dma_addr_t
 dma_map_page(struct device *dev, struct page *page,
@@ -53,8 +96,12 @@
  * After this call, reads by the cpu to the buffer are guarenteed to see
  * whatever the device wrote there.
  */
-extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-			  enum dma_data_direction direction);
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction dir)
+{
+	BUG_ON(!valid_dma_direction(dir));
+}
 
 static inline void
 dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
@@ -80,38 +127,66 @@
  * the same here.
  */
 extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		      enum dma_data_direction direction);
+		      enum dma_data_direction dir);
 
 /*
  * Unmap a set of streaming mode DMA translations.
  * Again, cpu read rules concerning calls here are the same as for
  * pci_unmap_single() above.
  */
-extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-		      int nhwentries, enum dma_data_direction direction);
-
-static inline void dma_sync_single_for_cpu(struct device *dev,
-					dma_addr_t handle, size_t size,
-					enum dma_data_direction dir)
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	     int nhwentries, enum dma_data_direction dir)
 {
+	BUG_ON(!valid_dma_direction(dir));
 }
 
-static inline void dma_sync_single_for_device(struct device *dev,
-					dma_addr_t handle, size_t size,
-					enum dma_data_direction dir)
+static inline void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction dir)
 {
+	BUG_ON(!valid_dma_direction(dir));
 }
 
-static inline void dma_sync_sg_for_cpu(struct device *dev,
-					struct scatterlist *sg,
-					int nents, enum dma_data_direction dir)
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t handle,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction dir)
 {
+	_dma_sync(handle + offset, size, dir);
 }
 
-static inline void dma_sync_sg_for_device(struct device *dev,
-					struct scatterlist *sg,
-					int nents, enum dma_data_direction dir)
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
+			enum dma_data_direction dir)
 {
+	dma_sync_single_range_for_cpu(dev, handle, 0, size, dir);
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
+			   enum dma_data_direction dir)
+{
+	dma_sync_single_range_for_device(dev, handle, 0, size, dir);
+}
+
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
+		    enum dma_data_direction dir)
+{
+	BUG_ON(!valid_dma_direction(dir));
+}
+
+extern void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+		       int nents, enum dma_data_direction dir);
+
+static inline void
+dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+	       enum dma_data_direction dir)
+{
+	_dma_sync((dma_addr_t)vaddr, size, dir);
 }
 
 #endif				/* _BLACKFIN_DMA_MAPPING_H */
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index c9a5962..bd2e622 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -10,46 +10,70 @@
 
 #include <linux/interrupt.h>
 #include <mach/dma.h>
+#include <asm/atomic.h>
 #include <asm/blackfin.h>
 #include <asm/page.h>
+#include <asm-generic/dma.h>
 
-#define MAX_DMA_ADDRESS PAGE_OFFSET
+/* DMA_CONFIG Masks */
+#define DMAEN			0x0001	/* DMA Channel Enable */
+#define WNR				0x0002	/* Channel Direction (W/R*) */
+#define WDSIZE_8		0x0000	/* Transfer Word Size = 8 */
+#define WDSIZE_16		0x0004	/* Transfer Word Size = 16 */
+#define WDSIZE_32		0x0008	/* Transfer Word Size = 32 */
+#define DMA2D			0x0010	/* DMA Mode (2D/1D*) */
+#define RESTART			0x0020	/* DMA Buffer Clear */
+#define DI_SEL			0x0040	/* Data Interrupt Timing Select */
+#define DI_EN			0x0080	/* Data Interrupt Enable */
+#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1 */
+#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2 */
+#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3 */
+#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4 */
+#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5 */
+#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6 */
+#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7 */
+#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8 */
+#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9 */
+#define NDSIZE			0x0f00	/* Next Descriptor Size */
+#define DMAFLOW			0x7000	/* Flow Control */
+#define DMAFLOW_STOP	0x0000	/* Stop Mode */
+#define DMAFLOW_AUTO	0x1000	/* Autobuffer Mode */
+#define DMAFLOW_ARRAY	0x4000	/* Descriptor Array Mode */
+#define DMAFLOW_SMALL	0x6000	/* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE	0x7000	/* Large Model Descriptor List Mode */
 
-/*****************************************************************************
-*        Generic DMA  Declarations
-*
-****************************************************************************/
-enum dma_chan_status {
-	DMA_CHANNEL_FREE,
-	DMA_CHANNEL_REQUESTED,
-	DMA_CHANNEL_ENABLED,
-};
+/* DMA_IRQ_STATUS Masks */
+#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status */
+#define DMA_ERR			0x0002	/* DMA Error Interrupt Status */
+#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator */
+#define DMA_RUN			0x0008	/* DMA Channel Running Indicator */
 
 /*-------------------------
  * config reg bits value
  *-------------------------*/
-#define DATA_SIZE_8 		0
-#define DATA_SIZE_16 		1
-#define DATA_SIZE_32 		2
+#define DATA_SIZE_8			0
+#define DATA_SIZE_16		1
+#define DATA_SIZE_32		2
 
-#define DMA_FLOW_STOP 		0
-#define DMA_FLOW_AUTO 		1
-#define DMA_FLOW_ARRAY 		4
-#define DMA_FLOW_SMALL 		6
-#define DMA_FLOW_LARGE 		7
+#define DMA_FLOW_STOP		0
+#define DMA_FLOW_AUTO		1
+#define DMA_FLOW_ARRAY		4
+#define DMA_FLOW_SMALL		6
+#define DMA_FLOW_LARGE		7
 
-#define DIMENSION_LINEAR    0
-#define DIMENSION_2D           1
+#define DIMENSION_LINEAR	0
+#define DIMENSION_2D		1
 
-#define DIR_READ     0
-#define DIR_WRITE    1
+#define DIR_READ			0
+#define DIR_WRITE			1
 
-#define INTR_DISABLE   0
-#define INTR_ON_BUF    2
-#define INTR_ON_ROW    3
+#define INTR_DISABLE		0
+#define INTR_ON_BUF			2
+#define INTR_ON_ROW			3
 
 #define DMA_NOSYNC_KEEP_DMA_BUF	0
-#define DMA_SYNC_RESTART	1
+#define DMA_SYNC_RESTART		1
 
 struct dmasg {
 	void *next_desc_addr;
@@ -104,11 +128,9 @@
 
 };
 
-struct mutex;
 struct dma_channel {
-	struct mutex dmalock;
 	const char *device_id;
-	enum dma_chan_status chan_status;
+	atomic_t chan_status;
 	volatile struct dma_register *regs;
 	struct dmasg *sg;		/* large mode descriptor */
 	unsigned int irq;
@@ -220,27 +242,20 @@
 
 static inline int dma_channel_active(unsigned int channel)
 {
-	if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE)
-		return 0;
-	else
-		return 1;
+	return atomic_read(&dma_ch[channel].chan_status);
 }
 
 static inline void disable_dma(unsigned int channel)
 {
 	dma_ch[channel].regs->cfg &= ~DMAEN;
 	SSYNC();
-	dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
 }
 static inline void enable_dma(unsigned int channel)
 {
 	dma_ch[channel].regs->curr_x_count = 0;
 	dma_ch[channel].regs->curr_y_count = 0;
 	dma_ch[channel].regs->cfg |= DMAEN;
-	dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
 }
-void free_dma(unsigned int channel);
-int request_dma(unsigned int channel, const char *device_id);
 int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
 
 static inline void dma_disable_irq(unsigned int channel)
diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h
index 925e66c..1597ae5 100644
--- a/arch/blackfin/include/asm/dpmc.h
+++ b/arch/blackfin/include/asm/dpmc.h
@@ -1,7 +1,7 @@
 /*
  * Miscellaneous IOCTL commands for Dynamic Power Management Controller Driver
  *
- * Copyright (C) 2004-2008 Analog Device Inc.
+ * Copyright (C) 2004-2009 Analog Device Inc.
  *
  * Licensed under the GPL-2
  */
@@ -9,7 +9,109 @@
 #ifndef _BLACKFIN_DPMC_H_
 #define _BLACKFIN_DPMC_H_
 
-#ifdef __KERNEL__
+/* PLL_CTL Masks */
+#define DF			0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2 */
+#define PLL_OFF			0x0002	/* PLL Not Powered */
+#define STOPCK			0x0008	/* Core Clock Off */
+#define PDWN			0x0020	/* Enter Deep Sleep Mode */
+#ifdef __ADSPBF539__
+# define IN_DELAY		0x0014	/* Add 200ps Delay To EBIU Input Latches */
+# define OUT_DELAY		0x00C0	/* Add 200ps Delay To EBIU Output Signals */
+#else
+# define IN_DELAY		0x0040	/* Add 200ps Delay To EBIU Input Latches */
+# define OUT_DELAY		0x0080	/* Add 200ps Delay To EBIU Output Signals */
+#endif
+#define BYPASS			0x0100	/* Bypass the PLL */
+#define MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors */
+#define SPORT_HYST		0x8000	/* Enable Additional Hysteresis on SPORT Input Pins */
+#define SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
+
+/* PLL_DIV Masks */
+#define SSEL			0x000F	/* System Select */
+#define CSEL			0x0030	/* Core Select */
+#define CSEL_DIV1		0x0000	/* CCLK = VCO / 1 */
+#define CSEL_DIV2		0x0010	/* CCLK = VCO / 2 */
+#define CSEL_DIV4		0x0020	/* CCLK = VCO / 4 */
+#define CSEL_DIV8		0x0030	/* CCLK = VCO / 8 */
+
+#define CCLK_DIV1 CSEL_DIV1
+#define CCLK_DIV2 CSEL_DIV2
+#define CCLK_DIV4 CSEL_DIV4
+#define CCLK_DIV8 CSEL_DIV8
+
+#define SET_SSEL(x)	((x) & 0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
+#define SCLK_DIV(x)	(x)		/* SCLK = VCO / x */
+
+/* PLL_STAT Masks */
+#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled */
+#define FULL_ON			0x0002	/* Processor In Full On Mode */
+#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled */
+#define PLL_LOCKED		0x0020	/* PLL_LOCKCNT Has Been Reached */
+
+#define RTCWS			0x0400	/* RTC/Reset Wake-Up Status */
+#define CANWS			0x0800	/* CAN Wake-Up Status */
+#define USBWS			0x2000	/* USB Wake-Up Status */
+#define KPADWS			0x4000	/* Keypad Wake-Up Status */
+#define ROTWS			0x8000	/* Rotary Wake-Up Status */
+#define GPWS			0x1000	/* General-Purpose Wake-Up Status */
+
+/* VR_CTL Masks */
+#if defined(__ADSPBF52x__) || defined(__ADSPBF51x__)
+#define FREQ			0x3000	/* Switching Oscillator Frequency For Regulator */
+#define FREQ_1000		0x3000	/* Switching Frequency Is 1 MHz */
+#else
+#define FREQ			0x0003	/* Switching Oscillator Frequency For Regulator */
+#define FREQ_333		0x0001	/* Switching Frequency Is 333 kHz */
+#define FREQ_667		0x0002	/* Switching Frequency Is 667 kHz */
+#define FREQ_1000		0x0003	/* Switching Frequency Is 1 MHz */
+#endif
+#define HIBERNATE		0x0000	/* Powerdown/Bypass On-Board Regulation */
+
+#define GAIN			0x000C	/* Voltage Level Gain */
+#define GAIN_5			0x0000	/* GAIN = 5 */
+#define GAIN_10			0x0004	/* GAIN = 1 */
+#define GAIN_20			0x0008	/* GAIN = 2 */
+#define GAIN_50			0x000C	/* GAIN = 5 */
+
+#define VLEV			0x00F0	/* Internal Voltage Level */
+#ifdef __ADSPBF52x__
+#define VLEV_085 		0x0040	/* VLEV = 0.85 V (-5% - +10% Accuracy) */
+#define VLEV_090		0x0050	/* VLEV = 0.90 V (-5% - +10% Accuracy) */
+#define VLEV_095		0x0060	/* VLEV = 0.95 V (-5% - +10% Accuracy) */
+#define VLEV_100		0x0070	/* VLEV = 1.00 V (-5% - +10% Accuracy) */
+#define VLEV_105		0x0080	/* VLEV = 1.05 V (-5% - +10% Accuracy) */
+#define VLEV_110		0x0090	/* VLEV = 1.10 V (-5% - +10% Accuracy) */
+#define VLEV_115		0x00A0	/* VLEV = 1.15 V (-5% - +10% Accuracy) */
+#define VLEV_120		0x00B0	/* VLEV = 1.20 V (-5% - +10% Accuracy) */
+#else
+#define VLEV_085 		0x0060	/* VLEV = 0.85 V (-5% - +10% Accuracy) */
+#define VLEV_090		0x0070	/* VLEV = 0.90 V (-5% - +10% Accuracy) */
+#define VLEV_095		0x0080	/* VLEV = 0.95 V (-5% - +10% Accuracy) */
+#define VLEV_100		0x0090	/* VLEV = 1.00 V (-5% - +10% Accuracy) */
+#define VLEV_105		0x00A0	/* VLEV = 1.05 V (-5% - +10% Accuracy) */
+#define VLEV_110		0x00B0	/* VLEV = 1.10 V (-5% - +10% Accuracy) */
+#define VLEV_115		0x00C0	/* VLEV = 1.15 V (-5% - +10% Accuracy) */
+#define VLEV_120		0x00D0	/* VLEV = 1.20 V (-5% - +10% Accuracy) */
+#define VLEV_125		0x00E0	/* VLEV = 1.25 V (-5% - +10% Accuracy) */
+#define VLEV_130		0x00F0	/* VLEV = 1.30 V (-5% - +10% Accuracy) */
+#endif
+
+#define WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate */
+#define CANWE			0x0200	/* Enable CAN Wakeup From Hibernate */
+#define PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate */
+#define GPWE			0x0400	/* General-Purpose Wake-Up Enable */
+#define MXVRWE			0x0400	/* Enable MXVR Wakeup From Hibernate */
+#define KPADWE			0x1000	/* Keypad Wake-Up Enable */
+#define ROTWE			0x2000	/* Rotary Wake-Up Enable */
+#define CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
+#define SCKELOW			0x8000	/* Do Not Drive SCKE High During Reset After Hibernate */
+
+#if defined(__ADSPBF52x__) || defined(__ADSPBF51x__)
+#define USBWE			0x0200	/* Enable USB Wakeup From Hibernate */
+#else
+#define USBWE			0x0800	/* Enable USB Wakeup From Hibernate */
+#endif
+
 #ifndef __ASSEMBLY__
 
 void sleep_mode(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
@@ -54,6 +156,5 @@
 	w[P0 + (x - PLL_CTL)] = R0;\
 
 #endif
-#endif	/* __KERNEL__ */
 
 #endif	/*_BLACKFIN_DPMC_H_*/
diff --git a/arch/blackfin/include/asm/elf.h b/arch/blackfin/include/asm/elf.h
index 8e0764c..5b50f0e 100644
--- a/arch/blackfin/include/asm/elf.h
+++ b/arch/blackfin/include/asm/elf.h
@@ -55,7 +55,6 @@
 	_regs->p2	= _dynamic_addr;				\
 } while(0)
 
-#define USE_ELF_CORE_DUMP
 #define ELF_FDPIC_CORE_EFLAGS	EF_BFIN_FDPIC
 #define ELF_EXEC_PAGESIZE	4096
 
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 5b44d05..539468a 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -159,6 +159,11 @@
 };
 #endif
 
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+void bfin_special_gpio_free(unsigned gpio);
+int bfin_special_gpio_request(unsigned gpio, const char *label);
+#endif
+
 #ifdef CONFIG_PM
 
 unsigned int bfin_pm_standby_setup(void);
diff --git a/arch/blackfin/include/asm/gptimers.h b/arch/blackfin/include/asm/gptimers.h
index 89f08de..c722acd 100644
--- a/arch/blackfin/include/asm/gptimers.h
+++ b/arch/blackfin/include/asm/gptimers.h
@@ -172,25 +172,25 @@
 
 /* The actual gptimer API */
 
-void     set_gptimer_pwidth(int timer_id, uint32_t width);
-uint32_t get_gptimer_pwidth(int timer_id);
-void     set_gptimer_period(int timer_id, uint32_t period);
-uint32_t get_gptimer_period(int timer_id);
-uint32_t get_gptimer_count(int timer_id);
-int      get_gptimer_intr(int timer_id);
-void     clear_gptimer_intr(int timer_id);
-int      get_gptimer_over(int timer_id);
-void     clear_gptimer_over(int timer_id);
-void     set_gptimer_config(int timer_id, uint16_t config);
-uint16_t get_gptimer_config(int timer_id);
-int      get_gptimer_run(int timer_id);
-void     set_gptimer_pulse_hi(int timer_id);
-void     clear_gptimer_pulse_hi(int timer_id);
+void     set_gptimer_pwidth(unsigned int timer_id, uint32_t width);
+uint32_t get_gptimer_pwidth(unsigned int timer_id);
+void     set_gptimer_period(unsigned int timer_id, uint32_t period);
+uint32_t get_gptimer_period(unsigned int timer_id);
+uint32_t get_gptimer_count(unsigned int timer_id);
+int      get_gptimer_intr(unsigned int timer_id);
+void     clear_gptimer_intr(unsigned int timer_id);
+int      get_gptimer_over(unsigned int timer_id);
+void     clear_gptimer_over(unsigned int timer_id);
+void     set_gptimer_config(unsigned int timer_id, uint16_t config);
+uint16_t get_gptimer_config(unsigned int timer_id);
+int      get_gptimer_run(unsigned int timer_id);
+void     set_gptimer_pulse_hi(unsigned int timer_id);
+void     clear_gptimer_pulse_hi(unsigned int timer_id);
 void     enable_gptimers(uint16_t mask);
 void     disable_gptimers(uint16_t mask);
 void     disable_gptimers_sync(uint16_t mask);
 uint16_t get_enabled_gptimers(void);
-uint32_t get_gptimer_status(int group);
-void     set_gptimer_status(int group, uint32_t value);
+uint32_t get_gptimer_status(unsigned int group);
+void     set_gptimer_status(unsigned int group, uint32_t value);
 
 #endif
diff --git a/arch/blackfin/include/asm/io.h b/arch/blackfin/include/asm/io.h
index d1f5029..29e55b9 100644
--- a/arch/blackfin/include/asm/io.h
+++ b/arch/blackfin/include/asm/io.h
@@ -31,12 +31,14 @@
 	unsigned int val;
 	int tmp;
 
-	__asm__ __volatile__ ("cli %1;\n\t"
-			"NOP; NOP; SSYNC;\n\t"
-			"%0 = b [%2] (z);\n\t"
-			"sti %1;\n\t"
-			: "=d"(val), "=d"(tmp): "a"(addr)
-			);
+	__asm__ __volatile__ (
+		"cli %1;"
+		"NOP; NOP; SSYNC;"
+		"%0 = b [%2] (z);"
+		"sti %1;"
+		: "=d"(val), "=d"(tmp)
+		: "a"(addr)
+	);
 
 	return (unsigned char) val;
 }
@@ -46,12 +48,14 @@
 	unsigned int val;
 	int tmp;
 
-	__asm__ __volatile__ ("cli %1;\n\t"
-			"NOP; NOP; SSYNC;\n\t"
-			"%0 = w [%2] (z);\n\t"
-			"sti %1;\n\t"
-		      	: "=d"(val), "=d"(tmp): "a"(addr)
-			);
+	__asm__ __volatile__ (
+		"cli %1;"
+		"NOP; NOP; SSYNC;"
+		"%0 = w [%2] (z);"
+		"sti %1;"
+		: "=d"(val), "=d"(tmp)
+		: "a"(addr)
+	);
 
 	return (unsigned short) val;
 }
@@ -61,20 +65,23 @@
 	unsigned int val;
 	int tmp;
 
-	__asm__ __volatile__ ("cli %1;\n\t"
-			"NOP; NOP; SSYNC;\n\t"
-			"%0 = [%2];\n\t"
-			"sti %1;\n\t"
-		      	: "=d"(val), "=d"(tmp): "a"(addr)
-			);
+	__asm__ __volatile__ (
+		"cli %1;"
+		"NOP; NOP; SSYNC;"
+		"%0 = [%2];"
+		"sti %1;"
+		: "=d"(val), "=d"(tmp)
+		: "a"(addr)
+	);
+
 	return val;
 }
 
 #endif /*  __ASSEMBLY__ */
 
-#define writeb(b,addr) (void)((*(volatile unsigned char *) (addr)) = (b))
-#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
-#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
+#define writeb(b, addr) (void)((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b, addr) (void)((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
 
 #define __raw_readb readb
 #define __raw_readw readw
@@ -82,9 +89,9 @@
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+#define memset_io(a, b, c)	memset((void *)(a), (b), (c))
+#define memcpy_fromio(a, b, c)	memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c)	memcpy((void *)(a), (b), (c))
 
 /* Convert "I/O port addresses" to actual addresses.  i.e. ugly casts. */
 #define __io(port) ((void *)(unsigned long)(port))
@@ -92,30 +99,30 @@
 #define inb(port)    readb(__io(port))
 #define inw(port)    readw(__io(port))
 #define inl(port)    readl(__io(port))
-#define outb(x,port) writeb(x,__io(port))
-#define outw(x,port) writew(x,__io(port))
-#define outl(x,port) writel(x,__io(port))
+#define outb(x, port) writeb(x, __io(port))
+#define outw(x, port) writew(x, __io(port))
+#define outl(x, port) writel(x, __io(port))
 
 #define inb_p(port)    inb(__io(port))
 #define inw_p(port)    inw(__io(port))
 #define inl_p(port)    inl(__io(port))
-#define outb_p(x,port) outb(x,__io(port))
-#define outw_p(x,port) outw(x,__io(port))
-#define outl_p(x,port) outl(x,__io(port))
+#define outb_p(x, port) outb(x, __io(port))
+#define outw_p(x, port) outw(x, __io(port))
+#define outl_p(x, port) outl(x, __io(port))
 
-#define ioread8_rep(a,d,c)	readsb(a,d,c)
-#define ioread16_rep(a,d,c)	readsw(a,d,c)
-#define ioread32_rep(a,d,c)	readsl(a,d,c)
-#define iowrite8_rep(a,s,c)	writesb(a,s,c)
-#define iowrite16_rep(a,s,c)	writesw(a,s,c)
-#define iowrite32_rep(a,s,c)	writesl(a,s,c)
+#define ioread8_rep(a, d, c)	readsb(a, d, c)
+#define ioread16_rep(a, d, c)	readsw(a, d, c)
+#define ioread32_rep(a, d, c)	readsl(a, d, c)
+#define iowrite8_rep(a, s, c)	writesb(a, s, c)
+#define iowrite16_rep(a, s, c)	writesw(a, s, c)
+#define iowrite32_rep(a, s, c)	writesl(a, s, c)
 
-#define ioread8(X)			readb(X)
-#define ioread16(X)			readw(X)
-#define ioread32(X)			readl(X)
-#define iowrite8(val,X)			writeb(val,X)
-#define iowrite16(val,X)		writew(val,X)
-#define iowrite32(val,X)		writel(val,X)
+#define ioread8(x)			readb(x)
+#define ioread16(x)			readw(x)
+#define ioread32(x)			readl(x)
+#define iowrite8(val, x)		writeb(val, x)
+#define iowrite16(val, x)		writew(val, x)
+#define iowrite32(val, x)		writel(val, x)
 
 #define mmiowb() wmb()
 
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index 4617ba6..d3b40449 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -35,9 +35,9 @@
 #include <asm/atomic.h>
 #include <asm/traps.h>
 
-#define IPIPE_ARCH_STRING     "1.11-00"
+#define IPIPE_ARCH_STRING     "1.12-00"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    11
+#define IPIPE_MINOR_NUMBER    12
 #define IPIPE_PATCH_NUMBER    0
 
 #ifdef CONFIG_SMP
@@ -124,16 +124,6 @@
 	return 1;
 }
 
-static inline void __ipipe_lock_root(void)
-{
-	set_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
-}
-
-static inline void __ipipe_unlock_root(void)
-{
-	clear_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status));
-}
-
 void __ipipe_enable_pipeline(void);
 
 #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h
index 490098f..0040920 100644
--- a/arch/blackfin/include/asm/ipipe_base.h
+++ b/arch/blackfin/include/asm/ipipe_base.h
@@ -51,23 +51,15 @@
 
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
 
-#define __ipipe_stall_root()						\
-	do {								\
-		volatile unsigned long *p = &__ipipe_root_status;	\
-		set_bit(0, p);						\
-	} while (0)
+void __ipipe_stall_root(void);
 
-#define __ipipe_test_and_stall_root()					\
-	({								\
-		volatile unsigned long *p = &__ipipe_root_status;	\
-		test_and_set_bit(0, p);					\
-	})
+unsigned long __ipipe_test_and_stall_root(void);
 
-#define __ipipe_test_root()					\
-	({							\
-		const unsigned long *p = &__ipipe_root_status;	\
-		test_bit(0, p);					\
-	})
+unsigned long __ipipe_test_root(void);
+
+void __ipipe_lock_root(void);
+
+void __ipipe_unlock_root(void);
 
 #endif /* !__ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index 9b19a19..813a1af 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -33,6 +33,7 @@
 
 #ifdef CONFIG_IPIPE
 
+#include <linux/compiler.h>
 #include <linux/ipipe_base.h>
 #include <linux/ipipe_trace.h>
 
@@ -49,12 +50,12 @@
 		barrier();				\
 	} while (0)
 
-static inline void raw_local_irq_enable(void)
-{
-	barrier();
-	ipipe_check_context(ipipe_root_domain);
-	__ipipe_unstall_root();
-}
+#define raw_local_irq_enable()				\
+	do {						\
+		barrier();				\
+		ipipe_check_context(ipipe_root_domain);	\
+		__ipipe_unstall_root();			\
+	} while (0)
 
 #define raw_local_save_flags_ptr(x)					\
 	do {								\
diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h
index c8b256d..8651afe 100644
--- a/arch/blackfin/include/asm/kgdb.h
+++ b/arch/blackfin/include/asm/kgdb.h
@@ -10,9 +10,6 @@
 
 #include <linux/ptrace.h>
 
-/* gdb locks */
-#define KGDB_MAX_NO_CPUS 8
-
 /*
  * BUFMAX defines the maximum number of characters in inbound/outbound buffers.
  * At least NUMREGBYTES*2 are needed for register packets.
diff --git a/arch/blackfin/include/asm/mem_init.h b/arch/blackfin/include/asm/mem_init.h
index 4179e32..7c8fe83 100644
--- a/arch/blackfin/include/asm/mem_init.h
+++ b/arch/blackfin/include/asm/mem_init.h
@@ -295,156 +295,3 @@
 #else
 #define PLL_BYPASS       0
 #endif
-
-/***************************************Currently Not Being Used *********************************/
-
-#if defined(CONFIG_FLASH_SPEED_BWAT) && \
-defined(CONFIG_FLASH_SPEED_BRAT) && \
-defined(CONFIG_FLASH_SPEED_BHT) && \
-defined(CONFIG_FLASH_SPEED_BST) && \
-defined(CONFIG_FLASH_SPEED_BTT)
-
-#define flash_EBIU_AMBCTL_WAT  ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_RAT  ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_HT   ((CONFIG_FLASH_SPEED_BHT  * 4) / (4000000000 / CONFIG_SCLK_HZ))
-#define flash_EBIU_AMBCTL_ST   ((CONFIG_FLASH_SPEED_BST  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_TT   ((CONFIG_FLASH_SPEED_BTT  * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-
-#if (flash_EBIU_AMBCTL_TT > 3)
-#define flash_EBIU_AMBCTL0_TT   B0TT_4
-#endif
-#if (flash_EBIU_AMBCTL_TT == 3)
-#define flash_EBIU_AMBCTL0_TT   B0TT_3
-#endif
-#if (flash_EBIU_AMBCTL_TT == 2)
-#define flash_EBIU_AMBCTL0_TT   B0TT_2
-#endif
-#if (flash_EBIU_AMBCTL_TT < 2)
-#define flash_EBIU_AMBCTL0_TT   B0TT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_ST > 3)
-#define flash_EBIU_AMBCTL0_ST   B0ST_4
-#endif
-#if (flash_EBIU_AMBCTL_ST == 3)
-#define flash_EBIU_AMBCTL0_ST   B0ST_3
-#endif
-#if (flash_EBIU_AMBCTL_ST == 2)
-#define flash_EBIU_AMBCTL0_ST   B0ST_2
-#endif
-#if (flash_EBIU_AMBCTL_ST < 2)
-#define flash_EBIU_AMBCTL0_ST   B0ST_1
-#endif
-
-#if (flash_EBIU_AMBCTL_HT > 2)
-#define flash_EBIU_AMBCTL0_HT   B0HT_3
-#endif
-#if (flash_EBIU_AMBCTL_HT == 2)
-#define flash_EBIU_AMBCTL0_HT   B0HT_2
-#endif
-#if (flash_EBIU_AMBCTL_HT == 1)
-#define flash_EBIU_AMBCTL0_HT   B0HT_1
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
-#define flash_EBIU_AMBCTL0_HT   B0HT_0
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
-#define flash_EBIU_AMBCTL0_HT   B0HT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_WAT > 14)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_15
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 14)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_14
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 13)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_13
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 12)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_12
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 11)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_11
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 10)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_10
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 9)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_9
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 8)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_8
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 7)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_7
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 6)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_6
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 5)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_5
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 4)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_4
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 3)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_3
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 2)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_2
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 1)
-#define flash_EBIU_AMBCTL0_WAT  B0WAT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_RAT > 14)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_15
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 14)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_14
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 13)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_13
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 12)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_12
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 11)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_11
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 10)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_10
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 9)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_9
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 8)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_8
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 7)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_7
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 6)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_6
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 5)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_5
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 4)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_4
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 3)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_3
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 2)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_2
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 1)
-#define flash_EBIU_AMBCTL0_RAT  B0RAT_1
-#endif
-
-#define flash_EBIU_AMBCTL0  \
-	(flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
-	 flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
-#endif
diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h
index 4a3be37..ae8ef4f 100644
--- a/arch/blackfin/include/asm/mmu_context.h
+++ b/arch/blackfin/include/asm/mmu_context.h
@@ -66,8 +66,8 @@
 
 #define activate_mm(prev, next) switch_mm(prev, next, NULL)
 
-static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
-			     struct task_struct *tsk)
+static inline void __switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
+			       struct task_struct *tsk)
 {
 #ifdef CONFIG_MPU
 	unsigned int cpu = smp_processor_id();
@@ -95,7 +95,24 @@
 #endif
 }
 
+#ifdef CONFIG_IPIPE
+#define lock_mm_switch(flags)	local_irq_save_hw_cond(flags)
+#define unlock_mm_switch(flags)	local_irq_restore_hw_cond(flags)
+#else
+#define lock_mm_switch(flags)	do { (void)(flags); } while (0)
+#define unlock_mm_switch(flags)	do { (void)(flags); } while (0)
+#endif /* CONFIG_IPIPE */
+
 #ifdef CONFIG_MPU
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	unsigned long flags;
+	lock_mm_switch(flags);
+	__switch_mm(prev, next, tsk);
+	unlock_mm_switch(flags);
+}
+
 static inline void protect_page(struct mm_struct *mm, unsigned long addr,
 				unsigned long flags)
 {
@@ -128,6 +145,12 @@
 		set_mask_dcplbs(mm->context.page_rwx_mask, cpu);
 	}
 }
+#else /* !CONFIG_MPU */
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	__switch_mm(prev, next, tsk);
+}
 #endif
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
@@ -173,4 +196,10 @@
 #endif
 }
 
+#define ipipe_mm_switch_protect(flags)		\
+	local_irq_save_hw_cond(flags)
+
+#define ipipe_mm_switch_unprotect(flags)	\
+	local_irq_restore_hw_cond(flags)
+
 #endif
diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h
index 9c1cfff..4282b16 100644
--- a/arch/blackfin/include/asm/module.h
+++ b/arch/blackfin/include/asm/module.h
@@ -7,8 +7,6 @@
 #ifndef _ASM_BFIN_MODULE_H
 #define _ASM_BFIN_MODULE_H
 
-#define MODULE_SYMBOL_PREFIX "_"
-
 #define Elf_Shdr        Elf32_Shdr
 #define Elf_Sym         Elf32_Sym
 #define Elf_Ehdr        Elf32_Ehdr
diff --git a/arch/blackfin/include/asm/pci.h b/arch/blackfin/include/asm/pci.h
index 6127735..99cae2e 100644
--- a/arch/blackfin/include/asm/pci.h
+++ b/arch/blackfin/include/asm/pci.h
@@ -4,145 +4,19 @@
 #define _ASM_BFIN_PCI_H
 
 #include <asm/scatterlist.h>
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci.h>
 
-/*
- *
- * Written by Wout Klaren.
- */
-
-/* Added by Chang Junxiao */
 #define PCIBIOS_MIN_IO 0x00001000
 #define PCIBIOS_MIN_MEM 0x10000000
 
-#define PCI_DMA_BUS_IS_PHYS       (1)
-struct pci_ops;
-
-/*
- * Structure with hardware dependent information and functions of the
- * PCI bus.
- */
-struct pci_bus_info {
-
-	/*
-	 * Resources of the PCI bus.
-	 */
-	struct resource mem_space;
-	struct resource io_space;
-
-	/*
-	 * System dependent functions.
-	 */
-	struct pci_ops *bfin_pci_ops;
-	void (*fixup) (int pci_modify);
-	void (*conf_device) (unsigned char bus, unsigned char device_fn);
-};
-
-#define pcibios_assign_all_busses()	0
 static inline void pcibios_set_master(struct pci_dev *dev)
 {
-
 	/* No special bus mastering setup handling */
 }
 static inline void pcibios_penalize_isa_irq(int irq)
 {
-
 	/* We don't do dynamic PCI IRQ allocation */
 }
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-					size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-
-	 /* return virt_to_bus(ptr); */
-	return (dma_addr_t) ptr;
-}
-
-/* Unmap a single streaming mode DMA translation.  The dma_addr and size
- * must match what was provided for in a previous pci_map_single call.  All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guarenteed to see
- * whatever the device wrote there.
- */
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-				    size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-
-	/* Nothing to do */
-}
-
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scather-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
-static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			     int nents, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-	return nents;
-}
-
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
-static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-				int nents, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-
-	/* Nothing to do */
-}
-
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single(struct pci_dev *hwdev,
-				       dma_addr_t dma_handle, size_t size,
-				       int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-
-	/* Nothing to do */
-}
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
-				   struct scatterlist *sg, int nelems,
-				   int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		BUG();
-
-	/* Nothing to do */
-}
 
 #endif				/* _ASM_BFIN_PCI_H */
diff --git a/arch/blackfin/include/asm/ptrace.h b/arch/blackfin/include/asm/ptrace.h
index 27290c9..b33a448 100644
--- a/arch/blackfin/include/asm/ptrace.h
+++ b/arch/blackfin/include/asm/ptrace.h
@@ -89,9 +89,9 @@
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13	/* ptrace signal  */
 
-#define PTRACE_GETFDPIC           31
-#define PTRACE_GETFDPIC_EXEC      0
-#define PTRACE_GETFDPIC_INTERP    1
+#define PTRACE_GETFDPIC           31	/* get the ELF fdpic loadmap address */
+#define PTRACE_GETFDPIC_EXEC       0	/* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP     1	/* [addr] request the interpreter loadmap */
 
 #define PS_S  (0x0002)
 
diff --git a/arch/blackfin/include/asm/sections.h b/arch/blackfin/include/asm/sections.h
index 1f5381f..42f6c53 100644
--- a/arch/blackfin/include/asm/sections.h
+++ b/arch/blackfin/include/asm/sections.h
@@ -13,10 +13,18 @@
 extern unsigned long _ramstart, _ramend, _rambase;
 extern unsigned long memory_start, memory_end, physical_mem_end;
 
-extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[],
-	_ebss_l1[], _l1_lma_start[], _sdata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
-	_stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[],
-	_ebss_l2[], _l2_lma_start[];
+/*
+ * The weak markings on the lengths might seem weird, but this is required
+ * in order to make gcc accept the fact that these may actually have a value
+ * of 0 (since they aren't actually addresses, but sizes of sections).
+ */
+extern char _stext_l1[], _etext_l1[], _text_l1_lma[], __weak _text_l1_len[];
+extern char _sdata_l1[], _edata_l1[], _sbss_l1[], _ebss_l1[],
+	_data_l1_lma[], __weak _data_l1_len[];
+extern char _sdata_b_l1[], _edata_b_l1[], _sbss_b_l1[], _ebss_b_l1[],
+	_data_b_l1_lma[], __weak _data_b_l1_len[];
+extern char _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[],
+	_sbss_l2[], _ebss_l2[], _l2_lma[], __weak _l2_len[];
 
 #include <asm/mem_map.h>
 
diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h
index afb3a86..a40d936 100644
--- a/arch/blackfin/include/asm/thread_info.h
+++ b/arch/blackfin/include/asm/thread_info.h
@@ -103,11 +103,13 @@
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_FREEZE              6       /* is freezing for suspend */
 #define TIF_IRQ_SYNC            7       /* sync pipeline stage */
+#define TIF_NOTIFY_RESUME       8       /* callback before returning to user */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_FREEZE             (1<<TIF_FREEZE)
diff --git a/arch/blackfin/include/asm/trace.h b/arch/blackfin/include/asm/trace.h
index 609ad3c..dc0aa55 100644
--- a/arch/blackfin/include/asm/trace.h
+++ b/arch/blackfin/include/asm/trace.h
@@ -28,6 +28,8 @@
 
 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
 
+#define trace_buffer_init() bfin_write_TBUFCTL(BFIN_TRACE_INIT)
+
 #define trace_buffer_save(x) \
 	do { \
 		(x) = bfin_read_TBUFCTL(); \
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h
index c03b853..1c0d190 100644
--- a/arch/blackfin/include/asm/uaccess.h
+++ b/arch/blackfin/include/asm/uaccess.h
@@ -17,9 +17,7 @@
 #include <linux/string.h>
 
 #include <asm/segment.h>
-#ifdef CONFIG_ACCESS_CHECK
-# include <asm/bfin-global.h>
-#endif
+#include <asm/sections.h>
 
 #define get_ds()        (KERNEL_DS)
 #define get_fs()        (current_thread_info()->addr_limit)
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 779be02..22886cb 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -388,8 +388,9 @@
 #define __NR_pwritev		367
 #define __NR_rt_tgsigqueueinfo	368
 #define __NR_perf_event_open	369
+#define __NR_recvmmsg		370
 
-#define __NR_syscall		370
+#define __NR_syscall		371
 #define NR_syscalls		__NR_syscall
 
 /* Old optional stuff no one actually uses */
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 3946aff..924c002 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -37,9 +37,8 @@
 	printk(KERN_INFO "Blackfin DMA Controller\n");
 
 	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
-		dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+		atomic_set(&dma_ch[i].chan_status, 0);
 		dma_ch[i].regs = dma_io_base_addr[i];
-		mutex_init(&(dma_ch[i].dmalock));
 	}
 	/* Mark MEMDMA Channel 0 as requested since we're using it internally */
 	request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
@@ -60,7 +59,7 @@
 	int i;
 
 	for (i = 0; i < MAX_DMA_CHANNELS; ++i)
-		if (dma_ch[i].chan_status != DMA_CHANNEL_FREE)
+		if (dma_channel_active(i))
 			seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id);
 
 	return 0;
@@ -107,20 +106,11 @@
 	}
 #endif
 
-	mutex_lock(&(dma_ch[channel].dmalock));
-
-	if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
-	    || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
-		mutex_unlock(&(dma_ch[channel].dmalock));
+	if (atomic_cmpxchg(&dma_ch[channel].chan_status, 0, 1)) {
 		pr_debug("DMA CHANNEL IN USE  \n");
 		return -EBUSY;
-	} else {
-		dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
-		pr_debug("DMA CHANNEL IS ALLOCATED  \n");
 	}
 
-	mutex_unlock(&(dma_ch[channel].dmalock));
-
 #ifdef CONFIG_BF54x
 	if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
 		unsigned int per_map;
@@ -148,21 +138,20 @@
 
 int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
 {
-	BUG_ON(channel >= MAX_DMA_CHANNELS ||
-			dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
+	int ret;
+	unsigned int irq;
 
-	if (callback != NULL) {
-		int ret;
-		unsigned int irq = channel2irq(channel);
+	BUG_ON(channel >= MAX_DMA_CHANNELS || !callback ||
+			!atomic_read(&dma_ch[channel].chan_status));
 
-		ret = request_irq(irq, callback, IRQF_DISABLED,
-			dma_ch[channel].device_id, data);
-		if (ret)
-			return ret;
+	irq = channel2irq(channel);
+	ret = request_irq(irq, callback, 0, dma_ch[channel].device_id, data);
+	if (ret)
+		return ret;
 
-		dma_ch[channel].irq = irq;
-		dma_ch[channel].data = data;
-	}
+	dma_ch[channel].irq = irq;
+	dma_ch[channel].data = data;
+
 	return 0;
 }
 EXPORT_SYMBOL(set_dma_callback);
@@ -184,7 +173,7 @@
 {
 	pr_debug("freedma() : BEGIN \n");
 	BUG_ON(channel >= MAX_DMA_CHANNELS ||
-			dma_ch[channel].chan_status == DMA_CHANNEL_FREE);
+			!atomic_read(&dma_ch[channel].chan_status));
 
 	/* Halt the DMA */
 	disable_dma(channel);
@@ -194,9 +183,7 @@
 		free_irq(dma_ch[channel].irq, dma_ch[channel].data);
 
 	/* Clear the DMA Variable in the Channel */
-	mutex_lock(&(dma_ch[channel].dmalock));
-	dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
-	mutex_unlock(&(dma_ch[channel].dmalock));
+	atomic_set(&dma_ch[channel].chan_status, 0);
 
 	pr_debug("freedma() : END \n");
 }
@@ -210,13 +197,14 @@
 {
 	int i;
 
-	for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i) {
-		if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
+	for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
+		if (dma_ch[i].regs->cfg & DMAEN) {
 			printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
 			return -EBUSY;
 		}
 
-		dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
+		if (i < MAX_DMA_SUSPEND_CHANNELS)
+			dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
 	}
 
 	return 0;
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 22705ee..a174596 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -100,6 +100,12 @@
 };
 # endif
 
+#elif defined(BF538_FAMILY)
+static unsigned short * const port_fer[] = {
+	(unsigned short *) PORTCIO_FER,
+	(unsigned short *) PORTDIO_FER,
+	(unsigned short *) PORTEIO_FER,
+};
 #endif
 
 static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
@@ -163,6 +169,27 @@
 
 static void port_setup(unsigned gpio, unsigned short usage)
 {
+#if defined(BF538_FAMILY)
+	/*
+	 * BF538/9 Port C,D and E are special.
+	 * Inverted PORT_FER polarity on CDE and no PORF_FER on F
+	 * Regular PORT F GPIOs are handled here, CDE are exclusively
+	 * managed by GPIOLIB
+	 */
+
+	if (gpio < MAX_BLACKFIN_GPIOS || gpio >= MAX_RESOURCES)
+		return;
+
+	gpio -= MAX_BLACKFIN_GPIOS;
+
+	if (usage == GPIO_USAGE)
+		*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
+	else
+		*port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+	SSYNC();
+	return;
+#endif
+
 	if (check_gpio(gpio))
 		return;
 
@@ -762,6 +789,8 @@
 	if (!(per & P_DEFINED))
 		return -ENODEV;
 
+	BUG_ON(ident >= MAX_RESOURCES);
+
 	local_irq_save_hw(flags);
 
 	/* If a pin can be muxed as either GPIO or peripheral, make
@@ -979,6 +1008,76 @@
 }
 EXPORT_SYMBOL(bfin_gpio_free);
 
+#ifdef BFIN_SPECIAL_GPIO_BANKS
+static unsigned short reserved_special_gpio_map[gpio_bank(MAX_RESOURCES)];
+
+int bfin_special_gpio_request(unsigned gpio, const char *label)
+{
+	unsigned long flags;
+
+	local_irq_save_hw(flags);
+
+	/*
+	 * Allow that the identical GPIO can
+	 * be requested from the same driver twice
+	 * Do nothing and return -
+	 */
+
+	if (cmp_label(gpio, label) == 0) {
+		local_irq_restore_hw(flags);
+		return 0;
+	}
+
+	if (unlikely(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+		local_irq_restore_hw(flags);
+		printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
+		       gpio, get_label(gpio));
+
+		return -EBUSY;
+	}
+	if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+		local_irq_restore_hw(flags);
+		printk(KERN_ERR
+		       "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
+		       gpio, get_label(gpio));
+
+		return -EBUSY;
+	}
+
+	reserved_special_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+	reserved_peri_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+	set_label(gpio, label);
+	local_irq_restore_hw(flags);
+	port_setup(gpio, GPIO_USAGE);
+
+	return 0;
+}
+EXPORT_SYMBOL(bfin_special_gpio_request);
+
+void bfin_special_gpio_free(unsigned gpio)
+{
+	unsigned long flags;
+
+	might_sleep();
+
+	local_irq_save_hw(flags);
+
+	if (unlikely(!(reserved_special_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+		gpio_error(gpio);
+		local_irq_restore_hw(flags);
+		return;
+	}
+
+	reserved_special_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+	reserved_peri_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+	set_label(gpio, "free");
+	local_irq_restore_hw(flags);
+}
+EXPORT_SYMBOL(bfin_special_gpio_free);
+#endif
+
+
 int bfin_gpio_irq_request(unsigned gpio, const char *label)
 {
 	unsigned long flags;
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
index b52c1f8..8d42b9e 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
@@ -92,6 +92,6 @@
 		icplb_tbl[cpu][i_i++].data = 0;
 }
 
-void generate_cplb_tables_all(void)
+void __init generate_cplb_tables_all(void)
 {
 }
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index 69e0e53..930c01c 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -113,11 +113,11 @@
 		addr = L2_START;
 		d_data = L2_DMEMORY;
 	} else if (addr >= physical_mem_end) {
-		if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE
-		    && (status & FAULT_USERSUPV)) {
-			addr &= ~0x3fffff;
+		if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
+			addr &= ~(4 * 1024 * 1024 - 1);
 			d_data &= ~PAGE_SIZE_4KB;
 			d_data |= PAGE_SIZE_4MB;
+			d_data |= CPLB_USER_RD | CPLB_USER_WR;
 		} else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
 		    && (status & (FAULT_RW | FAULT_USERSUPV)) == FAULT_USERSUPV) {
 			addr &= ~(1 * 1024 * 1024 - 1);
@@ -203,7 +203,12 @@
 		addr = L2_START;
 		i_data = L2_IMEMORY;
 	} else if (addr >= physical_mem_end) {
-		if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
+		if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
+			addr &= ~(4 * 1024 * 1024 - 1);
+			i_data &= ~PAGE_SIZE_4KB;
+			i_data |= PAGE_SIZE_4MB;
+			i_data |= CPLB_USER_RD;
+		} else if (addr >= BOOT_ROM_START && addr < BOOT_ROM_START + BOOT_ROM_LENGTH
 		    && (status & FAULT_USERSUPV)) {
 			addr &= ~(1 * 1024 * 1024 - 1);
 			i_data &= ~PAGE_SIZE_4KB;
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index fd9a2f3..282a791 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -89,15 +89,25 @@
 
 void __init generate_cplb_tables_all(void)
 {
+	unsigned long uncached_end;
 	int i_d, i_i;
 
 	i_d = 0;
 	/* Normal RAM, including MTD FS.  */
 #ifdef CONFIG_MTD_UCLINUX
-	dcplb_bounds[i_d].eaddr = memory_mtd_start + mtd_size;
+	uncached_end = memory_mtd_start + mtd_size;
 #else
-	dcplb_bounds[i_d].eaddr = memory_end;
+	uncached_end = memory_end;
 #endif
+	/*
+	 * if DMA uncached is less than 1MB, mark the 1MB chunk as uncached
+	 * so that we don't have to use 4kB pages and cause CPLB thrashing
+	 */
+	if ((DMA_UNCACHED_REGION >= 1 * 1024 * 1024) || !DMA_UNCACHED_REGION ||
+	    ((_ramend - uncached_end) >= 1 * 1024 * 1024))
+		dcplb_bounds[i_d].eaddr = uncached_end;
+	else
+		dcplb_bounds[i_d].eaddr = uncached_end & ~(1 * 1024 * 1024);
 	dcplb_bounds[i_d++].data = SDRAM_DGENERIC;
 	/* DMA uncached region.  */
 	if (DMA_UNCACHED_REGION) {
@@ -135,18 +145,15 @@
 
 	i_i = 0;
 	/* Normal RAM, including MTD FS.  */
-#ifdef CONFIG_MTD_UCLINUX
-	icplb_bounds[i_i].eaddr = memory_mtd_start + mtd_size;
-#else
-	icplb_bounds[i_i].eaddr = memory_end;
-#endif
+	icplb_bounds[i_i].eaddr = uncached_end;
 	icplb_bounds[i_i++].data = SDRAM_IGENERIC;
-	/* DMA uncached region.  */
-	if (DMA_UNCACHED_REGION) {
-		icplb_bounds[i_i].eaddr = _ramend;
-		icplb_bounds[i_i++].data = 0;
-	}
 	if (_ramend != physical_mem_end) {
+		/* DMA uncached region.  */
+		if (DMA_UNCACHED_REGION) {
+			/* Normally this hole is caught by the async below.  */
+			icplb_bounds[i_i].eaddr = _ramend;
+			icplb_bounds[i_i++].data = 0;
+		}
 		/* Reserved memory.  */
 		icplb_bounds[i_i].eaddr = physical_mem_end;
 		icplb_bounds[i_i++].data = (reserved_mem_icache_on ?
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
index e74e74d..e937f32 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -7,30 +7,25 @@
  */
 
 #include <linux/types.h>
-#include <linux/mm.h>
+#include <linux/gfp.h>
 #include <linux/string.h>
-#include <linux/bootmem.h>
 #include <linux/spinlock.h>
-#include <linux/device.h>
 #include <linux/dma-mapping.h>
-#include <linux/io.h>
 #include <linux/scatterlist.h>
-#include <asm/cacheflush.h>
-#include <asm/bfin-global.h>
 
 static spinlock_t dma_page_lock;
-static unsigned int *dma_page;
+static unsigned long *dma_page;
 static unsigned int dma_pages;
 static unsigned long dma_base;
 static unsigned long dma_size;
 static unsigned int dma_initialized;
 
-void dma_alloc_init(unsigned long start, unsigned long end)
+static void dma_alloc_init(unsigned long start, unsigned long end)
 {
 	spin_lock_init(&dma_page_lock);
 	dma_initialized = 0;
 
-	dma_page = (unsigned int *)__get_free_page(GFP_KERNEL);
+	dma_page = (unsigned long *)__get_free_page(GFP_KERNEL);
 	memset(dma_page, 0, PAGE_SIZE);
 	dma_base = PAGE_ALIGN(start);
 	dma_size = PAGE_ALIGN(end) - PAGE_ALIGN(start);
@@ -58,10 +53,11 @@
 	spin_lock_irqsave(&dma_page_lock, flags);
 
 	for (i = 0; i < dma_pages;) {
-		if (dma_page[i++] == 0) {
+		if (test_bit(i++, dma_page) == 0) {
 			if (++count == pages) {
 				while (count--)
-					dma_page[--i] = 1;
+					__set_bit(--i, dma_page);
+
 				ret = dma_base + (i << PAGE_SHIFT);
 				break;
 			}
@@ -84,14 +80,14 @@
 	}
 
 	spin_lock_irqsave(&dma_page_lock, flags);
-	for (i = page; i < page + pages; i++) {
-		dma_page[i] = 0;
-	}
+	for (i = page; i < page + pages; i++)
+		__clear_bit(i, dma_page);
+
 	spin_unlock_irqrestore(&dma_page_lock, flags);
 }
 
 void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t * dma_handle, gfp_t gfp)
+			 dma_addr_t *dma_handle, gfp_t gfp)
 {
 	void *ret;
 
@@ -115,21 +111,14 @@
 EXPORT_SYMBOL(dma_free_coherent);
 
 /*
- * Dummy functions defined for some existing drivers
+ * Streaming DMA mappings
  */
-
-dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
-	       enum dma_data_direction direction)
+void __dma_sync(dma_addr_t addr, size_t size,
+		enum dma_data_direction dir)
 {
-	BUG_ON(direction == DMA_NONE);
-
-	invalidate_dcache_range((unsigned long)ptr,
-			(unsigned long)ptr + size);
-
-	return (dma_addr_t) ptr;
+	_dma_sync(addr, size, dir);
 }
-EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(__dma_sync);
 
 int
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
@@ -137,30 +126,23 @@
 {
 	int i;
 
-	BUG_ON(direction == DMA_NONE);
-
 	for (i = 0; i < nents; i++, sg++) {
 		sg->dma_address = (dma_addr_t) sg_virt(sg);
-
-		invalidate_dcache_range(sg_dma_address(sg),
-					sg_dma_address(sg) +
-					sg_dma_len(sg));
+		__dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
 	}
 
 	return nents;
 }
 EXPORT_SYMBOL(dma_map_sg);
 
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		enum dma_data_direction direction)
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+			    int nelems, enum dma_data_direction direction)
 {
-	BUG_ON(direction == DMA_NONE);
-}
-EXPORT_SYMBOL(dma_unmap_single);
+	int i;
 
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-		int nhwentries, enum dma_data_direction direction)
-{
-	BUG_ON(direction == DMA_NONE);
+	for (i = 0; i < nelems; i++, sg++) {
+		sg->dma_address = (dma_addr_t) sg_virt(sg);
+		__dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
+	}
 }
-EXPORT_SYMBOL(dma_unmap_sg);
+EXPORT_SYMBOL(dma_sync_sg_for_device);
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c
index 7281a91..cdbe075 100644
--- a/arch/blackfin/kernel/gptimers.c
+++ b/arch/blackfin/kernel/gptimers.c
@@ -137,7 +137,7 @@
 #endif
 };
 
-void set_gptimer_pwidth(int timer_id, uint32_t value)
+void set_gptimer_pwidth(unsigned int timer_id, uint32_t value)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	timer_regs[timer_id]->width = value;
@@ -145,14 +145,14 @@
 }
 EXPORT_SYMBOL(set_gptimer_pwidth);
 
-uint32_t get_gptimer_pwidth(int timer_id)
+uint32_t get_gptimer_pwidth(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return timer_regs[timer_id]->width;
 }
 EXPORT_SYMBOL(get_gptimer_pwidth);
 
-void set_gptimer_period(int timer_id, uint32_t period)
+void set_gptimer_period(unsigned int timer_id, uint32_t period)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	timer_regs[timer_id]->period = period;
@@ -160,28 +160,28 @@
 }
 EXPORT_SYMBOL(set_gptimer_period);
 
-uint32_t get_gptimer_period(int timer_id)
+uint32_t get_gptimer_period(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return timer_regs[timer_id]->period;
 }
 EXPORT_SYMBOL(get_gptimer_period);
 
-uint32_t get_gptimer_count(int timer_id)
+uint32_t get_gptimer_count(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return timer_regs[timer_id]->counter;
 }
 EXPORT_SYMBOL(get_gptimer_count);
 
-uint32_t get_gptimer_status(int group)
+uint32_t get_gptimer_status(unsigned int group)
 {
 	tassert(group < BFIN_TIMER_NUM_GROUP);
 	return group_regs[group]->status;
 }
 EXPORT_SYMBOL(get_gptimer_status);
 
-void set_gptimer_status(int group, uint32_t value)
+void set_gptimer_status(unsigned int group, uint32_t value)
 {
 	tassert(group < BFIN_TIMER_NUM_GROUP);
 	group_regs[group]->status = value;
@@ -189,42 +189,42 @@
 }
 EXPORT_SYMBOL(set_gptimer_status);
 
-int get_gptimer_intr(int timer_id)
+int get_gptimer_intr(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & timil_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_intr);
 
-void clear_gptimer_intr(int timer_id)
+void clear_gptimer_intr(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	group_regs[BFIN_TIMER_OCTET(timer_id)]->status = timil_mask[timer_id];
 }
 EXPORT_SYMBOL(clear_gptimer_intr);
 
-int get_gptimer_over(int timer_id)
+int get_gptimer_over(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & tovf_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_over);
 
-void clear_gptimer_over(int timer_id)
+void clear_gptimer_over(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	group_regs[BFIN_TIMER_OCTET(timer_id)]->status = tovf_mask[timer_id];
 }
 EXPORT_SYMBOL(clear_gptimer_over);
 
-int get_gptimer_run(int timer_id)
+int get_gptimer_run(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return !!(group_regs[BFIN_TIMER_OCTET(timer_id)]->status & trun_mask[timer_id]);
 }
 EXPORT_SYMBOL(get_gptimer_run);
 
-void set_gptimer_config(int timer_id, uint16_t config)
+void set_gptimer_config(unsigned int timer_id, uint16_t config)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	timer_regs[timer_id]->config = config;
@@ -232,7 +232,7 @@
 }
 EXPORT_SYMBOL(set_gptimer_config);
 
-uint16_t get_gptimer_config(int timer_id)
+uint16_t get_gptimer_config(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	return timer_regs[timer_id]->config;
@@ -280,7 +280,7 @@
 }
 EXPORT_SYMBOL(disable_gptimers_sync);
 
-void set_gptimer_pulse_hi(int timer_id)
+void set_gptimer_pulse_hi(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	timer_regs[timer_id]->config |= TIMER_PULSE_HI;
@@ -288,7 +288,7 @@
 }
 EXPORT_SYMBOL(set_gptimer_pulse_hi);
 
-void clear_gptimer_pulse_hi(int timer_id)
+void clear_gptimer_pulse_hi(unsigned int timer_id)
 {
 	tassert(timer_id < MAX_BLACKFIN_GPTIMERS);
 	timer_regs[timer_id]->config &= ~TIMER_PULSE_HI;
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 5d73823..a77307a 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -335,3 +335,70 @@
 	__clear_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
 	bfin_sti(bfin_irq_flags);
 }
+
+/*
+ * We could use standard atomic bitops in the following root status
+ * manipulation routines, but let's prepare for SMP support in the
+ * same move, preventing CPU migration as required.
+ */
+void __ipipe_stall_root(void)
+{
+	unsigned long *p, flags;
+
+	local_irq_save_hw(flags);
+	p = &__ipipe_root_status;
+	__set_bit(IPIPE_STALL_FLAG, p);
+	local_irq_restore_hw(flags);
+}
+EXPORT_SYMBOL(__ipipe_stall_root);
+
+unsigned long __ipipe_test_and_stall_root(void)
+{
+	unsigned long *p, flags;
+	int x;
+
+	local_irq_save_hw(flags);
+	p = &__ipipe_root_status;
+	x = __test_and_set_bit(IPIPE_STALL_FLAG, p);
+	local_irq_restore_hw(flags);
+
+	return x;
+}
+EXPORT_SYMBOL(__ipipe_test_and_stall_root);
+
+unsigned long __ipipe_test_root(void)
+{
+	const unsigned long *p;
+	unsigned long flags;
+	int x;
+
+	local_irq_save_hw_smp(flags);
+	p = &__ipipe_root_status;
+	x = test_bit(IPIPE_STALL_FLAG, p);
+	local_irq_restore_hw_smp(flags);
+
+	return x;
+}
+EXPORT_SYMBOL(__ipipe_test_root);
+
+void __ipipe_lock_root(void)
+{
+	unsigned long *p, flags;
+
+	local_irq_save_hw(flags);
+	p = &__ipipe_root_status;
+	__set_bit(IPIPE_SYNCDEFER_FLAG, p);
+	local_irq_restore_hw(flags);
+}
+EXPORT_SYMBOL(__ipipe_lock_root);
+
+void __ipipe_unlock_root(void)
+{
+	unsigned long *p, flags;
+
+	local_irq_save_hw(flags);
+	p = &__ipipe_root_status;
+	__clear_bit(IPIPE_SYNCDEFER_FLAG, p);
+	local_irq_restore_hw(flags);
+}
+EXPORT_SYMBOL(__ipipe_unlock_root);
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index cce79d0..f1036b6 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -24,16 +24,6 @@
 #include <asm/blackfin.h>
 #include <asm/dma.h>
 
-/* Put the error code here just in case the user cares.  */
-int gdb_bfin_errcode;
-/* Likewise, the vector number here (since GDB only gets the signal
-   number through the usual means, and that's not very specific).  */
-int gdb_bfin_vector = -1;
-
-#if KGDB_MAX_NO_CPUS != 8
-#error change the definition of slavecpulocks
-#endif
-
 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
 	gdb_regs[BFIN_R0] = regs->r0;
@@ -369,13 +359,6 @@
 }
 #endif
 
-void kgdb_post_primary_code(struct pt_regs *regs, int eVector, int err_code)
-{
-	/* Master processor is completely in the debugger */
-	gdb_bfin_vector = eVector;
-	gdb_bfin_errcode = err_code;
-}
-
 int kgdb_arch_handle_exception(int vector, int signo,
 			       int err_code, char *remcom_in_buffer,
 			       char *remcom_out_buffer,
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
index 59fc42d..9a4b075 100644
--- a/arch/blackfin/kernel/kgdb_test.c
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -17,8 +17,9 @@
 
 #include <asm/blackfin.h>
 
+/* Symbols are here for kgdb test to poke directly */
 static char cmdline[256];
-static unsigned long len;
+static size_t len;
 
 #ifndef CONFIG_SMP
 static int num1 __attribute__((l1_data));
@@ -27,11 +28,10 @@
 
 void kgdb_l1_test(void)
 {
-	printk(KERN_ALERT "L1(before change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
-	printk(KERN_ALERT "L1 : code function addr = 0x%p\n", kgdb_l1_test);
-	num1 = num1 + 10 ;
-	printk(KERN_ALERT "L1(after change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
-	return ;
+	pr_alert("L1(before change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
+	pr_alert("L1 : code function addr = 0x%p\n", kgdb_l1_test);
+	num1 = num1 + 10;
+	pr_alert("L1(after change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
 }
 #endif
 
@@ -42,11 +42,10 @@
 
 void kgdb_l2_test(void)
 {
-	printk(KERN_ALERT "L2(before change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
-	printk(KERN_ALERT "L2 : code function addr = 0x%p\n", kgdb_l2_test);
-	num2 = num2 + 20 ;
-	printk(KERN_ALERT "L2(after change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
-	return ;
+	pr_alert("L2(before change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
+	pr_alert("L2 : code function addr = 0x%p\n", kgdb_l2_test);
+	num2 = num2 + 20;
+	pr_alert("L2(after change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
 }
 
 #endif
@@ -54,12 +53,14 @@
 
 int kgdb_test(char *name, int len, int count, int z)
 {
-	printk(KERN_ALERT "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
+	pr_alert("kgdb name(%d): %s, %d, %d\n", len, name, count, z);
 	count = z;
 	return count;
 }
 
-static int test_proc_output(char *buf)
+static ssize_t
+kgdb_test_proc_read(struct file *file, char __user *buf,
+                    size_t count, loff_t *ppos)
 {
 	kgdb_test("hello world!", 12, 0x55, 0x10);
 #ifndef CONFIG_SMP
@@ -72,49 +73,31 @@
 	return 0;
 }
 
-static int test_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+static ssize_t
+kgdb_test_proc_write(struct file *file, const char __user *buffer,
+                     size_t count, loff_t *pos)
 {
-	int len;
-
-	len = test_proc_output(page);
-	if (len <= off+count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-	return len;
-}
-
-static int test_write_proc(struct file *file, const char *buffer,
-				 unsigned long count, void *data)
-{
-	if (count >= 256)
-		len = 255;
-	else
-		len = count;
-
+	len = min_t(size_t, 255, count);
 	memcpy(cmdline, buffer, count);
 	cmdline[len] = 0;
 
 	return len;
 }
 
+static const struct file_operations kgdb_test_proc_fops = {
+	.owner = THIS_MODULE,
+	.read  = kgdb_test_proc_read,
+	.write = kgdb_test_proc_write,
+};
+
 static int __init kgdbtest_init(void)
 {
 	struct proc_dir_entry *entry;
 
-	entry = create_proc_entry("kgdbtest", 0, NULL);
+	entry = proc_create("kgdbtest", 0, NULL, &kgdb_test_proc_fops);
 	if (entry == NULL)
 		return -ENOMEM;
 
-	entry->read_proc = test_read_proc;
-	entry->write_proc = test_write_proc;
-	entry->data = NULL;
-
 	return 0;
 }
 
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 4587642..b56b0e4 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -258,9 +258,12 @@
 	int __user *up0 = (int __user *)regs->p0;
 
 	switch (regs->pc) {
+	default:
+		/* not in middle of an atomic step, so resume like normal */
+		return;
+
 	case ATOMIC_XCHG32 + 2:
 		put_user(regs->r1, up0);
-		regs->pc = ATOMIC_XCHG32 + 4;
 		break;
 
 	case ATOMIC_CAS32 + 2:
@@ -268,7 +271,6 @@
 		if (regs->r0 == regs->r1)
 	case ATOMIC_CAS32 + 6:
 			put_user(regs->r2, up0);
-		regs->pc = ATOMIC_CAS32 + 8;
 		break;
 
 	case ATOMIC_ADD32 + 2:
@@ -276,7 +278,6 @@
 		/* fall through */
 	case ATOMIC_ADD32 + 4:
 		put_user(regs->r0, up0);
-		regs->pc = ATOMIC_ADD32 + 6;
 		break;
 
 	case ATOMIC_SUB32 + 2:
@@ -284,7 +285,6 @@
 		/* fall through */
 	case ATOMIC_SUB32 + 4:
 		put_user(regs->r0, up0);
-		regs->pc = ATOMIC_SUB32 + 6;
 		break;
 
 	case ATOMIC_IOR32 + 2:
@@ -292,7 +292,6 @@
 		/* fall through */
 	case ATOMIC_IOR32 + 4:
 		put_user(regs->r0, up0);
-		regs->pc = ATOMIC_IOR32 + 6;
 		break;
 
 	case ATOMIC_AND32 + 2:
@@ -300,7 +299,6 @@
 		/* fall through */
 	case ATOMIC_AND32 + 4:
 		put_user(regs->r0, up0);
-		regs->pc = ATOMIC_AND32 + 6;
 		break;
 
 	case ATOMIC_XOR32 + 2:
@@ -308,9 +306,15 @@
 		/* fall through */
 	case ATOMIC_XOR32 + 4:
 		put_user(regs->r0, up0);
-		regs->pc = ATOMIC_XOR32 + 6;
 		break;
 	}
+
+	/*
+	 * We've finished the atomic section, and the only thing left for
+	 * userspace is to do a RTS, so we might as well handle that too
+	 * since we need to update the PC anyways.
+	 */
+	regs->pc = regs->rets;
 }
 
 static inline
@@ -332,12 +336,58 @@
 {
 	return in_mem_const_off(addr, size, 0, const_addr, const_size);
 }
-#define IN_ASYNC(bnum, bctlnum) \
+#define ASYNC_ENABLED(bnum, bctlnum) \
 ({ \
-	(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \
-	bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \
-	BFIN_MEM_ACCESS_CORE; \
+	(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \
+	bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \
+	1; \
 })
+/*
+ * We can't read EBIU banks that aren't enabled or we end up hanging
+ * on the access to the async space.  Make sure we validate accesses
+ * that cross async banks too.
+ *	0 - found, but unusable
+ *	1 - found & usable
+ *	2 - not found
+ */
+static
+int in_async(unsigned long addr, unsigned long size)
+{
+	if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) {
+		if (!ASYNC_ENABLED(0, 0))
+			return 0;
+		if (addr + size <= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)
+			return 1;
+		size -= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE - addr;
+		addr = ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE;
+	}
+	if (addr >= ASYNC_BANK1_BASE && addr < ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) {
+		if (!ASYNC_ENABLED(1, 0))
+			return 0;
+		if (addr + size <= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)
+			return 1;
+		size -= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE - addr;
+		addr = ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE;
+	}
+	if (addr >= ASYNC_BANK2_BASE && addr < ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) {
+		if (!ASYNC_ENABLED(2, 1))
+			return 0;
+		if (addr + size <= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE)
+			return 1;
+		size -= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE - addr;
+		addr = ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE;
+	}
+	if (addr >= ASYNC_BANK3_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
+		if (ASYNC_ENABLED(3, 1))
+			return 0;
+		if (addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
+			return 1;
+		return 0;
+	}
+
+	/* not within async bounds */
+	return 2;
+}
 
 int bfin_mem_access_type(unsigned long addr, unsigned long size)
 {
@@ -374,17 +424,11 @@
 	if (addr >= SYSMMR_BASE)
 		return BFIN_MEM_ACCESS_CORE_ONLY;
 
-	/* We can't read EBIU banks that aren't enabled or we end up hanging
-	 * on the access to the async space.
-	 */
-	if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE))
-		return IN_ASYNC(0, 0);
-	if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
-		return IN_ASYNC(1, 0);
-	if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
-		return IN_ASYNC(2, 1);
-	if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
-		return IN_ASYNC(3, 1);
+	switch (in_async(addr, size)) {
+	case 0: return -EFAULT;
+	case 1: return BFIN_MEM_ACCESS_CORE;
+	case 2: /* fall through */;
+	}
 
 	if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
 		return BFIN_MEM_ACCESS_CORE;
@@ -401,6 +445,8 @@
 /* Return 1 if access to memory range is OK, 0 otherwise */
 int _access_ok(unsigned long addr, unsigned long size)
 {
+	int aret;
+
 	if (size == 0)
 		return 1;
 	/* Check that things do not wrap around */
@@ -450,6 +496,11 @@
 	if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
 		return 1;
 #endif
+
+	aret = in_async(addr, size);
+	if (aret < 2)
+		return aret;
+
 	if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
 		return 1;
 
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 56b0ba1..65567dc 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -316,19 +316,6 @@
 			case BFIN_MEM_ACCESS_CORE_ONLY:
 				copied = access_process_vm(child, addr, &data,
 				                           to_copy, 1);
-				if (copied)
-					break;
-
-				/* hrm, why didn't that work ... maybe no mapping */
-				if (addr >= FIXED_CODE_START &&
-				    addr + to_copy <= FIXED_CODE_END) {
-					copy_to_user_page(0, 0, 0, paddr, &data, to_copy);
-					copied = to_copy;
-				} else if (addr >= BOOT_ROM_START) {
-					memcpy(paddr, &data, to_copy);
-					copied = to_copy;
-				}
-
 				break;
 			case BFIN_MEM_ACCESS_DMA:
 				if (safe_dma_memcpy(paddr, &data, to_copy))
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index c202a44..95448ae 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -178,10 +178,10 @@
 
 void __init bfin_relocate_l1_mem(void)
 {
-	unsigned long l1_code_length;
-	unsigned long l1_data_a_length;
-	unsigned long l1_data_b_length;
-	unsigned long l2_length;
+	unsigned long text_l1_len = (unsigned long)_text_l1_len;
+	unsigned long data_l1_len = (unsigned long)_data_l1_len;
+	unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
+	unsigned long l2_len = (unsigned long)_l2_len;
 
 	early_shadow_stamp();
 
@@ -201,30 +201,23 @@
 
 	blackfin_dma_early_init();
 
-	/* if necessary, copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
-	l1_code_length = _etext_l1 - _stext_l1;
-	if (l1_code_length)
-		early_dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
+	/* if necessary, copy L1 text to L1 instruction SRAM */
+	if (L1_CODE_LENGTH && text_l1_len)
+		early_dma_memcpy(_stext_l1, _text_l1_lma, text_l1_len);
 
-	/* if necessary, copy _sdata_l1 to _sbss_l1 to L1 data bank A SRAM */
-	l1_data_a_length = _sbss_l1 - _sdata_l1;
-	if (l1_data_a_length)
-		early_dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+	/* if necessary, copy L1 data to L1 data bank A SRAM */
+	if (L1_DATA_A_LENGTH && data_l1_len)
+		early_dma_memcpy(_sdata_l1, _data_l1_lma, data_l1_len);
 
-	/* if necessary, copy _sdata_b_l1 to _sbss_b_l1 to L1 data bank B SRAM */
-	l1_data_b_length = _sbss_b_l1 - _sdata_b_l1;
-	if (l1_data_b_length)
-		early_dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
-			l1_data_a_length, l1_data_b_length);
+	/* if necessary, copy L1 data B to L1 data bank B SRAM */
+	if (L1_DATA_B_LENGTH && data_b_l1_len)
+		early_dma_memcpy(_sdata_b_l1, _data_b_l1_lma, data_b_l1_len);
 
 	early_dma_memcpy_done();
 
-	/* if necessary, copy _stext_l2 to _edata_l2 to L2 SRAM */
-	if (L2_LENGTH != 0) {
-		l2_length = _sbss_l2 - _stext_l2;
-		if (l2_length)
-			memcpy(_stext_l2, _l2_lma_start, l2_length);
-	}
+	/* if necessary, copy L2 text/data to L2 SRAM */
+	if (L2_LENGTH && l2_len)
+		memcpy(_stext_l2, _l2_lma, l2_len);
 }
 
 /* add_memory_region to memmap */
@@ -608,11 +601,6 @@
 	page_mask_order = get_order(3 * page_mask_nelts * sizeof(long));
 #endif
 
-#if !defined(CONFIG_MTD_UCLINUX)
-	/*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
-	memory_end -= SIZE_4K;
-#endif
-
 	init_mm.start_code = (unsigned long)_stext;
 	init_mm.end_code = (unsigned long)_etext;
 	init_mm.end_data = (unsigned long)_edata;
@@ -917,7 +905,7 @@
 
 	printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n");
 	if (bfin_compiled_revid() == 0xffff)
-		printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
+		printk(KERN_INFO "Compiled for ADSP-%s Rev any, running on 0.%d\n", CPU, bfin_revid());
 	else if (bfin_compiled_revid() == -1)
 		printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU);
 	else
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index 9d90c18..e0fd63e 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -12,6 +12,7 @@
 #include <linux/binfmts.h>
 #include <linux/freezer.h>
 #include <linux/uaccess.h>
+#include <linux/tracehook.h>
 
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
@@ -332,3 +333,20 @@
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
 }
+
+/*
+ * notification of userspace execution resumption
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs)
+{
+	if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK))
+		do_signal(regs);
+
+	if (test_thread_flag(TIF_NOTIFY_RESUME)) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index 359cfb1..17c38c5 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -22,8 +22,6 @@
 #include <asm/time.h>
 #include <asm/gptimers.h>
 
-#if defined(CONFIG_CYCLES_CLOCKSOURCE)
-
 /* Accelerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
@@ -46,20 +44,11 @@
  *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
  */
 
-static unsigned long cyc2ns_scale;
 #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
-	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR) / cpu_khz;
-}
+#if defined(CONFIG_CYCLES_CLOCKSOURCE)
 
-static inline unsigned long long cycles_2_ns(cycle_t cyc)
-{
-	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
-static cycle_t bfin_read_cycles(struct clocksource *cs)
+static notrace cycle_t bfin_read_cycles(struct clocksource *cs)
 {
 	return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
 }
@@ -69,19 +58,18 @@
 	.rating		= 400,
 	.read		= bfin_read_cycles,
 	.mask		= CLOCKSOURCE_MASK(64),
-	.shift		= 22,
+	.shift		= CYC2NS_SCALE_FACTOR,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-unsigned long long sched_clock(void)
+static inline unsigned long long bfin_cs_cycles_sched_clock(void)
 {
-	return cycles_2_ns(bfin_read_cycles(&bfin_cs_cycles));
+	return clocksource_cyc2ns(bfin_read_cycles(&bfin_cs_cycles),
+		bfin_cs_cycles.mult, bfin_cs_cycles.shift);
 }
 
 static int __init bfin_cs_cycles_init(void)
 {
-	set_cyc2ns_scale(get_cclk() / 1000);
-
 	bfin_cs_cycles.mult = \
 		clocksource_hz2mult(get_cclk(), bfin_cs_cycles.shift);
 
@@ -108,7 +96,7 @@
 	enable_gptimers(TIMER0bit);
 }
 
-static cycle_t bfin_read_gptimer0(void)
+static cycle_t bfin_read_gptimer0(struct clocksource *cs)
 {
 	return bfin_read_TIMER0_COUNTER();
 }
@@ -118,10 +106,16 @@
 	.rating		= 350,
 	.read		= bfin_read_gptimer0,
 	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 22,
+	.shift		= CYC2NS_SCALE_FACTOR,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static inline unsigned long long bfin_cs_gptimer0_sched_clock(void)
+{
+	return clocksource_cyc2ns(bfin_read_TIMER0_COUNTER(),
+		bfin_cs_gptimer0.mult, bfin_cs_gptimer0.shift);
+}
+
 static int __init bfin_cs_gptimer0_init(void)
 {
 	setup_gptimer0();
@@ -138,6 +132,19 @@
 # define bfin_cs_gptimer0_init()
 #endif
 
+
+#if defined(CONFIG_GPTMR0_CLOCKSOURCE) || defined(CONFIG_CYCLES_CLOCKSOURCE)
+/* prefer to use cycles since it has higher rating */
+notrace unsigned long long sched_clock(void)
+{
+#if defined(CONFIG_CYCLES_CLOCKSOURCE)
+	return bfin_cs_cycles_sched_clock();
+#else
+	return bfin_cs_gptimer0_sched_clock();
+#endif
+}
+#endif
+
 #ifdef CONFIG_CORE_TIMER_IRQ_L1
 __attribute__((l1_text))
 #endif
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index bd3b53d..13c1ee3 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -184,11 +184,3 @@
 
 	time_sched_init(timer_interrupt);
 }
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	return (unsigned long long)jiffies *(NSEC_PER_SEC / HZ);
-}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 9636bac..d3cbcd6 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -119,6 +119,15 @@
 		return;
 	}
 
+	/*
+	 * Don't walk any of the vmas if we are oopsing, it has been known
+	 * to cause problems - corrupt vmas (kernel crashes) cause double faults
+	 */
+	if (oops_in_progress) {
+		strcat(buf, "/* kernel dynamic memory (maybe user-space) */");
+		return;
+	}
+
 	/* looks like we're off in user-land, so let's walk all the
 	 * mappings of all our processes and see if we can't be a whee
 	 * bit more specific
@@ -515,6 +524,36 @@
 			break;
 		/* External Memory Addressing Error */
 		case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
+			if (ANOMALY_05000310) {
+				static unsigned long anomaly_rets;
+
+				if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
+				    (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) {
+					/*
+					 * A false hardware error will happen while fetching at
+					 * the L1 instruction SRAM boundary.  Ignore it.
+					 */
+					anomaly_rets = fp->rets;
+					goto traps_done;
+				} else if (fp->rets == anomaly_rets) {
+					/*
+					 * While boundary code returns to a function, at the ret
+					 * point, a new false hardware error might occur too based
+					 * on tests.  Ignore it too.
+					 */
+					goto traps_done;
+				} else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
+				           (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) {
+					/*
+					 * If boundary code calls a function, at the entry point,
+					 * a new false hardware error maybe happen based on tests.
+					 * Ignore it too.
+					 */
+					goto traps_done;
+				} else
+					anomaly_rets = 0;
+			}
+
 			info.si_code = BUS_ADRERR;
 			sig = SIGBUS;
 			strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
@@ -976,12 +1015,12 @@
 	    !((unsigned long)current & 0x3) && current->pid) {
 		verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
 		if (current->comm >= (char *)FIXED_CODE_START)
-			verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n",
+			verbose_printk(KERN_NOTICE "COMM=%s PID=%d",
 				current->comm, current->pid);
 		else
-			verbose_printk(KERN_NOTICE "COMM= invalid\n");
+			verbose_printk(KERN_NOTICE "COMM= invalid");
 
-		printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
+		printk(KERN_CONT " CPU=%d\n", current_thread_info()->cpu);
 		if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
 			verbose_printk(KERN_NOTICE
 				"TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 10e1253..66799e7 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -4,8 +4,6 @@
  * Licensed under the GPL-2 or later
  */
 
-#define VMLINUX_SYMBOL(_sym_) _##_sym_
-
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/mem_map.h>
 #include <asm/page.h>
@@ -123,8 +121,6 @@
 		EXIT_DATA
 	}
 
-	__l1_lma_start = .;
-
 	.text_l1 L1_CODE_START : AT(LOADADDR(.exit.data) + SIZEOF(.exit.data))
 	{
 		. = ALIGN(4);
@@ -136,9 +132,11 @@
 		. = ALIGN(4);
 		__etext_l1 = .;
 	}
-	ASSERT (SIZEOF(.text_l1) <= L1_CODE_LENGTH, "L1 text overflow!")
+	__text_l1_lma = LOADADDR(.text_l1);
+	__text_l1_len = SIZEOF(.text_l1);
+	ASSERT (__text_l1_len <= L1_CODE_LENGTH, "L1 text overflow!")
 
-	.data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
+	.data_l1 L1_DATA_A_START : AT(__text_l1_lma + __text_l1_len)
 	{
 		. = ALIGN(4);
 		__sdata_l1 = .;
@@ -154,9 +152,11 @@
 		. = ALIGN(4);
 		__ebss_l1 = .;
 	}
-	ASSERT (SIZEOF(.data_l1) <= L1_DATA_A_LENGTH, "L1 data A overflow!")
+	__data_l1_lma = LOADADDR(.data_l1);
+	__data_l1_len = SIZEOF(.data_l1);
+	ASSERT (__data_l1_len <= L1_DATA_A_LENGTH, "L1 data A overflow!")
 
-	.data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
+	.data_b_l1 L1_DATA_B_START : AT(__data_l1_lma + __data_l1_len)
 	{
 		. = ALIGN(4);
 		__sdata_b_l1 = .;
@@ -169,11 +169,11 @@
 		. = ALIGN(4);
 		__ebss_b_l1 = .;
 	}
-	ASSERT (SIZEOF(.data_b_l1) <= L1_DATA_B_LENGTH, "L1 data B overflow!")
+	__data_b_l1_lma = LOADADDR(.data_b_l1);
+	__data_b_l1_len = SIZEOF(.data_b_l1);
+	ASSERT (__data_b_l1_len <= L1_DATA_B_LENGTH, "L1 data B overflow!")
 
-	__l2_lma_start = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
-
-	.text_data_l2 L2_START : AT(LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1))
+	.text_data_l2 L2_START : AT(__data_b_l1_lma + __data_b_l1_len)
 	{
 		. = ALIGN(4);
 		__stext_l2 = .;
@@ -195,12 +195,14 @@
 		. = ALIGN(4);
 		__ebss_l2 = .;
 	}
-	ASSERT (SIZEOF(.text_data_l2) <= L2_LENGTH, "L2 overflow!")
+	__l2_lma = LOADADDR(.text_data_l2);
+	__l2_len = SIZEOF(.text_data_l2);
+	ASSERT (__l2_len <= L2_LENGTH, "L2 overflow!")
 
 	/* Force trailing alignment of our init section so that when we
 	 * free our init memory, we don't leave behind a partial page.
 	 */
-	. = LOADADDR(.text_data_l2) + SIZEOF(.text_data_l2);
+	. = __l2_lma + __l2_len;
 	. = ALIGN(PAGE_SIZE);
 	___init_end = .;
 
diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile
index 635288f..42c47dc 100644
--- a/arch/blackfin/lib/Makefile
+++ b/arch/blackfin/lib/Makefile
@@ -5,7 +5,7 @@
 lib-y := \
 	ashldi3.o ashrdi3.o lshrdi3.o \
 	muldi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
-	checksum.o memcpy.o memset.o memcmp.o memchr.o memmove.o \
+	memcpy.o memset.o memcmp.o memchr.o memmove.o \
 	strcmp.o strcpy.o strncmp.o strncpy.o \
 	umulsi3_highpart.o smulsi3_highpart.o \
 	ins.o outs.o
diff --git a/arch/blackfin/lib/checksum.c b/arch/blackfin/lib/checksum.c
deleted file mode 100644
index c62969d..0000000
--- a/arch/blackfin/lib/checksum.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2004-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- *
- * An implementation of the TCP/IP protocol suite for the LINUX operating
- * system. INET is implemented using the BSD Socket interface as the
- * means of communication with the user level.
- *
- */
-
-#include <linux/module.h>
-#include <net/checksum.h>
-#include <asm/checksum.h>
-
-#ifdef CONFIG_IP_CHECKSUM_L1
-static unsigned short do_csum(const unsigned char *buff, int len)__attribute__((l1_text));
-#endif
-
-static unsigned short do_csum(const unsigned char *buff, int len)
-{
-	register unsigned long sum = 0;
-	int swappem = 0;
-
-	if (1 & (unsigned long)buff) {
-		sum = *buff << 8;
-		buff++;
-		len--;
-		++swappem;
-	}
-
-	while (len > 1) {
-		sum += *(unsigned short *)buff;
-		buff += 2;
-		len -= 2;
-	}
-
-	if (len > 0)
-		sum += *buff;
-
-	/*  Fold 32-bit sum to 16 bits */
-	while (sum >> 16)
-		sum = (sum & 0xffff) + (sum >> 16);
-
-	if (swappem)
-		sum = ((sum & 0xff00) >> 8) + ((sum & 0x00ff) << 8);
-
-	return sum;
-
-}
-
-/*
- *	This is a version of ip_compute_csum() optimized for IP headers,
- *	which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(unsigned char *iph, unsigned int ihl)
-{
-	return (__force __sum16)~do_csum(iph, ihl * 4);
-}
-EXPORT_SYMBOL(ip_fast_csum);
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-	/*
-	 * Just in case we get nasty checksum data...
-	 * Like 0xffff6ec3 in the case of our IPv6 multicast header.
-	 * We fold to begin with, as well as at the end.
-	 */
-	sum = (sum & 0xffff) + (sum >> 16);
-
-	sum += do_csum(buff, len);
-
-	sum = (sum & 0xffff) + (sum >> 16);
-
-	return sum;
-}
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
-	return (__force __sum16)~do_csum(buff, len);
-}
-EXPORT_SYMBOL(ip_compute_csum);
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst,
-			    int len, __wsum sum, int *csum_err)
-{
-	if (csum_err)
-		*csum_err = 0;
-	memcpy(dst, (__force void *)src, len);
-	return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy_from_user);
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-
-__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy);
diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig
index 4c76fef..4ab2d16 100644
--- a/arch/blackfin/mach-bf518/Kconfig
+++ b/arch/blackfin/mach-bf518/Kconfig
@@ -1,3 +1,7 @@
+config BF51x
+	def_bool y
+	depends on (BF512 || BF514 || BF516 || BF518)
+
 if (BF51x)
 
 source "arch/blackfin/mach-bf518/boards/Kconfig"
diff --git a/arch/blackfin/mach-bf518/include/mach/blackfin.h b/arch/blackfin/mach-bf518/include/mach/blackfin.h
index 6cfb246..9053462 100644
--- a/arch/blackfin/mach-bf518/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf518/include/mach/blackfin.h
@@ -58,10 +58,4 @@
 #define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
 #define OFFSET_GCTL             0x24	/* Global Control Register              */
 
-/* PLL_DIV Masks													*/
-#define CCLK_DIV1 CSEL_DIV1	/*          CCLK = VCO / 1                                  */
-#define CCLK_DIV2 CSEL_DIV2	/*          CCLK = VCO / 2                                  */
-#define CCLK_DIV4 CSEL_DIV4	/*          CCLK = VCO / 4                                  */
-#define CCLK_DIV8 CSEL_DIV8	/*          CCLK = VCO / 8                                  */
-
 #endif
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
index e1d9991..108fa4b 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
@@ -1,7 +1,7 @@
 /*
  * Copyright 2008-2009 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _CDEF_BF514_H
@@ -10,15 +10,8 @@
 /* include all Core registers and bit definitions */
 #include "defBF514.h"
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF514 */
-
-/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "cdefBF51x_base.h"
-
-/* The following are the #defines needed by ADSP-BF514 that are not in the common header */
+/* BF514 is BF512 + RSI */
+#include "cdefBF512.h"
 
 /* Removable Storage Interface Registers */
 
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
index 6b364ed..2751592 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
@@ -1,7 +1,7 @@
 /*
  * Copyright 2008-2009 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _CDEF_BF516_H
@@ -10,15 +10,8 @@
 /* include all Core registers and bit definitions */
 #include "defBF516.h"
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF516 */
-
-/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "cdefBF51x_base.h"
-
-/* The following are the #defines needed by ADSP-BF516 that are not in the common header */
+/* BF516 is BF514 + EMAC */
+#include "cdefBF514.h"
 
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
 
@@ -185,71 +178,4 @@
 #define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
 #define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
 
-/* Removable Storage Interface Registers */
-
-#define bfin_read_RSI_PWR_CTL()        bfin_read16(RSI_PWR_CONTROL)
-#define bfin_write_RSI_PWR_CTL(val)    bfin_write16(RSI_PWR_CONTROL, val)
-#define bfin_read_RSI_CLK_CTL()	       bfin_read16(RSI_CLK_CONTROL)
-#define bfin_write_RSI_CLK_CTL(val)    bfin_write16(RSI_CLK_CONTROL, val)
-#define bfin_read_RSI_ARGUMENT()       bfin_read32(RSI_ARGUMENT)
-#define bfin_write_RSI_ARGUMENT(val)   bfin_write32(RSI_ARGUMENT, val)
-#define bfin_read_RSI_COMMAND()        bfin_read16(RSI_COMMAND)
-#define bfin_write_RSI_COMMAND(val)    bfin_write16(RSI_COMMAND, val)
-#define bfin_read_RSI_RESP_CMD()       bfin_read16(RSI_RESP_CMD)
-#define bfin_write_RSI_RESP_CMD(val)   bfin_write16(RSI_RESP_CMD, val)
-#define bfin_read_RSI_RESPONSE0()      bfin_read32(RSI_RESPONSE0)
-#define bfin_write_RSI_RESPONSE0(val)  bfin_write32(RSI_RESPONSE0, val)
-#define bfin_read_RSI_RESPONSE1()      bfin_read32(RSI_RESPONSE1)
-#define bfin_write_RSI_RESPONSE1(val)  bfin_write32(RSI_RESPONSE1, val)
-#define bfin_read_RSI_RESPONSE2()      bfin_read32(RSI_RESPONSE2)
-#define bfin_write_RSI_RESPONSE2(val)  bfin_write32(RSI_RESPONSE2, val)
-#define bfin_read_RSI_RESPONSE3()      bfin_read32(RSI_RESPONSE3)
-#define bfin_write_RSI_RESPONSE3(val)  bfin_write32(RSI_RESPONSE3, val)
-#define bfin_read_RSI_DATA_TIMER()     bfin_read32(RSI_DATA_TIMER)
-#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
-#define bfin_read_RSI_DATA_LGTH()      bfin_read16(RSI_DATA_LGTH)
-#define bfin_write_RSI_DATA_LGTH(val)  bfin_write16(RSI_DATA_LGTH, val)
-#define bfin_read_RSI_DATA_CTL()       bfin_read16(RSI_DATA_CONTROL)
-#define bfin_write_RSI_DATA_CTL(val)   bfin_write16(RSI_DATA_CONTROL, val)
-#define bfin_read_RSI_DATA_CNT()       bfin_read16(RSI_DATA_CNT)
-#define bfin_write_RSI_DATA_CNT(val)   bfin_write16(RSI_DATA_CNT, val)
-#define bfin_read_RSI_STATUS()         bfin_read32(RSI_STATUS)
-#define bfin_write_RSI_STATUS(val)     bfin_write32(RSI_STATUS, val)
-#define bfin_read_RSI_STATUS_CLR()     bfin_read16(RSI_STATUSCL)
-#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
-#define bfin_read_RSI_MASK0()          bfin_read32(RSI_MASK0)
-#define bfin_write_RSI_MASK0(val)      bfin_write32(RSI_MASK0, val)
-#define bfin_read_RSI_MASK1()          bfin_read32(RSI_MASK1)
-#define bfin_write_RSI_MASK1(val)      bfin_write32(RSI_MASK1, val)
-#define bfin_read_RSI_FIFO_CNT()       bfin_read16(RSI_FIFO_CNT)
-#define bfin_write_RSI_FIFO_CNT(val)   bfin_write16(RSI_FIFO_CNT, val)
-#define bfin_read_RSI_CEATA_CTL()      bfin_read16(RSI_CEATA_CONTROL)
-#define bfin_write_RSI_CEATA_CTL(val)  bfin_write16(RSI_CEATA_CONTROL, val)
-#define bfin_read_RSI_FIFO()           bfin_read32(RSI_FIFO)
-#define bfin_write_RSI_FIFO(val)       bfin_write32(RSI_FIFO, val)
-#define bfin_read_RSI_E_STATUS()       bfin_read16(RSI_ESTAT)
-#define bfin_write_RSI_E_STATUS(val)   bfin_write16(RSI_ESTAT, val)
-#define bfin_read_RSI_E_MASK()         bfin_read16(RSI_EMASK)
-#define bfin_write_RSI_E_MASK(val)     bfin_write16(RSI_EMASK, val)
-#define bfin_read_RSI_CFG()            bfin_read16(RSI_CONFIG)
-#define bfin_write_RSI_CFG(val)        bfin_write16(RSI_CONFIG, val)
-#define bfin_read_RSI_RD_WAIT_EN()     bfin_read16(RSI_RD_WAIT_EN)
-#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
-#define bfin_read_RSI_PID0()           bfin_read16(RSI_PID0)
-#define bfin_write_RSI_PID0(val)       bfin_write16(RSI_PID0, val)
-#define bfin_read_RSI_PID1()           bfin_read16(RSI_PID1)
-#define bfin_write_RSI_PID1(val)       bfin_write16(RSI_PID1, val)
-#define bfin_read_RSI_PID2()           bfin_read16(RSI_PID2)
-#define bfin_write_RSI_PID2(val)       bfin_write16(RSI_PID2, val)
-#define bfin_read_RSI_PID3()           bfin_read16(RSI_PID3)
-#define bfin_write_RSI_PID3(val)       bfin_write16(RSI_PID3, val)
-#define bfin_read_RSI_PID4()           bfin_read16(RSI_PID4)
-#define bfin_write_RSI_PID4(val)       bfin_write16(RSI_PID4, val)
-#define bfin_read_RSI_PID5()           bfin_read16(RSI_PID5)
-#define bfin_write_RSI_PID5(val)       bfin_write16(RSI_PID5, val)
-#define bfin_read_RSI_PID6()           bfin_read16(RSI_PID6)
-#define bfin_write_RSI_PID6(val)       bfin_write16(RSI_PID6, val)
-#define bfin_read_RSI_PID7()           bfin_read16(RSI_PID7)
-#define bfin_write_RSI_PID7(val)       bfin_write16(RSI_PID7, val)
-
 #endif /* _CDEF_BF516_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF518.h b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
index 929b906..7fb7f0e 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
@@ -1,7 +1,7 @@
 /*
  * Copyright 2008-2009 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later
+ * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
 #ifndef _CDEF_BF518_H
@@ -10,181 +10,10 @@
 /* include all Core registers and bit definitions */
 #include "defBF518.h"
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
+/* BF518 is BF516 + IEEE-1588 */
+#include "cdefBF516.h"
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF518 */
-
-/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "cdefBF51x_base.h"
-
-/* The following are the #defines needed by ADSP-BF518 that are not in the common header */
-
-
-/* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
-
-#define bfin_read_EMAC_OPMODE()			bfin_read32(EMAC_OPMODE)
-#define bfin_write_EMAC_OPMODE(val)		bfin_write32(EMAC_OPMODE, val)
-#define bfin_read_EMAC_ADDRLO()			bfin_read32(EMAC_ADDRLO)
-#define bfin_write_EMAC_ADDRLO(val)		bfin_write32(EMAC_ADDRLO, val)
-#define bfin_read_EMAC_ADDRHI()			bfin_read32(EMAC_ADDRHI)
-#define bfin_write_EMAC_ADDRHI(val)		bfin_write32(EMAC_ADDRHI, val)
-#define bfin_read_EMAC_HASHLO()			bfin_read32(EMAC_HASHLO)
-#define bfin_write_EMAC_HASHLO(val)		bfin_write32(EMAC_HASHLO, val)
-#define bfin_read_EMAC_HASHHI()			bfin_read32(EMAC_HASHHI)
-#define bfin_write_EMAC_HASHHI(val)		bfin_write32(EMAC_HASHHI, val)
-#define bfin_read_EMAC_STAADD()			bfin_read32(EMAC_STAADD)
-#define bfin_write_EMAC_STAADD(val)		bfin_write32(EMAC_STAADD, val)
-#define bfin_read_EMAC_STADAT()			bfin_read32(EMAC_STADAT)
-#define bfin_write_EMAC_STADAT(val)		bfin_write32(EMAC_STADAT, val)
-#define bfin_read_EMAC_FLC()			bfin_read32(EMAC_FLC)
-#define bfin_write_EMAC_FLC(val)		bfin_write32(EMAC_FLC, val)
-#define bfin_read_EMAC_VLAN1()			bfin_read32(EMAC_VLAN1)
-#define bfin_write_EMAC_VLAN1(val)		bfin_write32(EMAC_VLAN1, val)
-#define bfin_read_EMAC_VLAN2()			bfin_read32(EMAC_VLAN2)
-#define bfin_write_EMAC_VLAN2(val)		bfin_write32(EMAC_VLAN2, val)
-#define bfin_read_EMAC_WKUP_CTL()		bfin_read32(EMAC_WKUP_CTL)
-#define bfin_write_EMAC_WKUP_CTL(val)		bfin_write32(EMAC_WKUP_CTL, val)
-#define bfin_read_EMAC_WKUP_FFMSK0()		bfin_read32(EMAC_WKUP_FFMSK0)
-#define bfin_write_EMAC_WKUP_FFMSK0(val)	bfin_write32(EMAC_WKUP_FFMSK0, val)
-#define bfin_read_EMAC_WKUP_FFMSK1()		bfin_read32(EMAC_WKUP_FFMSK1)
-#define bfin_write_EMAC_WKUP_FFMSK1(val)	bfin_write32(EMAC_WKUP_FFMSK1, val)
-#define bfin_read_EMAC_WKUP_FFMSK2()		bfin_read32(EMAC_WKUP_FFMSK2)
-#define bfin_write_EMAC_WKUP_FFMSK2(val)	bfin_write32(EMAC_WKUP_FFMSK2, val)
-#define bfin_read_EMAC_WKUP_FFMSK3()		bfin_read32(EMAC_WKUP_FFMSK3)
-#define bfin_write_EMAC_WKUP_FFMSK3(val)	bfin_write32(EMAC_WKUP_FFMSK3, val)
-#define bfin_read_EMAC_WKUP_FFCMD()		bfin_read32(EMAC_WKUP_FFCMD)
-#define bfin_write_EMAC_WKUP_FFCMD(val)		bfin_write32(EMAC_WKUP_FFCMD, val)
-#define bfin_read_EMAC_WKUP_FFOFF()		bfin_read32(EMAC_WKUP_FFOFF)
-#define bfin_write_EMAC_WKUP_FFOFF(val)		bfin_write32(EMAC_WKUP_FFOFF, val)
-#define bfin_read_EMAC_WKUP_FFCRC0()		bfin_read32(EMAC_WKUP_FFCRC0)
-#define bfin_write_EMAC_WKUP_FFCRC0(val)	bfin_write32(EMAC_WKUP_FFCRC0, val)
-#define bfin_read_EMAC_WKUP_FFCRC1()		bfin_read32(EMAC_WKUP_FFCRC1)
-#define bfin_write_EMAC_WKUP_FFCRC1(val)	bfin_write32(EMAC_WKUP_FFCRC1, val)
-
-#define bfin_read_EMAC_SYSCTL()			bfin_read32(EMAC_SYSCTL)
-#define bfin_write_EMAC_SYSCTL(val)		bfin_write32(EMAC_SYSCTL, val)
-#define bfin_read_EMAC_SYSTAT()			bfin_read32(EMAC_SYSTAT)
-#define bfin_write_EMAC_SYSTAT(val)		bfin_write32(EMAC_SYSTAT, val)
-#define bfin_read_EMAC_RX_STAT()		bfin_read32(EMAC_RX_STAT)
-#define bfin_write_EMAC_RX_STAT(val)		bfin_write32(EMAC_RX_STAT, val)
-#define bfin_read_EMAC_RX_STKY()		bfin_read32(EMAC_RX_STKY)
-#define bfin_write_EMAC_RX_STKY(val)		bfin_write32(EMAC_RX_STKY, val)
-#define bfin_read_EMAC_RX_IRQE()		bfin_read32(EMAC_RX_IRQE)
-#define bfin_write_EMAC_RX_IRQE(val)		bfin_write32(EMAC_RX_IRQE, val)
-#define bfin_read_EMAC_TX_STAT()		bfin_read32(EMAC_TX_STAT)
-#define bfin_write_EMAC_TX_STAT(val)		bfin_write32(EMAC_TX_STAT, val)
-#define bfin_read_EMAC_TX_STKY()		bfin_read32(EMAC_TX_STKY)
-#define bfin_write_EMAC_TX_STKY(val)		bfin_write32(EMAC_TX_STKY, val)
-#define bfin_read_EMAC_TX_IRQE()		bfin_read32(EMAC_TX_IRQE)
-#define bfin_write_EMAC_TX_IRQE(val)		bfin_write32(EMAC_TX_IRQE, val)
-
-#define bfin_read_EMAC_MMC_CTL()		bfin_read32(EMAC_MMC_CTL)
-#define bfin_write_EMAC_MMC_CTL(val)		bfin_write32(EMAC_MMC_CTL, val)
-#define bfin_read_EMAC_MMC_RIRQS()		bfin_read32(EMAC_MMC_RIRQS)
-#define bfin_write_EMAC_MMC_RIRQS(val)		bfin_write32(EMAC_MMC_RIRQS, val)
-#define bfin_read_EMAC_MMC_RIRQE()		bfin_read32(EMAC_MMC_RIRQE)
-#define bfin_write_EMAC_MMC_RIRQE(val)		bfin_write32(EMAC_MMC_RIRQE, val)
-#define bfin_read_EMAC_MMC_TIRQS()		bfin_read32(EMAC_MMC_TIRQS)
-#define bfin_write_EMAC_MMC_TIRQS(val)		bfin_write32(EMAC_MMC_TIRQS, val)
-#define bfin_read_EMAC_MMC_TIRQE()		bfin_read32(EMAC_MMC_TIRQE)
-#define bfin_write_EMAC_MMC_TIRQE(val)		bfin_write32(EMAC_MMC_TIRQE, val)
-
-#define bfin_read_EMAC_RXC_OK()			bfin_read32(EMAC_RXC_OK)
-#define bfin_write_EMAC_RXC_OK(val)		bfin_write32(EMAC_RXC_OK, val)
-#define bfin_read_EMAC_RXC_FCS()		bfin_read32(EMAC_RXC_FCS)
-#define bfin_write_EMAC_RXC_FCS(val)		bfin_write32(EMAC_RXC_FCS, val)
-#define bfin_read_EMAC_RXC_ALIGN()		bfin_read32(EMAC_RXC_ALIGN)
-#define bfin_write_EMAC_RXC_ALIGN(val)		bfin_write32(EMAC_RXC_ALIGN, val)
-#define bfin_read_EMAC_RXC_OCTET()		bfin_read32(EMAC_RXC_OCTET)
-#define bfin_write_EMAC_RXC_OCTET(val)		bfin_write32(EMAC_RXC_OCTET, val)
-#define bfin_read_EMAC_RXC_DMAOVF()		bfin_read32(EMAC_RXC_DMAOVF)
-#define bfin_write_EMAC_RXC_DMAOVF(val)		bfin_write32(EMAC_RXC_DMAOVF, val)
-#define bfin_read_EMAC_RXC_UNICST()		bfin_read32(EMAC_RXC_UNICST)
-#define bfin_write_EMAC_RXC_UNICST(val)		bfin_write32(EMAC_RXC_UNICST, val)
-#define bfin_read_EMAC_RXC_MULTI()		bfin_read32(EMAC_RXC_MULTI)
-#define bfin_write_EMAC_RXC_MULTI(val)		bfin_write32(EMAC_RXC_MULTI, val)
-#define bfin_read_EMAC_RXC_BROAD()		bfin_read32(EMAC_RXC_BROAD)
-#define bfin_write_EMAC_RXC_BROAD(val)		bfin_write32(EMAC_RXC_BROAD, val)
-#define bfin_read_EMAC_RXC_LNERRI()		bfin_read32(EMAC_RXC_LNERRI)
-#define bfin_write_EMAC_RXC_LNERRI(val)		bfin_write32(EMAC_RXC_LNERRI, val)
-#define bfin_read_EMAC_RXC_LNERRO()		bfin_read32(EMAC_RXC_LNERRO)
-#define bfin_write_EMAC_RXC_LNERRO(val)		bfin_write32(EMAC_RXC_LNERRO, val)
-#define bfin_read_EMAC_RXC_LONG()		bfin_read32(EMAC_RXC_LONG)
-#define bfin_write_EMAC_RXC_LONG(val)		bfin_write32(EMAC_RXC_LONG, val)
-#define bfin_read_EMAC_RXC_MACCTL()		bfin_read32(EMAC_RXC_MACCTL)
-#define bfin_write_EMAC_RXC_MACCTL(val)		bfin_write32(EMAC_RXC_MACCTL, val)
-#define bfin_read_EMAC_RXC_OPCODE()		bfin_read32(EMAC_RXC_OPCODE)
-#define bfin_write_EMAC_RXC_OPCODE(val)		bfin_write32(EMAC_RXC_OPCODE, val)
-#define bfin_read_EMAC_RXC_PAUSE()		bfin_read32(EMAC_RXC_PAUSE)
-#define bfin_write_EMAC_RXC_PAUSE(val)		bfin_write32(EMAC_RXC_PAUSE, val)
-#define bfin_read_EMAC_RXC_ALLFRM()		bfin_read32(EMAC_RXC_ALLFRM)
-#define bfin_write_EMAC_RXC_ALLFRM(val)		bfin_write32(EMAC_RXC_ALLFRM, val)
-#define bfin_read_EMAC_RXC_ALLOCT()		bfin_read32(EMAC_RXC_ALLOCT)
-#define bfin_write_EMAC_RXC_ALLOCT(val)		bfin_write32(EMAC_RXC_ALLOCT, val)
-#define bfin_read_EMAC_RXC_TYPED()		bfin_read32(EMAC_RXC_TYPED)
-#define bfin_write_EMAC_RXC_TYPED(val)		bfin_write32(EMAC_RXC_TYPED, val)
-#define bfin_read_EMAC_RXC_SHORT()		bfin_read32(EMAC_RXC_SHORT)
-#define bfin_write_EMAC_RXC_SHORT(val)		bfin_write32(EMAC_RXC_SHORT, val)
-#define bfin_read_EMAC_RXC_EQ64()		bfin_read32(EMAC_RXC_EQ64)
-#define bfin_write_EMAC_RXC_EQ64(val)		bfin_write32(EMAC_RXC_EQ64, val)
-#define bfin_read_EMAC_RXC_LT128()		bfin_read32(EMAC_RXC_LT128)
-#define bfin_write_EMAC_RXC_LT128(val)		bfin_write32(EMAC_RXC_LT128, val)
-#define bfin_read_EMAC_RXC_LT256()		bfin_read32(EMAC_RXC_LT256)
-#define bfin_write_EMAC_RXC_LT256(val)		bfin_write32(EMAC_RXC_LT256, val)
-#define bfin_read_EMAC_RXC_LT512()		bfin_read32(EMAC_RXC_LT512)
-#define bfin_write_EMAC_RXC_LT512(val)		bfin_write32(EMAC_RXC_LT512, val)
-#define bfin_read_EMAC_RXC_LT1024()		bfin_read32(EMAC_RXC_LT1024)
-#define bfin_write_EMAC_RXC_LT1024(val)		bfin_write32(EMAC_RXC_LT1024, val)
-#define bfin_read_EMAC_RXC_GE1024()		bfin_read32(EMAC_RXC_GE1024)
-#define bfin_write_EMAC_RXC_GE1024(val)		bfin_write32(EMAC_RXC_GE1024, val)
-
-#define bfin_read_EMAC_TXC_OK()			bfin_read32(EMAC_TXC_OK)
-#define bfin_write_EMAC_TXC_OK(val)		bfin_write32(EMAC_TXC_OK, val)
-#define bfin_read_EMAC_TXC_1COL()		bfin_read32(EMAC_TXC_1COL)
-#define bfin_write_EMAC_TXC_1COL(val)		bfin_write32(EMAC_TXC_1COL, val)
-#define bfin_read_EMAC_TXC_GT1COL()		bfin_read32(EMAC_TXC_GT1COL)
-#define bfin_write_EMAC_TXC_GT1COL(val)		bfin_write32(EMAC_TXC_GT1COL, val)
-#define bfin_read_EMAC_TXC_OCTET()		bfin_read32(EMAC_TXC_OCTET)
-#define bfin_write_EMAC_TXC_OCTET(val)		bfin_write32(EMAC_TXC_OCTET, val)
-#define bfin_read_EMAC_TXC_DEFER()		bfin_read32(EMAC_TXC_DEFER)
-#define bfin_write_EMAC_TXC_DEFER(val)		bfin_write32(EMAC_TXC_DEFER, val)
-#define bfin_read_EMAC_TXC_LATECL()		bfin_read32(EMAC_TXC_LATECL)
-#define bfin_write_EMAC_TXC_LATECL(val)		bfin_write32(EMAC_TXC_LATECL, val)
-#define bfin_read_EMAC_TXC_XS_COL()		bfin_read32(EMAC_TXC_XS_COL)
-#define bfin_write_EMAC_TXC_XS_COL(val)		bfin_write32(EMAC_TXC_XS_COL, val)
-#define bfin_read_EMAC_TXC_DMAUND()		bfin_read32(EMAC_TXC_DMAUND)
-#define bfin_write_EMAC_TXC_DMAUND(val)		bfin_write32(EMAC_TXC_DMAUND, val)
-#define bfin_read_EMAC_TXC_CRSERR()		bfin_read32(EMAC_TXC_CRSERR)
-#define bfin_write_EMAC_TXC_CRSERR(val)		bfin_write32(EMAC_TXC_CRSERR, val)
-#define bfin_read_EMAC_TXC_UNICST()		bfin_read32(EMAC_TXC_UNICST)
-#define bfin_write_EMAC_TXC_UNICST(val)		bfin_write32(EMAC_TXC_UNICST, val)
-#define bfin_read_EMAC_TXC_MULTI()		bfin_read32(EMAC_TXC_MULTI)
-#define bfin_write_EMAC_TXC_MULTI(val)		bfin_write32(EMAC_TXC_MULTI, val)
-#define bfin_read_EMAC_TXC_BROAD()		bfin_read32(EMAC_TXC_BROAD)
-#define bfin_write_EMAC_TXC_BROAD(val)		bfin_write32(EMAC_TXC_BROAD, val)
-#define bfin_read_EMAC_TXC_XS_DFR()		bfin_read32(EMAC_TXC_XS_DFR)
-#define bfin_write_EMAC_TXC_XS_DFR(val)		bfin_write32(EMAC_TXC_XS_DFR, val)
-#define bfin_read_EMAC_TXC_MACCTL()		bfin_read32(EMAC_TXC_MACCTL)
-#define bfin_write_EMAC_TXC_MACCTL(val)		bfin_write32(EMAC_TXC_MACCTL, val)
-#define bfin_read_EMAC_TXC_ALLFRM()		bfin_read32(EMAC_TXC_ALLFRM)
-#define bfin_write_EMAC_TXC_ALLFRM(val)		bfin_write32(EMAC_TXC_ALLFRM, val)
-#define bfin_read_EMAC_TXC_ALLOCT()		bfin_read32(EMAC_TXC_ALLOCT)
-#define bfin_write_EMAC_TXC_ALLOCT(val)		bfin_write32(EMAC_TXC_ALLOCT, val)
-#define bfin_read_EMAC_TXC_EQ64()		bfin_read32(EMAC_TXC_EQ64)
-#define bfin_write_EMAC_TXC_EQ64(val)		bfin_write32(EMAC_TXC_EQ64, val)
-#define bfin_read_EMAC_TXC_LT128()		bfin_read32(EMAC_TXC_LT128)
-#define bfin_write_EMAC_TXC_LT128(val)		bfin_write32(EMAC_TXC_LT128, val)
-#define bfin_read_EMAC_TXC_LT256()		bfin_read32(EMAC_TXC_LT256)
-#define bfin_write_EMAC_TXC_LT256(val)		bfin_write32(EMAC_TXC_LT256, val)
-#define bfin_read_EMAC_TXC_LT512()		bfin_read32(EMAC_TXC_LT512)
-#define bfin_write_EMAC_TXC_LT512(val)		bfin_write32(EMAC_TXC_LT512, val)
-#define bfin_read_EMAC_TXC_LT1024()		bfin_read32(EMAC_TXC_LT1024)
-#define bfin_write_EMAC_TXC_LT1024(val)		bfin_write32(EMAC_TXC_LT1024, val)
-#define bfin_read_EMAC_TXC_GE1024()		bfin_read32(EMAC_TXC_GE1024)
-#define bfin_write_EMAC_TXC_GE1024(val)		bfin_write32(EMAC_TXC_GE1024, val)
-#define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
-#define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
+/* PTP TSYNC Registers */
 
 #define bfin_read_EMAC_PTP_CTL()                bfin_read16(EMAC_PTP_CTL)
 #define bfin_write_EMAC_PTP_CTL(val)            bfin_write16(EMAC_PTP_CTL, val)
@@ -227,72 +56,4 @@
 #define bfin_read_EMAC_PTP_PPS_PERIOD()         bfin_read32(EMAC_PTP_PPS_PERIOD)
 #define bfin_write_EMAC_PTP_PPS_PERIOD(val)     bfin_write32(EMAC_PTP_PPS_PERIOD, val)
 
-/* Removable Storage Interface Registers */
-
-#define bfin_read_RSI_PWR_CTL()        bfin_read16(RSI_PWR_CONTROL)
-#define bfin_write_RSI_PWR_CTL(val)    bfin_write16(RSI_PWR_CONTROL, val)
-#define bfin_read_RSI_CLK_CTL()	       bfin_read16(RSI_CLK_CONTROL)
-#define bfin_write_RSI_CLK_CTL(val)    bfin_write16(RSI_CLK_CONTROL, val)
-#define bfin_read_RSI_ARGUMENT()       bfin_read32(RSI_ARGUMENT)
-#define bfin_write_RSI_ARGUMENT(val)   bfin_write32(RSI_ARGUMENT, val)
-#define bfin_read_RSI_COMMAND()        bfin_read16(RSI_COMMAND)
-#define bfin_write_RSI_COMMAND(val)    bfin_write16(RSI_COMMAND, val)
-#define bfin_read_RSI_RESP_CMD()       bfin_read16(RSI_RESP_CMD)
-#define bfin_write_RSI_RESP_CMD(val)   bfin_write16(RSI_RESP_CMD, val)
-#define bfin_read_RSI_RESPONSE0()      bfin_read32(RSI_RESPONSE0)
-#define bfin_write_RSI_RESPONSE0(val)  bfin_write32(RSI_RESPONSE0, val)
-#define bfin_read_RSI_RESPONSE1()      bfin_read32(RSI_RESPONSE1)
-#define bfin_write_RSI_RESPONSE1(val)  bfin_write32(RSI_RESPONSE1, val)
-#define bfin_read_RSI_RESPONSE2()      bfin_read32(RSI_RESPONSE2)
-#define bfin_write_RSI_RESPONSE2(val)  bfin_write32(RSI_RESPONSE2, val)
-#define bfin_read_RSI_RESPONSE3()      bfin_read32(RSI_RESPONSE3)
-#define bfin_write_RSI_RESPONSE3(val)  bfin_write32(RSI_RESPONSE3, val)
-#define bfin_read_RSI_DATA_TIMER()     bfin_read32(RSI_DATA_TIMER)
-#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
-#define bfin_read_RSI_DATA_LGTH()      bfin_read16(RSI_DATA_LGTH)
-#define bfin_write_RSI_DATA_LGTH(val)  bfin_write16(RSI_DATA_LGTH, val)
-#define bfin_read_RSI_DATA_CTL()       bfin_read16(RSI_DATA_CONTROL)
-#define bfin_write_RSI_DATA_CTL(val)   bfin_write16(RSI_DATA_CONTROL, val)
-#define bfin_read_RSI_DATA_CNT()       bfin_read16(RSI_DATA_CNT)
-#define bfin_write_RSI_DATA_CNT(val)   bfin_write16(RSI_DATA_CNT, val)
-#define bfin_read_RSI_STATUS()         bfin_read32(RSI_STATUS)
-#define bfin_write_RSI_STATUS(val)     bfin_write32(RSI_STATUS, val)
-#define bfin_read_RSI_STATUS_CLR()     bfin_read16(RSI_STATUSCL)
-#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
-#define bfin_read_RSI_MASK0()          bfin_read32(RSI_MASK0)
-#define bfin_write_RSI_MASK0(val)      bfin_write32(RSI_MASK0, val)
-#define bfin_read_RSI_MASK1()          bfin_read32(RSI_MASK1)
-#define bfin_write_RSI_MASK1(val)      bfin_write32(RSI_MASK1, val)
-#define bfin_read_RSI_FIFO_CNT()       bfin_read16(RSI_FIFO_CNT)
-#define bfin_write_RSI_FIFO_CNT(val)   bfin_write16(RSI_FIFO_CNT, val)
-#define bfin_read_RSI_CEATA_CTL()      bfin_read16(RSI_CEATA_CONTROL)
-#define bfin_write_RSI_CEATA_CTL(val)  bfin_write16(RSI_CEATA_CONTROL, val)
-#define bfin_read_RSI_FIFO()           bfin_read32(RSI_FIFO)
-#define bfin_write_RSI_FIFO(val)       bfin_write32(RSI_FIFO, val)
-#define bfin_read_RSI_E_STATUS()       bfin_read16(RSI_ESTAT)
-#define bfin_write_RSI_E_STATUS(val)   bfin_write16(RSI_ESTAT, val)
-#define bfin_read_RSI_E_MASK()         bfin_read16(RSI_EMASK)
-#define bfin_write_RSI_E_MASK(val)     bfin_write16(RSI_EMASK, val)
-#define bfin_read_RSI_CFG()            bfin_read16(RSI_CONFIG)
-#define bfin_write_RSI_CFG(val)        bfin_write16(RSI_CONFIG, val)
-#define bfin_read_RSI_RD_WAIT_EN()     bfin_read16(RSI_RD_WAIT_EN)
-#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
-#define bfin_read_RSI_PID0()           bfin_read16(RSI_PID0)
-#define bfin_write_RSI_PID0(val)       bfin_write16(RSI_PID0, val)
-#define bfin_read_RSI_PID1()           bfin_read16(RSI_PID1)
-#define bfin_write_RSI_PID1(val)       bfin_write16(RSI_PID1, val)
-#define bfin_read_RSI_PID2()           bfin_read16(RSI_PID2)
-#define bfin_write_RSI_PID2(val)       bfin_write16(RSI_PID2, val)
-#define bfin_read_RSI_PID3()           bfin_read16(RSI_PID3)
-#define bfin_write_RSI_PID3(val)       bfin_write16(RSI_PID3, val)
-#define bfin_read_RSI_PID4()           bfin_read16(RSI_PID4)
-#define bfin_write_RSI_PID4(val)       bfin_write16(RSI_PID4, val)
-#define bfin_read_RSI_PID5()           bfin_read16(RSI_PID5)
-#define bfin_write_RSI_PID5(val)       bfin_write16(RSI_PID5, val)
-#define bfin_read_RSI_PID6()           bfin_read16(RSI_PID6)
-#define bfin_write_RSI_PID6(val)       bfin_write16(RSI_PID6, val)
-#define bfin_read_RSI_PID7()           bfin_read16(RSI_PID7)
-#define bfin_write_RSI_PID7(val)       bfin_write16(RSI_PID7, val)
-
-
 #endif /* _CDEF_BF518_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
index 1d970df..e548e9d 100644
--- a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
@@ -131,23 +131,6 @@
 #define bfin_write_UART0_GCTL(val)		bfin_write16(UART0_GCTL, val)
 
 
-/* SPI Controller		(0xFFC00500 - 0xFFC005FF)									*/
-#define bfin_read_SPI_CTL()			bfin_read16(SPI_CTL)
-#define bfin_write_SPI_CTL(val)			bfin_write16(SPI_CTL, val)
-#define bfin_read_SPI_FLG()			bfin_read16(SPI_FLG)
-#define bfin_write_SPI_FLG(val)			bfin_write16(SPI_FLG, val)
-#define bfin_read_SPI_STAT()			bfin_read16(SPI_STAT)
-#define bfin_write_SPI_STAT(val)		bfin_write16(SPI_STAT, val)
-#define bfin_read_SPI_TDBR()			bfin_read16(SPI_TDBR)
-#define bfin_write_SPI_TDBR(val)		bfin_write16(SPI_TDBR, val)
-#define bfin_read_SPI_RDBR()			bfin_read16(SPI_RDBR)
-#define bfin_write_SPI_RDBR(val)		bfin_write16(SPI_RDBR, val)
-#define bfin_read_SPI_BAUD()			bfin_read16(SPI_BAUD)
-#define bfin_write_SPI_BAUD(val)		bfin_write16(SPI_BAUD, val)
-#define bfin_read_SPI_SHADOW()			bfin_read16(SPI_SHADOW)
-#define bfin_write_SPI_SHADOW(val)		bfin_write16(SPI_SHADOW, val)
-
-
 /* TIMER0-7 Registers		(0xFFC00600 - 0xFFC006FF)								*/
 #define bfin_read_TIMER0_CONFIG()		bfin_read16(TIMER0_CONFIG)
 #define bfin_write_TIMER0_CONFIG(val)		bfin_write16(TIMER0_CONFIG, val)
@@ -844,6 +827,7 @@
 #define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
 #define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
 #define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
+#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
 #define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
 #define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
 #define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
@@ -1062,17 +1046,6 @@
 #define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
 #define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
 
-/* OTP/FUSE Registers */
-
-#define bfin_read_OTP_CONTROL()			bfin_read16(OTP_CONTROL)
-#define bfin_write_OTP_CONTROL(val)		bfin_write16(OTP_CONTROL, val)
-#define bfin_read_OTP_BEN()			bfin_read16(OTP_BEN)
-#define bfin_write_OTP_BEN(val)			bfin_write16(OTP_BEN, val)
-#define bfin_read_OTP_STATUS()			bfin_read16(OTP_STATUS)
-#define bfin_write_OTP_STATUS(val)		bfin_write16(OTP_STATUS, val)
-#define bfin_read_OTP_TIMING()			bfin_read32(OTP_TIMING)
-#define bfin_write_OTP_TIMING(val)		bfin_write32(OTP_TIMING, val)
-
 /* Security Registers */
 
 #define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
@@ -1082,52 +1055,6 @@
 #define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
 #define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
 
-/* OTP Read/Write Data Buffer Registers */
-
-#define bfin_read_OTP_DATA0()			bfin_read32(OTP_DATA0)
-#define bfin_write_OTP_DATA0(val)		bfin_write32(OTP_DATA0, val)
-#define bfin_read_OTP_DATA1()			bfin_read32(OTP_DATA1)
-#define bfin_write_OTP_DATA1(val)		bfin_write32(OTP_DATA1, val)
-#define bfin_read_OTP_DATA2()			bfin_read32(OTP_DATA2)
-#define bfin_write_OTP_DATA2(val)		bfin_write32(OTP_DATA2, val)
-#define bfin_read_OTP_DATA3()			bfin_read32(OTP_DATA3)
-#define bfin_write_OTP_DATA3(val)		bfin_write32(OTP_DATA3, val)
-
-/* NFC Registers */
-
-#define bfin_read_NFC_CTL()			bfin_read16(NFC_CTL)
-#define bfin_write_NFC_CTL(val)			bfin_write16(NFC_CTL, val)
-#define bfin_read_NFC_STAT()			bfin_read16(NFC_STAT)
-#define bfin_write_NFC_STAT(val)		bfin_write16(NFC_STAT, val)
-#define bfin_read_NFC_IRQSTAT()			bfin_read16(NFC_IRQSTAT)
-#define bfin_write_NFC_IRQSTAT(val)		bfin_write16(NFC_IRQSTAT, val)
-#define bfin_read_NFC_IRQMASK()			bfin_read16(NFC_IRQMASK)
-#define bfin_write_NFC_IRQMASK(val)		bfin_write16(NFC_IRQMASK, val)
-#define bfin_read_NFC_ECC0()			bfin_read16(NFC_ECC0)
-#define bfin_write_NFC_ECC0(val)		bfin_write16(NFC_ECC0, val)
-#define bfin_read_NFC_ECC1()			bfin_read16(NFC_ECC1)
-#define bfin_write_NFC_ECC1(val)		bfin_write16(NFC_ECC1, val)
-#define bfin_read_NFC_ECC2()			bfin_read16(NFC_ECC2)
-#define bfin_write_NFC_ECC2(val)		bfin_write16(NFC_ECC2, val)
-#define bfin_read_NFC_ECC3()			bfin_read16(NFC_ECC3)
-#define bfin_write_NFC_ECC3(val)		bfin_write16(NFC_ECC3, val)
-#define bfin_read_NFC_COUNT()			bfin_read16(NFC_COUNT)
-#define bfin_write_NFC_COUNT(val)		bfin_write16(NFC_COUNT, val)
-#define bfin_read_NFC_RST()			bfin_read16(NFC_RST)
-#define bfin_write_NFC_RST(val)			bfin_write16(NFC_RST, val)
-#define bfin_read_NFC_PGCTL()			bfin_read16(NFC_PGCTL)
-#define bfin_write_NFC_PGCTL(val)		bfin_write16(NFC_PGCTL, val)
-#define bfin_read_NFC_READ()			bfin_read16(NFC_READ)
-#define bfin_write_NFC_READ(val)		bfin_write16(NFC_READ, val)
-#define bfin_read_NFC_ADDR()			bfin_read16(NFC_ADDR)
-#define bfin_write_NFC_ADDR(val)		bfin_write16(NFC_ADDR, val)
-#define bfin_read_NFC_CMD()			bfin_read16(NFC_CMD)
-#define bfin_write_NFC_CMD(val)			bfin_write16(NFC_CMD, val)
-#define bfin_read_NFC_DATA_WR()			bfin_read16(NFC_DATA_WR)
-#define bfin_write_NFC_DATA_WR(val)		bfin_write16(NFC_DATA_WR, val)
-#define bfin_read_NFC_DATA_RD()			bfin_read16(NFC_DATA_RD)
-#define bfin_write_NFC_DATA_RD(val)		bfin_write16(NFC_DATA_RD, val)
-
 /* These need to be last due to the cdef/linux inter-dependencies */
 #include <asm/irq.h>
 
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF514.h b/arch/blackfin/mach-bf518/include/mach/defBF514.h
index b5adca2..92e950d 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF514.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF514.h
@@ -7,49 +7,8 @@
 #ifndef _DEF_BF514_H
 #define _DEF_BF514_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF514 */
-
-/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "defBF51x_base.h"
-
-/* The following are the #defines needed by ADSP-BF514 that are not in the common header */
-
-/* SDH Registers */
-
-#define SDH_PWR_CTL                    0xFFC03900 /* SDH Power Control */
-#define SDH_CLK_CTL                    0xFFC03904 /* SDH Clock Control */
-#define SDH_ARGUMENT                   0xFFC03908 /* SDH Argument */
-#define SDH_COMMAND                    0xFFC0390C /* SDH Command */
-#define SDH_RESP_CMD                   0xFFC03910 /* SDH Response Command */
-#define SDH_RESPONSE0                  0xFFC03914 /* SDH Response0 */
-#define SDH_RESPONSE1                  0xFFC03918 /* SDH Response1 */
-#define SDH_RESPONSE2                  0xFFC0391C /* SDH Response2 */
-#define SDH_RESPONSE3                  0xFFC03920 /* SDH Response3 */
-#define SDH_DATA_TIMER                 0xFFC03924 /* SDH Data Timer */
-#define SDH_DATA_LGTH                  0xFFC03928 /* SDH Data Length */
-#define SDH_DATA_CTL                   0xFFC0392C /* SDH Data Control */
-#define SDH_DATA_CNT                   0xFFC03930 /* SDH Data Counter */
-#define SDH_STATUS                     0xFFC03934 /* SDH Status */
-#define SDH_STATUS_CLR                 0xFFC03938 /* SDH Status Clear */
-#define SDH_MASK0                      0xFFC0393C /* SDH Interrupt0 Mask */
-#define SDH_MASK1                      0xFFC03940 /* SDH Interrupt1 Mask */
-#define SDH_FIFO_CNT                   0xFFC03948 /* SDH FIFO Counter */
-#define SDH_FIFO                       0xFFC03980 /* SDH Data FIFO */
-#define SDH_E_STATUS                   0xFFC039C0 /* SDH Exception Status */
-#define SDH_E_MASK                     0xFFC039C4 /* SDH Exception Mask */
-#define SDH_CFG                        0xFFC039C8 /* SDH Configuration */
-#define SDH_RD_WAIT_EN                 0xFFC039CC /* SDH Read Wait Enable */
-#define SDH_PID0                       0xFFC039D0 /* SDH Peripheral Identification0 */
-#define SDH_PID1                       0xFFC039D4 /* SDH Peripheral Identification1 */
-#define SDH_PID2                       0xFFC039D8 /* SDH Peripheral Identification2 */
-#define SDH_PID3                       0xFFC039DC /* SDH Peripheral Identification3 */
-#define SDH_PID4                       0xFFC039E0 /* SDH Peripheral Identification4 */
-#define SDH_PID5                       0xFFC039E4 /* SDH Peripheral Identification5 */
-#define SDH_PID6                       0xFFC039E8 /* SDH Peripheral Identification6 */
-#define SDH_PID7                       0xFFC039EC /* SDH Peripheral Identification7 */
+/* BF514 is BF512 + RSI */
+#include "defBF512.h"
 
 /* Removable Storage Interface Registers */
 
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF516.h b/arch/blackfin/mach-bf518/include/mach/defBF516.h
index 7eb1877..22a3aa0 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF516.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF516.h
@@ -7,13 +7,8 @@
 #ifndef _DEF_BF516_H
 #define _DEF_BF516_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF516 */
-
-/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "defBF51x_base.h"
+/* BF516 is BF514 + EMAC */
+#include "defBF514.h"
 
 /* The following are the #defines needed by ADSP-BF516 that are not in the common header */
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
@@ -394,208 +389,4 @@
 #define	TX_GE1024_CNT     0x00200000    /* 1024-Max-Byte TX Frames Sent                           */
 #define	TX_ABORT_CNT      0x00400000    /* TX Frames Aborted                                      */
 
-/* SDH Registers */
-
-#define SDH_PWR_CTL                    0xFFC03900 /* SDH Power Control */
-#define SDH_CLK_CTL                    0xFFC03904 /* SDH Clock Control */
-#define SDH_ARGUMENT                   0xFFC03908 /* SDH Argument */
-#define SDH_COMMAND                    0xFFC0390C /* SDH Command */
-#define SDH_RESP_CMD                   0xFFC03910 /* SDH Response Command */
-#define SDH_RESPONSE0                  0xFFC03914 /* SDH Response0 */
-#define SDH_RESPONSE1                  0xFFC03918 /* SDH Response1 */
-#define SDH_RESPONSE2                  0xFFC0391C /* SDH Response2 */
-#define SDH_RESPONSE3                  0xFFC03920 /* SDH Response3 */
-#define SDH_DATA_TIMER                 0xFFC03924 /* SDH Data Timer */
-#define SDH_DATA_LGTH                  0xFFC03928 /* SDH Data Length */
-#define SDH_DATA_CTL                   0xFFC0392C /* SDH Data Control */
-#define SDH_DATA_CNT                   0xFFC03930 /* SDH Data Counter */
-#define SDH_STATUS                     0xFFC03934 /* SDH Status */
-#define SDH_STATUS_CLR                 0xFFC03938 /* SDH Status Clear */
-#define SDH_MASK0                      0xFFC0393C /* SDH Interrupt0 Mask */
-#define SDH_MASK1                      0xFFC03940 /* SDH Interrupt1 Mask */
-#define SDH_FIFO_CNT                   0xFFC03948 /* SDH FIFO Counter */
-#define SDH_FIFO                       0xFFC03980 /* SDH Data FIFO */
-#define SDH_E_STATUS                   0xFFC039C0 /* SDH Exception Status */
-#define SDH_E_MASK                     0xFFC039C4 /* SDH Exception Mask */
-#define SDH_CFG                        0xFFC039C8 /* SDH Configuration */
-#define SDH_RD_WAIT_EN                 0xFFC039CC /* SDH Read Wait Enable */
-#define SDH_PID0                       0xFFC039D0 /* SDH Peripheral Identification0 */
-#define SDH_PID1                       0xFFC039D4 /* SDH Peripheral Identification1 */
-#define SDH_PID2                       0xFFC039D8 /* SDH Peripheral Identification2 */
-#define SDH_PID3                       0xFFC039DC /* SDH Peripheral Identification3 */
-#define SDH_PID4                       0xFFC039E0 /* SDH Peripheral Identification4 */
-#define SDH_PID5                       0xFFC039E4 /* SDH Peripheral Identification5 */
-#define SDH_PID6                       0xFFC039E8 /* SDH Peripheral Identification6 */
-#define SDH_PID7                       0xFFC039EC /* SDH Peripheral Identification7 */
-
-/* Removable Storage Interface Registers */
-
-#define RSI_PWR_CONTROL                0xFFC03800 /* RSI Power Control Register */
-#define RSI_CLK_CONTROL                0xFFC03804 /* RSI Clock Control Register */
-#define RSI_ARGUMENT                   0xFFC03808 /* RSI Argument Register */
-#define RSI_COMMAND                    0xFFC0380C /* RSI Command Register */
-#define RSI_RESP_CMD                   0xFFC03810 /* RSI Response Command Register */
-#define RSI_RESPONSE0                  0xFFC03814 /* RSI Response Register */
-#define RSI_RESPONSE1                  0xFFC03818 /* RSI Response Register */
-#define RSI_RESPONSE2                  0xFFC0381C /* RSI Response Register */
-#define RSI_RESPONSE3                  0xFFC03820 /* RSI Response Register */
-#define RSI_DATA_TIMER                 0xFFC03824 /* RSI Data Timer Register */
-#define RSI_DATA_LGTH                  0xFFC03828 /* RSI Data Length Register */
-#define RSI_DATA_CONTROL               0xFFC0382C /* RSI Data Control Register */
-#define RSI_DATA_CNT                   0xFFC03830 /* RSI Data Counter Register */
-#define RSI_STATUS                     0xFFC03834 /* RSI Status Register */
-#define RSI_STATUSCL                   0xFFC03838 /* RSI Status Clear Register */
-#define RSI_MASK0                      0xFFC0383C /* RSI Interrupt 0 Mask Register */
-#define RSI_MASK1                      0xFFC03840 /* RSI Interrupt 1 Mask Register */
-#define RSI_FIFO_CNT                   0xFFC03848 /* RSI FIFO Counter Register */
-#define RSI_CEATA_CONTROL              0xFFC0384C /* RSI CEATA Register */
-#define RSI_FIFO                       0xFFC03880 /* RSI Data FIFO Register */
-#define RSI_ESTAT                      0xFFC038C0 /* RSI Exception Status Register */
-#define RSI_EMASK                      0xFFC038C4 /* RSI Exception Mask Register */
-#define RSI_CONFIG                     0xFFC038C8 /* RSI Configuration Register */
-#define RSI_RD_WAIT_EN                 0xFFC038CC /* RSI Read Wait Enable Register */
-#define RSI_PID0                       0xFFC03FE0 /* RSI Peripheral ID Register 0 */
-#define RSI_PID1                       0xFFC03FE4 /* RSI Peripheral ID Register 1 */
-#define RSI_PID2                       0xFFC03FE8 /* RSI Peripheral ID Register 2 */
-#define RSI_PID3                       0xFFC03FEC /* RSI Peripheral ID Register 3 */
-#define RSI_PID4                       0xFFC03FF0 /* RSI Peripheral ID Register 4 */
-#define RSI_PID5                       0xFFC03FF4 /* RSI Peripheral ID Register 5 */
-#define RSI_PID6                       0xFFC03FF8 /* RSI Peripheral ID Register 6 */
-#define RSI_PID7                       0xFFC03FFC /* RSI Peripheral ID Register 7 */
-
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for SDH_COMMAND */
-
-#define                   CMD_IDX  0x3f       /* Command Index */
-#define                   CMD_RSP  0x40       /* Response */
-#define                 CMD_L_RSP  0x80       /* Long Response */
-#define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                CMD_PEND_E  0x200      /* Command Pending */
-#define                     CMD_E  0x400      /* Command Enable */
-
-/* Bit masks for SDH_PWR_CTL */
-
-#define                    PWR_ON  0x3        /* Power On */
-#if 0
-#define                       TBD  0x3c       /* TBD */
-#endif
-#define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                   ROD_CTL  0x80       /* Rod Control */
-
-/* Bit masks for SDH_CLK_CTL */
-
-#define                    CLKDIV  0xff       /* MC_CLK Divisor */
-#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-
-/* Bit masks for SDH_RESP_CMD */
-
-#define                  RESP_CMD  0x3f       /* Response Command */
-
-/* Bit masks for SDH_DATA_CTL */
-
-#define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
-
-/* Bit masks for SDH_STATUS */
-
-#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
-#define               DAT_TIME_OUT  0x8        /* Data Time Out */
-#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define              CMD_RESP_END  0x40       /* CMD Response End */
-#define                  CMD_SENT  0x80       /* CMD Sent */
-#define                   DAT_END  0x100      /* Data End */
-#define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define               DAT_BLK_END  0x400      /* Data Block End */
-#define                   CMD_ACT  0x800      /* CMD Active */
-#define                    TX_ACT  0x1000     /* Transmit Active */
-#define                    RX_ACT  0x2000     /* Receive Active */
-#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-
-/* Bit masks for SDH_STATUS_CLR */
-
-#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define              DAT_END_STAT  0x100      /* Data End Status */
-#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-
-/* Bit masks for SDH_MASK0 */
-
-#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define              DAT_END_MASK  0x100      /* Data End Mask */
-#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-
-/* Bit masks for SDH_FIFO_CNT */
-
-#define                FIFO_COUNT  0x7fff     /* FIFO Count */
-
-/* Bit masks for SDH_E_STATUS */
-
-#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define               SD_CARD_DET  0x10       /* SD Card Detect */
-
-/* Bit masks for SDH_E_MASK */
-
-#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                   SCD_MSK  0x40       /* Mask Card Detect */
-
-/* Bit masks for SDH_CFG */
-
-#define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                       MWE  0x8        /* Moving Window Enable */
-#define                    SD_RST  0x10       /* SDMMC Reset */
-#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-
-/* Bit masks for SDH_RD_WAIT_EN */
-
-#define                       RWR  0x1        /* Read Wait Request */
-
 #endif /* _DEF_BF516_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF518.h b/arch/blackfin/mach-bf518/include/mach/defBF518.h
index 794cf06e..cb18270 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF518.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF518.h
@@ -7,461 +7,8 @@
 #ifndef _DEF_BF518_H
 #define _DEF_BF518_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF518 */
-
-/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
-#include "defBF51x_base.h"
-
-/* The following are the #defines needed by ADSP-BF518 that are not in the common header */
-/* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
-
-#define EMAC_OPMODE             0xFFC03000       /* Operating Mode Register                              */
-#define EMAC_ADDRLO             0xFFC03004       /* Address Low (32 LSBs) Register                       */
-#define EMAC_ADDRHI             0xFFC03008       /* Address High (16 MSBs) Register                      */
-#define EMAC_HASHLO             0xFFC0300C       /* Multicast Hash Table Low (Bins 31-0) Register        */
-#define EMAC_HASHHI             0xFFC03010       /* Multicast Hash Table High (Bins 63-32) Register      */
-#define EMAC_STAADD             0xFFC03014       /* Station Management Address Register                  */
-#define EMAC_STADAT             0xFFC03018       /* Station Management Data Register                     */
-#define EMAC_FLC                0xFFC0301C       /* Flow Control Register                                */
-#define EMAC_VLAN1              0xFFC03020       /* VLAN1 Tag Register                                   */
-#define EMAC_VLAN2              0xFFC03024       /* VLAN2 Tag Register                                   */
-#define EMAC_WKUP_CTL           0xFFC0302C       /* Wake-Up Control/Status Register                      */
-#define EMAC_WKUP_FFMSK0        0xFFC03030       /* Wake-Up Frame Filter 0 Byte Mask Register            */
-#define EMAC_WKUP_FFMSK1        0xFFC03034       /* Wake-Up Frame Filter 1 Byte Mask Register            */
-#define EMAC_WKUP_FFMSK2        0xFFC03038       /* Wake-Up Frame Filter 2 Byte Mask Register            */
-#define EMAC_WKUP_FFMSK3        0xFFC0303C       /* Wake-Up Frame Filter 3 Byte Mask Register            */
-#define EMAC_WKUP_FFCMD         0xFFC03040       /* Wake-Up Frame Filter Commands Register               */
-#define EMAC_WKUP_FFOFF         0xFFC03044       /* Wake-Up Frame Filter Offsets Register                */
-#define EMAC_WKUP_FFCRC0        0xFFC03048       /* Wake-Up Frame Filter 0,1 CRC-16 Register             */
-#define EMAC_WKUP_FFCRC1        0xFFC0304C       /* Wake-Up Frame Filter 2,3 CRC-16 Register             */
-
-#define EMAC_SYSCTL             0xFFC03060       /* EMAC System Control Register                         */
-#define EMAC_SYSTAT             0xFFC03064       /* EMAC System Status Register                          */
-#define EMAC_RX_STAT            0xFFC03068       /* RX Current Frame Status Register                     */
-#define EMAC_RX_STKY            0xFFC0306C       /* RX Sticky Frame Status Register                      */
-#define EMAC_RX_IRQE            0xFFC03070       /* RX Frame Status Interrupt Enables Register           */
-#define EMAC_TX_STAT            0xFFC03074       /* TX Current Frame Status Register                     */
-#define EMAC_TX_STKY            0xFFC03078       /* TX Sticky Frame Status Register                      */
-#define EMAC_TX_IRQE            0xFFC0307C       /* TX Frame Status Interrupt Enables Register           */
-
-#define EMAC_MMC_CTL            0xFFC03080       /* MMC Counter Control Register                         */
-#define EMAC_MMC_RIRQS          0xFFC03084       /* MMC RX Interrupt Status Register                     */
-#define EMAC_MMC_RIRQE          0xFFC03088       /* MMC RX Interrupt Enables Register                    */
-#define EMAC_MMC_TIRQS          0xFFC0308C       /* MMC TX Interrupt Status Register                     */
-#define EMAC_MMC_TIRQE          0xFFC03090       /* MMC TX Interrupt Enables Register                    */
-
-#define EMAC_RXC_OK             0xFFC03100       /* RX Frame Successful Count                            */
-#define EMAC_RXC_FCS            0xFFC03104       /* RX Frame FCS Failure Count                           */
-#define EMAC_RXC_ALIGN          0xFFC03108       /* RX Alignment Error Count                             */
-#define EMAC_RXC_OCTET          0xFFC0310C       /* RX Octets Successfully Received Count                */
-#define EMAC_RXC_DMAOVF         0xFFC03110       /* Internal MAC Sublayer Error RX Frame Count           */
-#define EMAC_RXC_UNICST         0xFFC03114       /* Unicast RX Frame Count                               */
-#define EMAC_RXC_MULTI          0xFFC03118       /* Multicast RX Frame Count                             */
-#define EMAC_RXC_BROAD          0xFFC0311C       /* Broadcast RX Frame Count                             */
-#define EMAC_RXC_LNERRI         0xFFC03120       /* RX Frame In Range Error Count                        */
-#define EMAC_RXC_LNERRO         0xFFC03124       /* RX Frame Out Of Range Error Count                    */
-#define EMAC_RXC_LONG           0xFFC03128       /* RX Frame Too Long Count                              */
-#define EMAC_RXC_MACCTL         0xFFC0312C       /* MAC Control RX Frame Count                           */
-#define EMAC_RXC_OPCODE         0xFFC03130       /* Unsupported Op-Code RX Frame Count                   */
-#define EMAC_RXC_PAUSE          0xFFC03134       /* MAC Control Pause RX Frame Count                     */
-#define EMAC_RXC_ALLFRM         0xFFC03138       /* Overall RX Frame Count                               */
-#define EMAC_RXC_ALLOCT         0xFFC0313C       /* Overall RX Octet Count                               */
-#define EMAC_RXC_TYPED          0xFFC03140       /* Type/Length Consistent RX Frame Count                */
-#define EMAC_RXC_SHORT          0xFFC03144       /* RX Frame Fragment Count - Byte Count x < 64          */
-#define EMAC_RXC_EQ64           0xFFC03148       /* Good RX Frame Count - Byte Count x = 64              */
-#define EMAC_RXC_LT128          0xFFC0314C       /* Good RX Frame Count - Byte Count  64 < x < 128       */
-#define EMAC_RXC_LT256          0xFFC03150       /* Good RX Frame Count - Byte Count 128 <= x < 256      */
-#define EMAC_RXC_LT512          0xFFC03154       /* Good RX Frame Count - Byte Count 256 <= x < 512      */
-#define EMAC_RXC_LT1024         0xFFC03158       /* Good RX Frame Count - Byte Count 512 <= x < 1024     */
-#define EMAC_RXC_GE1024         0xFFC0315C       /* Good RX Frame Count - Byte Count x >= 1024           */
-
-#define EMAC_TXC_OK             0xFFC03180       /* TX Frame Successful Count                             */
-#define EMAC_TXC_1COL           0xFFC03184       /* TX Frames Successful After Single Collision Count     */
-#define EMAC_TXC_GT1COL         0xFFC03188       /* TX Frames Successful After Multiple Collisions Count  */
-#define EMAC_TXC_OCTET          0xFFC0318C       /* TX Octets Successfully Received Count                 */
-#define EMAC_TXC_DEFER          0xFFC03190       /* TX Frame Delayed Due To Busy Count                    */
-#define EMAC_TXC_LATECL         0xFFC03194       /* Late TX Collisions Count                              */
-#define EMAC_TXC_XS_COL         0xFFC03198       /* TX Frame Failed Due To Excessive Collisions Count     */
-#define EMAC_TXC_DMAUND         0xFFC0319C       /* Internal MAC Sublayer Error TX Frame Count            */
-#define EMAC_TXC_CRSERR         0xFFC031A0       /* Carrier Sense Deasserted During TX Frame Count        */
-#define EMAC_TXC_UNICST         0xFFC031A4       /* Unicast TX Frame Count                                */
-#define EMAC_TXC_MULTI          0xFFC031A8       /* Multicast TX Frame Count                              */
-#define EMAC_TXC_BROAD          0xFFC031AC       /* Broadcast TX Frame Count                              */
-#define EMAC_TXC_XS_DFR         0xFFC031B0       /* TX Frames With Excessive Deferral Count               */
-#define EMAC_TXC_MACCTL         0xFFC031B4       /* MAC Control TX Frame Count                            */
-#define EMAC_TXC_ALLFRM         0xFFC031B8       /* Overall TX Frame Count                                */
-#define EMAC_TXC_ALLOCT         0xFFC031BC       /* Overall TX Octet Count                                */
-#define EMAC_TXC_EQ64           0xFFC031C0       /* Good TX Frame Count - Byte Count x = 64               */
-#define EMAC_TXC_LT128          0xFFC031C4       /* Good TX Frame Count - Byte Count  64 < x < 128        */
-#define EMAC_TXC_LT256          0xFFC031C8       /* Good TX Frame Count - Byte Count 128 <= x < 256       */
-#define EMAC_TXC_LT512          0xFFC031CC       /* Good TX Frame Count - Byte Count 256 <= x < 512       */
-#define EMAC_TXC_LT1024         0xFFC031D0       /* Good TX Frame Count - Byte Count 512 <= x < 1024      */
-#define EMAC_TXC_GE1024         0xFFC031D4       /* Good TX Frame Count - Byte Count x >= 1024            */
-#define EMAC_TXC_ABORT          0xFFC031D8       /* Total TX Frames Aborted Count                         */
-
-/* Listing for IEEE-Supported Count Registers */
-
-#define FramesReceivedOK                EMAC_RXC_OK        /* RX Frame Successful Count                            */
-#define FrameCheckSequenceErrors        EMAC_RXC_FCS       /* RX Frame FCS Failure Count                           */
-#define AlignmentErrors                 EMAC_RXC_ALIGN     /* RX Alignment Error Count                             */
-#define OctetsReceivedOK                EMAC_RXC_OCTET     /* RX Octets Successfully Received Count                */
-#define FramesLostDueToIntMACRcvError   EMAC_RXC_DMAOVF    /* Internal MAC Sublayer Error RX Frame Count           */
-#define UnicastFramesReceivedOK         EMAC_RXC_UNICST    /* Unicast RX Frame Count                               */
-#define MulticastFramesReceivedOK       EMAC_RXC_MULTI     /* Multicast RX Frame Count                             */
-#define BroadcastFramesReceivedOK       EMAC_RXC_BROAD     /* Broadcast RX Frame Count                             */
-#define InRangeLengthErrors             EMAC_RXC_LNERRI    /* RX Frame In Range Error Count                        */
-#define OutOfRangeLengthField           EMAC_RXC_LNERRO    /* RX Frame Out Of Range Error Count                    */
-#define FrameTooLongErrors              EMAC_RXC_LONG      /* RX Frame Too Long Count                              */
-#define MACControlFramesReceived        EMAC_RXC_MACCTL    /* MAC Control RX Frame Count                           */
-#define UnsupportedOpcodesReceived      EMAC_RXC_OPCODE    /* Unsupported Op-Code RX Frame Count                   */
-#define PAUSEMACCtrlFramesReceived      EMAC_RXC_PAUSE     /* MAC Control Pause RX Frame Count                     */
-#define FramesReceivedAll               EMAC_RXC_ALLFRM    /* Overall RX Frame Count                               */
-#define OctetsReceivedAll               EMAC_RXC_ALLOCT    /* Overall RX Octet Count                               */
-#define TypedFramesReceived             EMAC_RXC_TYPED     /* Type/Length Consistent RX Frame Count                */
-#define FramesLenLt64Received           EMAC_RXC_SHORT     /* RX Frame Fragment Count - Byte Count x < 64          */
-#define FramesLenEq64Received           EMAC_RXC_EQ64      /* Good RX Frame Count - Byte Count x = 64              */
-#define FramesLen65_127Received         EMAC_RXC_LT128     /* Good RX Frame Count - Byte Count  64 < x < 128       */
-#define FramesLen128_255Received        EMAC_RXC_LT256     /* Good RX Frame Count - Byte Count 128 <= x < 256      */
-#define FramesLen256_511Received        EMAC_RXC_LT512     /* Good RX Frame Count - Byte Count 256 <= x < 512      */
-#define FramesLen512_1023Received       EMAC_RXC_LT1024    /* Good RX Frame Count - Byte Count 512 <= x < 1024     */
-#define FramesLen1024_MaxReceived       EMAC_RXC_GE1024    /* Good RX Frame Count - Byte Count x >= 1024           */
-
-#define FramesTransmittedOK             EMAC_TXC_OK        /* TX Frame Successful Count                            */
-#define SingleCollisionFrames           EMAC_TXC_1COL      /* TX Frames Successful After Single Collision Count    */
-#define MultipleCollisionFrames         EMAC_TXC_GT1COL    /* TX Frames Successful After Multiple Collisions Count */
-#define OctetsTransmittedOK             EMAC_TXC_OCTET     /* TX Octets Successfully Received Count                */
-#define FramesWithDeferredXmissions     EMAC_TXC_DEFER     /* TX Frame Delayed Due To Busy Count                   */
-#define LateCollisions                  EMAC_TXC_LATECL    /* Late TX Collisions Count                             */
-#define FramesAbortedDueToXSColls       EMAC_TXC_XS_COL    /* TX Frame Failed Due To Excessive Collisions Count    */
-#define FramesLostDueToIntMacXmitError  EMAC_TXC_DMAUND    /* Internal MAC Sublayer Error TX Frame Count           */
-#define CarrierSenseErrors              EMAC_TXC_CRSERR    /* Carrier Sense Deasserted During TX Frame Count       */
-#define UnicastFramesXmittedOK          EMAC_TXC_UNICST    /* Unicast TX Frame Count                               */
-#define MulticastFramesXmittedOK        EMAC_TXC_MULTI     /* Multicast TX Frame Count                             */
-#define BroadcastFramesXmittedOK        EMAC_TXC_BROAD     /* Broadcast TX Frame Count                             */
-#define FramesWithExcessiveDeferral     EMAC_TXC_XS_DFR    /* TX Frames With Excessive Deferral Count              */
-#define MACControlFramesTransmitted     EMAC_TXC_MACCTL    /* MAC Control TX Frame Count                           */
-#define FramesTransmittedAll            EMAC_TXC_ALLFRM    /* Overall TX Frame Count                               */
-#define OctetsTransmittedAll            EMAC_TXC_ALLOCT    /* Overall TX Octet Count                               */
-#define FramesLenEq64Transmitted        EMAC_TXC_EQ64      /* Good TX Frame Count - Byte Count x = 64              */
-#define FramesLen65_127Transmitted      EMAC_TXC_LT128     /* Good TX Frame Count - Byte Count  64 < x < 128       */
-#define FramesLen128_255Transmitted     EMAC_TXC_LT256     /* Good TX Frame Count - Byte Count 128 <= x < 256      */
-#define FramesLen256_511Transmitted     EMAC_TXC_LT512     /* Good TX Frame Count - Byte Count 256 <= x < 512      */
-#define FramesLen512_1023Transmitted    EMAC_TXC_LT1024    /* Good TX Frame Count - Byte Count 512 <= x < 1024     */
-#define FramesLen1024_MaxTransmitted    EMAC_TXC_GE1024    /* Good TX Frame Count - Byte Count x >= 1024           */
-#define TxAbortedFrames                 EMAC_TXC_ABORT     /* Total TX Frames Aborted Count                        */
-
-/***********************************************************************************
-** System MMR Register Bits And Macros
-**
-** Disclaimer:	All macros are intended to make C and Assembly code more readable.
-**				Use these macros carefully, as any that do left shifts for field
-**				depositing will result in the lower order bits being destroyed.  Any
-**				macro that shifts left to properly position the bit-field should be
-**				used as part of an OR to initialize a register and NOT as a dynamic
-**				modifier UNLESS the lower order bits are saved and ORed back in when
-**				the macro is used.
-*************************************************************************************/
-
-/************************  ETHERNET 10/100 CONTROLLER MASKS  ************************/
-
-/* EMAC_OPMODE Masks */
-
-#define	RE                 0x00000001     /* Receiver Enable                                    */
-#define	ASTP               0x00000002     /* Enable Automatic Pad Stripping On RX Frames        */
-#define	HU                 0x00000010     /* Hash Filter Unicast Address                        */
-#define	HM                 0x00000020     /* Hash Filter Multicast Address                      */
-#define	PAM                0x00000040     /* Pass-All-Multicast Mode Enable                     */
-#define	PR                 0x00000080     /* Promiscuous Mode Enable                            */
-#define	IFE                0x00000100     /* Inverse Filtering Enable                           */
-#define	DBF                0x00000200     /* Disable Broadcast Frame Reception                  */
-#define	PBF                0x00000400     /* Pass Bad Frames Enable                             */
-#define	PSF                0x00000800     /* Pass Short Frames Enable                           */
-#define	RAF                0x00001000     /* Receive-All Mode                                   */
-#define	TE                 0x00010000     /* Transmitter Enable                                 */
-#define	DTXPAD             0x00020000     /* Disable Automatic TX Padding                       */
-#define	DTXCRC             0x00040000     /* Disable Automatic TX CRC Generation                */
-#define	DC                 0x00080000     /* Deferral Check                                     */
-#define	BOLMT              0x00300000     /* Back-Off Limit                                     */
-#define	BOLMT_10           0x00000000     /*		10-bit range                            */
-#define	BOLMT_8            0x00100000     /*		8-bit range                             */
-#define	BOLMT_4            0x00200000     /*		4-bit range                             */
-#define	BOLMT_1            0x00300000     /*		1-bit range                             */
-#define	DRTY               0x00400000     /* Disable TX Retry On Collision                      */
-#define	LCTRE              0x00800000     /* Enable TX Retry On Late Collision                  */
-#define	RMII               0x01000000     /* RMII/MII* Mode                                     */
-#define	RMII_10            0x02000000     /* Speed Select for RMII Port (10MBit/100MBit*)       */
-#define	FDMODE             0x04000000     /* Duplex Mode Enable (Full/Half*)                    */
-#define	LB                 0x08000000     /* Internal Loopback Enable                           */
-#define	DRO                0x10000000     /* Disable Receive Own Frames (Half-Duplex Mode)      */
-
-/* EMAC_STAADD Masks */
-
-#define	STABUSY            0x00000001     /* Initiate Station Mgt Reg Access / STA Busy Stat    */
-#define	STAOP              0x00000002     /* Station Management Operation Code (Write/Read*)    */
-#define	STADISPRE          0x00000004     /* Disable Preamble Generation                        */
-#define	STAIE              0x00000008     /* Station Mgt. Transfer Done Interrupt Enable        */
-#define	REGAD              0x000007C0     /* STA Register Address                               */
-#define	PHYAD              0x0000F800     /* PHY Device Address                                 */
-
-#define	SET_REGAD(x) (((x)&0x1F)<<  6 )   /* Set STA Register Address                           */
-#define	SET_PHYAD(x) (((x)&0x1F)<< 11 )   /* Set PHY Device Address                             */
-
-/* EMAC_STADAT Mask */
-
-#define	STADATA            0x0000FFFF     /* Station Management Data                            */
-
-/* EMAC_FLC Masks */
-
-#define	FLCBUSY            0x00000001     /* Send Flow Ctrl Frame / Flow Ctrl Busy Status       */
-#define	FLCE               0x00000002     /* Flow Control Enable                                */
-#define	PCF                0x00000004     /* Pass Control Frames                                */
-#define	BKPRSEN            0x00000008     /* Enable Backpressure                                */
-#define	FLCPAUSE           0xFFFF0000     /* Pause Time                                         */
-
-#define	SET_FLCPAUSE(x) (((x)&0xFFFF)<< 16) /* Set Pause Time                                   */
-
-/* EMAC_WKUP_CTL Masks */
-
-#define	CAPWKFRM           0x00000001    /* Capture Wake-Up Frames                              */
-#define	MPKE               0x00000002    /* Magic Packet Enable                                 */
-#define	RWKE               0x00000004    /* Remote Wake-Up Frame Enable                         */
-#define	GUWKE              0x00000008    /* Global Unicast Wake Enable                          */
-#define	MPKS               0x00000020    /* Magic Packet Received Status                        */
-#define	RWKS               0x00000F00    /* Wake-Up Frame Received Status, Filters 3:0          */
-
-/* EMAC_WKUP_FFCMD Masks */
-
-#define	WF0_E              0x00000001    /* Enable Wake-Up Filter 0                              */
-#define	WF0_T              0x00000008    /* Wake-Up Filter 0 Addr Type (Multicast/Unicast*)      */
-#define	WF1_E              0x00000100    /* Enable Wake-Up Filter 1                              */
-#define	WF1_T              0x00000800    /* Wake-Up Filter 1 Addr Type (Multicast/Unicast*)      */
-#define	WF2_E              0x00010000    /* Enable Wake-Up Filter 2                              */
-#define	WF2_T              0x00080000    /* Wake-Up Filter 2 Addr Type (Multicast/Unicast*)      */
-#define	WF3_E              0x01000000    /* Enable Wake-Up Filter 3                              */
-#define	WF3_T              0x08000000    /* Wake-Up Filter 3 Addr Type (Multicast/Unicast*)      */
-
-/* EMAC_WKUP_FFOFF Masks */
-
-#define	WF0_OFF            0x000000FF    /* Wake-Up Filter 0 Pattern Offset                      */
-#define	WF1_OFF            0x0000FF00    /* Wake-Up Filter 1 Pattern Offset                      */
-#define	WF2_OFF            0x00FF0000    /* Wake-Up Filter 2 Pattern Offset                      */
-#define	WF3_OFF            0xFF000000    /* Wake-Up Filter 3 Pattern Offset                      */
-
-#define	SET_WF0_OFF(x) (((x)&0xFF)<<  0 ) /* Set Wake-Up Filter 0 Byte Offset                    */
-#define	SET_WF1_OFF(x) (((x)&0xFF)<<  8 ) /* Set Wake-Up Filter 1 Byte Offset                    */
-#define	SET_WF2_OFF(x) (((x)&0xFF)<< 16 ) /* Set Wake-Up Filter 2 Byte Offset                    */
-#define	SET_WF3_OFF(x) (((x)&0xFF)<< 24 ) /* Set Wake-Up Filter 3 Byte Offset                    */
-/* Set ALL Offsets */
-#define	SET_WF_OFFS(x0,x1,x2,x3) (SET_WF0_OFF((x0))|SET_WF1_OFF((x1))|SET_WF2_OFF((x2))|SET_WF3_OFF((x3)))
-
-/* EMAC_WKUP_FFCRC0 Masks */
-
-#define	WF0_CRC           0x0000FFFF    /* Wake-Up Filter 0 Pattern CRC                           */
-#define	WF1_CRC           0xFFFF0000    /* Wake-Up Filter 1 Pattern CRC                           */
-
-#define	SET_WF0_CRC(x) (((x)&0xFFFF)<<   0 ) /* Set Wake-Up Filter 0 Target CRC                   */
-#define	SET_WF1_CRC(x) (((x)&0xFFFF)<<  16 ) /* Set Wake-Up Filter 1 Target CRC                   */
-
-/* EMAC_WKUP_FFCRC1 Masks */
-
-#define	WF2_CRC           0x0000FFFF    /* Wake-Up Filter 2 Pattern CRC                           */
-#define	WF3_CRC           0xFFFF0000    /* Wake-Up Filter 3 Pattern CRC                           */
-
-#define	SET_WF2_CRC(x) (((x)&0xFFFF)<<   0 ) /* Set Wake-Up Filter 2 Target CRC                   */
-#define	SET_WF3_CRC(x) (((x)&0xFFFF)<<  16 ) /* Set Wake-Up Filter 3 Target CRC                   */
-
-/* EMAC_SYSCTL Masks */
-
-#define	PHYIE             0x00000001    /* PHY_INT Interrupt Enable                               */
-#define	RXDWA             0x00000002    /* Receive Frame DMA Word Alignment (Odd/Even*)           */
-#define	RXCKS             0x00000004    /* Enable RX Frame TCP/UDP Checksum Computation           */
-#define	TXDWA             0x00000010    /* Transmit Frame DMA Word Alignment (Odd/Even*)          */
-#define	MDCDIV            0x00003F00    /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))]            */
-
-#define	SET_MDCDIV(x) (((x)&0x3F)<< 8)   /* Set MDC Clock Divisor                                 */
-
-/* EMAC_SYSTAT Masks */
-
-#define	PHYINT            0x00000001    /* PHY_INT Interrupt Status                               */
-#define	MMCINT            0x00000002    /* MMC Counter Interrupt Status                           */
-#define	RXFSINT           0x00000004    /* RX Frame-Status Interrupt Status                       */
-#define	TXFSINT           0x00000008    /* TX Frame-Status Interrupt Status                       */
-#define	WAKEDET           0x00000010    /* Wake-Up Detected Status                                */
-#define	RXDMAERR          0x00000020    /* RX DMA Direction Error Status                          */
-#define	TXDMAERR          0x00000040    /* TX DMA Direction Error Status                          */
-#define	STMDONE           0x00000080    /* Station Mgt. Transfer Done Interrupt Status            */
-
-/* EMAC_RX_STAT, EMAC_RX_STKY, and EMAC_RX_IRQE Masks */
-
-#define	RX_FRLEN          0x000007FF    /* Frame Length In Bytes                                  */
-#define	RX_COMP           0x00001000    /* RX Frame Complete                                      */
-#define	RX_OK             0x00002000    /* RX Frame Received With No Errors                       */
-#define	RX_LONG           0x00004000    /* RX Frame Too Long Error                                */
-#define	RX_ALIGN          0x00008000    /* RX Frame Alignment Error                               */
-#define	RX_CRC            0x00010000    /* RX Frame CRC Error                                     */
-#define	RX_LEN            0x00020000    /* RX Frame Length Error                                  */
-#define	RX_FRAG           0x00040000    /* RX Frame Fragment Error                                */
-#define	RX_ADDR           0x00080000    /* RX Frame Address Filter Failed Error                   */
-#define	RX_DMAO           0x00100000    /* RX Frame DMA Overrun Error                             */
-#define	RX_PHY            0x00200000    /* RX Frame PHY Error                                     */
-#define	RX_LATE           0x00400000    /* RX Frame Late Collision Error                          */
-#define	RX_RANGE          0x00800000    /* RX Frame Length Field Out of Range Error               */
-#define	RX_MULTI          0x01000000    /* RX Multicast Frame Indicator                           */
-#define	RX_BROAD          0x02000000    /* RX Broadcast Frame Indicator                           */
-#define	RX_CTL            0x04000000    /* RX Control Frame Indicator                             */
-#define	RX_UCTL           0x08000000    /* Unsupported RX Control Frame Indicator                 */
-#define	RX_TYPE           0x10000000    /* RX Typed Frame Indicator                               */
-#define	RX_VLAN1          0x20000000    /* RX VLAN1 Frame Indicator                               */
-#define	RX_VLAN2          0x40000000    /* RX VLAN2 Frame Indicator                               */
-#define	RX_ACCEPT         0x80000000    /* RX Frame Accepted Indicator                            */
-
-/*  EMAC_TX_STAT, EMAC_TX_STKY, and EMAC_TX_IRQE Masks  */
-
-#define	TX_COMP           0x00000001    /* TX Frame Complete                                      */
-#define	TX_OK             0x00000002    /* TX Frame Sent With No Errors                           */
-#define	TX_ECOLL          0x00000004    /* TX Frame Excessive Collision Error                     */
-#define	TX_LATE           0x00000008    /* TX Frame Late Collision Error                          */
-#define	TX_DMAU           0x00000010    /* TX Frame DMA Underrun Error (STAT)                     */
-#define	TX_MACE           0x00000010    /* Internal MAC Error Detected (STKY and IRQE)            */
-#define	TX_EDEFER         0x00000020    /* TX Frame Excessive Deferral Error                      */
-#define	TX_BROAD          0x00000040    /* TX Broadcast Frame Indicator                           */
-#define	TX_MULTI          0x00000080    /* TX Multicast Frame Indicator                           */
-#define	TX_CCNT           0x00000F00    /* TX Frame Collision Count                               */
-#define	TX_DEFER          0x00001000    /* TX Frame Deferred Indicator                            */
-#define	TX_CRS            0x00002000    /* TX Frame Carrier Sense Not Asserted Error              */
-#define	TX_LOSS           0x00004000    /* TX Frame Carrier Lost During TX Error                  */
-#define	TX_RETRY          0x00008000    /* TX Frame Successful After Retry                        */
-#define	TX_FRLEN          0x07FF0000    /* TX Frame Length (Bytes)                                */
-
-/* EMAC_MMC_CTL Masks */
-#define	RSTC              0x00000001    /* Reset All Counters                                     */
-#define	CROLL             0x00000002    /* Counter Roll-Over Enable                               */
-#define	CCOR              0x00000004    /* Counter Clear-On-Read Mode Enable                      */
-#define	MMCE              0x00000008    /* Enable MMC Counter Operation                           */
-
-/* EMAC_MMC_RIRQS and EMAC_MMC_RIRQE Masks */
-#define	RX_OK_CNT         0x00000001    /* RX Frames Received With No Errors                      */
-#define	RX_FCS_CNT        0x00000002    /* RX Frames W/Frame Check Sequence Errors                */
-#define	RX_ALIGN_CNT      0x00000004    /* RX Frames With Alignment Errors                        */
-#define	RX_OCTET_CNT      0x00000008    /* RX Octets Received OK                                  */
-#define	RX_LOST_CNT       0x00000010    /* RX Frames Lost Due To Internal MAC RX Error            */
-#define	RX_UNI_CNT        0x00000020    /* Unicast RX Frames Received OK                          */
-#define	RX_MULTI_CNT      0x00000040    /* Multicast RX Frames Received OK                        */
-#define	RX_BROAD_CNT      0x00000080    /* Broadcast RX Frames Received OK                        */
-#define	RX_IRL_CNT        0x00000100    /* RX Frames With In-Range Length Errors                  */
-#define	RX_ORL_CNT        0x00000200    /* RX Frames With Out-Of-Range Length Errors              */
-#define	RX_LONG_CNT       0x00000400    /* RX Frames With Frame Too Long Errors                   */
-#define	RX_MACCTL_CNT     0x00000800    /* MAC Control RX Frames Received                         */
-#define	RX_OPCODE_CTL     0x00001000    /* Unsupported Op-Code RX Frames Received                 */
-#define	RX_PAUSE_CNT      0x00002000    /* PAUSEMAC Control RX Frames Received                    */
-#define	RX_ALLF_CNT       0x00004000    /* All RX Frames Received                                 */
-#define	RX_ALLO_CNT       0x00008000    /* All RX Octets Received                                 */
-#define	RX_TYPED_CNT      0x00010000    /* Typed RX Frames Received                               */
-#define	RX_SHORT_CNT      0x00020000    /* RX Frame Fragments (< 64 Bytes) Received               */
-#define	RX_EQ64_CNT       0x00040000    /* 64-Byte RX Frames Received                             */
-#define	RX_LT128_CNT      0x00080000    /* 65-127-Byte RX Frames Received                         */
-#define	RX_LT256_CNT      0x00100000    /* 128-255-Byte RX Frames Received                        */
-#define	RX_LT512_CNT      0x00200000    /* 256-511-Byte RX Frames Received                        */
-#define	RX_LT1024_CNT     0x00400000    /* 512-1023-Byte RX Frames Received                       */
-#define	RX_GE1024_CNT     0x00800000    /* 1024-Max-Byte RX Frames Received                       */
-
-/* EMAC_MMC_TIRQS and EMAC_MMC_TIRQE Masks  */
-
-#define	TX_OK_CNT         0x00000001    /* TX Frames Sent OK                                      */
-#define	TX_SCOLL_CNT      0x00000002    /* TX Frames With Single Collisions                       */
-#define	TX_MCOLL_CNT      0x00000004    /* TX Frames With Multiple Collisions                     */
-#define	TX_OCTET_CNT      0x00000008    /* TX Octets Sent OK                                      */
-#define	TX_DEFER_CNT      0x00000010    /* TX Frames With Deferred Transmission                   */
-#define	TX_LATE_CNT       0x00000020    /* TX Frames With Late Collisions                         */
-#define	TX_ABORTC_CNT     0x00000040    /* TX Frames Aborted Due To Excess Collisions             */
-#define	TX_LOST_CNT       0x00000080    /* TX Frames Lost Due To Internal MAC TX Error            */
-#define	TX_CRS_CNT        0x00000100    /* TX Frames With Carrier Sense Errors                    */
-#define	TX_UNI_CNT        0x00000200    /* Unicast TX Frames Sent                                 */
-#define	TX_MULTI_CNT      0x00000400    /* Multicast TX Frames Sent                               */
-#define	TX_BROAD_CNT      0x00000800    /* Broadcast TX Frames Sent                               */
-#define	TX_EXDEF_CTL      0x00001000    /* TX Frames With Excessive Deferral                      */
-#define	TX_MACCTL_CNT     0x00002000    /* MAC Control TX Frames Sent                             */
-#define	TX_ALLF_CNT       0x00004000    /* All TX Frames Sent                                     */
-#define	TX_ALLO_CNT       0x00008000    /* All TX Octets Sent                                     */
-#define	TX_EQ64_CNT       0x00010000    /* 64-Byte TX Frames Sent                                 */
-#define	TX_LT128_CNT      0x00020000    /* 65-127-Byte TX Frames Sent                             */
-#define	TX_LT256_CNT      0x00040000    /* 128-255-Byte TX Frames Sent                            */
-#define	TX_LT512_CNT      0x00080000    /* 256-511-Byte TX Frames Sent                            */
-#define	TX_LT1024_CNT     0x00100000    /* 512-1023-Byte TX Frames Sent                           */
-#define	TX_GE1024_CNT     0x00200000    /* 1024-Max-Byte TX Frames Sent                           */
-#define	TX_ABORT_CNT      0x00400000    /* TX Frames Aborted                                      */
-
-/* SDH Registers */
-
-#define SDH_PWR_CTL                    0xFFC03900 /* SDH Power Control */
-#define SDH_CLK_CTL                    0xFFC03904 /* SDH Clock Control */
-#define SDH_ARGUMENT                   0xFFC03908 /* SDH Argument */
-#define SDH_COMMAND                    0xFFC0390C /* SDH Command */
-#define SDH_RESP_CMD                   0xFFC03910 /* SDH Response Command */
-#define SDH_RESPONSE0                  0xFFC03914 /* SDH Response0 */
-#define SDH_RESPONSE1                  0xFFC03918 /* SDH Response1 */
-#define SDH_RESPONSE2                  0xFFC0391C /* SDH Response2 */
-#define SDH_RESPONSE3                  0xFFC03920 /* SDH Response3 */
-#define SDH_DATA_TIMER                 0xFFC03924 /* SDH Data Timer */
-#define SDH_DATA_LGTH                  0xFFC03928 /* SDH Data Length */
-#define SDH_DATA_CTL                   0xFFC0392C /* SDH Data Control */
-#define SDH_DATA_CNT                   0xFFC03930 /* SDH Data Counter */
-#define SDH_STATUS                     0xFFC03934 /* SDH Status */
-#define SDH_STATUS_CLR                 0xFFC03938 /* SDH Status Clear */
-#define SDH_MASK0                      0xFFC0393C /* SDH Interrupt0 Mask */
-#define SDH_MASK1                      0xFFC03940 /* SDH Interrupt1 Mask */
-#define SDH_FIFO_CNT                   0xFFC03948 /* SDH FIFO Counter */
-#define SDH_FIFO                       0xFFC03980 /* SDH Data FIFO */
-#define SDH_E_STATUS                   0xFFC039C0 /* SDH Exception Status */
-#define SDH_E_MASK                     0xFFC039C4 /* SDH Exception Mask */
-#define SDH_CFG                        0xFFC039C8 /* SDH Configuration */
-#define SDH_RD_WAIT_EN                 0xFFC039CC /* SDH Read Wait Enable */
-#define SDH_PID0                       0xFFC039D0 /* SDH Peripheral Identification0 */
-#define SDH_PID1                       0xFFC039D4 /* SDH Peripheral Identification1 */
-#define SDH_PID2                       0xFFC039D8 /* SDH Peripheral Identification2 */
-#define SDH_PID3                       0xFFC039DC /* SDH Peripheral Identification3 */
-#define SDH_PID4                       0xFFC039E0 /* SDH Peripheral Identification4 */
-#define SDH_PID5                       0xFFC039E4 /* SDH Peripheral Identification5 */
-#define SDH_PID6                       0xFFC039E8 /* SDH Peripheral Identification6 */
-#define SDH_PID7                       0xFFC039EC /* SDH Peripheral Identification7 */
-
-/* Removable Storage Interface Registers */
-
-#define RSI_PWR_CONTROL                0xFFC03800 /* RSI Power Control Register */
-#define RSI_CLK_CONTROL                0xFFC03804 /* RSI Clock Control Register */
-#define RSI_ARGUMENT                   0xFFC03808 /* RSI Argument Register */
-#define RSI_COMMAND                    0xFFC0380C /* RSI Command Register */
-#define RSI_RESP_CMD                   0xFFC03810 /* RSI Response Command Register */
-#define RSI_RESPONSE0                  0xFFC03814 /* RSI Response Register */
-#define RSI_RESPONSE1                  0xFFC03818 /* RSI Response Register */
-#define RSI_RESPONSE2                  0xFFC0381C /* RSI Response Register */
-#define RSI_RESPONSE3                  0xFFC03820 /* RSI Response Register */
-#define RSI_DATA_TIMER                 0xFFC03824 /* RSI Data Timer Register */
-#define RSI_DATA_LGTH                  0xFFC03828 /* RSI Data Length Register */
-#define RSI_DATA_CONTROL               0xFFC0382C /* RSI Data Control Register */
-#define RSI_DATA_CNT                   0xFFC03830 /* RSI Data Counter Register */
-#define RSI_STATUS                     0xFFC03834 /* RSI Status Register */
-#define RSI_STATUSCL                   0xFFC03838 /* RSI Status Clear Register */
-#define RSI_MASK0                      0xFFC0383C /* RSI Interrupt 0 Mask Register */
-#define RSI_MASK1                      0xFFC03840 /* RSI Interrupt 1 Mask Register */
-#define RSI_FIFO_CNT                   0xFFC03848 /* RSI FIFO Counter Register */
-#define RSI_CEATA_CONTROL              0xFFC0384C /* RSI CEATA Register */
-#define RSI_FIFO                       0xFFC03880 /* RSI Data FIFO Register */
-#define RSI_ESTAT                      0xFFC038C0 /* RSI Exception Status Register */
-#define RSI_EMASK                      0xFFC038C4 /* RSI Exception Mask Register */
-#define RSI_CONFIG                     0xFFC038C8 /* RSI Configuration Register */
-#define RSI_RD_WAIT_EN                 0xFFC038CC /* RSI Read Wait Enable Register */
-#define RSI_PID0                       0xFFC03FE0 /* RSI Peripheral ID Register 0 */
-#define RSI_PID1                       0xFFC03FE4 /* RSI Peripheral ID Register 1 */
-#define RSI_PID2                       0xFFC03FE8 /* RSI Peripheral ID Register 2 */
-#define RSI_PID3                       0xFFC03FEC /* RSI Peripheral ID Register 3 */
-#define RSI_PID4                       0xFFC03FF0 /* RSI Peripheral ID Register 4 */
-#define RSI_PID5                       0xFFC03FF4 /* RSI Peripheral ID Register 5 */
-#define RSI_PID6                       0xFFC03FF8 /* RSI Peripheral ID Register 6 */
-#define RSI_PID7                       0xFFC03FFC /* RSI Peripheral ID Register 7 */
+/* BF518 is BF516 + IEEE-1588 */
+#include "defBF516.h"
 
 /* PTP TSYNC Registers */
 
@@ -489,141 +36,6 @@
 #define EMAC_PTP_PPS_STARTHI           0xFFC030F4 /* PPS Start Time High */
 #define EMAC_PTP_PPS_PERIOD            0xFFC030F8 /* PPS Count Register */
 
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for SDH_COMMAND */
-
-#define                   CMD_IDX  0x3f       /* Command Index */
-#define                   CMD_RSP  0x40       /* Response */
-#define                 CMD_L_RSP  0x80       /* Long Response */
-#define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                CMD_PEND_E  0x200      /* Command Pending */
-#define                     CMD_E  0x400      /* Command Enable */
-
-/* Bit masks for SDH_PWR_CTL */
-
-#define                    PWR_ON  0x3        /* Power On */
-#if 0
-#define                       TBD  0x3c       /* TBD */
-#endif
-#define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                   ROD_CTL  0x80       /* Rod Control */
-
-/* Bit masks for SDH_CLK_CTL */
-
-#define                    CLKDIV  0xff       /* MC_CLK Divisor */
-#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-
-/* Bit masks for SDH_RESP_CMD */
-
-#define                  RESP_CMD  0x3f       /* Response Command */
-
-/* Bit masks for SDH_DATA_CTL */
-
-#define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
-
-/* Bit masks for SDH_STATUS */
-
-#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
-#define               DAT_TIME_OUT  0x8        /* Data Time Out */
-#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define              CMD_RESP_END  0x40       /* CMD Response End */
-#define                  CMD_SENT  0x80       /* CMD Sent */
-#define                   DAT_END  0x100      /* Data End */
-#define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define               DAT_BLK_END  0x400      /* Data Block End */
-#define                   CMD_ACT  0x800      /* CMD Active */
-#define                    TX_ACT  0x1000     /* Transmit Active */
-#define                    RX_ACT  0x2000     /* Receive Active */
-#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-
-/* Bit masks for SDH_STATUS_CLR */
-
-#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define              DAT_END_STAT  0x100      /* Data End Status */
-#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-
-/* Bit masks for SDH_MASK0 */
-
-#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define              DAT_END_MASK  0x100      /* Data End Mask */
-#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-
-/* Bit masks for SDH_FIFO_CNT */
-
-#define                FIFO_COUNT  0x7fff     /* FIFO Count */
-
-/* Bit masks for SDH_E_STATUS */
-
-#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define               SD_CARD_DET  0x10       /* SD Card Detect */
-
-/* Bit masks for SDH_E_MASK */
-
-#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                   SCD_MSK  0x40       /* Mask Card Detect */
-
-/* Bit masks for SDH_CFG */
-
-#define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                       MWE  0x8        /* Moving Window Enable */
-#define                    SD_RST  0x10       /* SDMMC Reset */
-#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-
-/* Bit masks for SDH_RD_WAIT_EN */
-
-#define                       RWR  0x1        /* Read Wait Request */
-
 /* Bit masks for EMAC_PTP_CTL */
 
 #define                    PTP_EN  0x1        /* Enable the PTP_TSYNC module */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
index f9fd2b2..9241205 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
@@ -585,58 +585,6 @@
 **				modifier UNLESS the lower order bits are saved and ORed back in when
 **				the macro is used.
 *************************************************************************************/
-/*
-** ********************* PLL AND RESET MASKS ****************************************/
-/* PLL_CTL Masks																	*/
-#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2					*/
-#define PLL_OFF			0x0002	/* PLL Not Powered									*/
-#define STOPCK			0x0008	/* Core Clock Off									*/
-#define PDWN			0x0020	/* Enter Deep Sleep Mode							*/
-#define	IN_DELAY		0x0040	/* Add 200ps Delay To EBIU Input Latches			*/
-#define	OUT_DELAY		0x0080	/* Add 200ps Delay To EBIU Output Signals			*/
-#define BYPASS			0x0100	/* Bypass the PLL									*/
-#define	MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors			*/
-/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
-#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
-
-/* PLL_DIV Masks														*/
-#define SSEL			0x000F	/* System Select						*/
-#define	CSEL			0x0030	/* Core Select							*/
-#define CSEL_DIV1		0x0000	/* 		CCLK = VCO / 1					*/
-#define CSEL_DIV2		0x0010	/* 		CCLK = VCO / 2					*/
-#define	CSEL_DIV4		0x0020	/* 		CCLK = VCO / 4					*/
-#define	CSEL_DIV8		0x0030	/* 		CCLK = VCO / 8					*/
-/* PLL_DIV Macros														*/
-#define SET_SSEL(x)		((x)&0xF)		/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
-
-/* VR_CTL Masks	*/
-#define	FREQ			0x3000	/* Switching Oscillator Frequency For Regulator	*/
-#define	HIBERNATE		0x0000	/* 		Powerdown/Bypass On-Board Regulation	*/
-
-#define	VLEV			0x00F0	/* Internal Voltage Level					*/
-#define	VLEV_085 		0x0060	/* 		VLEV = 0.85 V (-5% - +10% Accuracy)	*/
-#define	VLEV_090		0x0070	/* 		VLEV = 0.90 V (-5% - +10% Accuracy)	*/
-#define	VLEV_095		0x0080	/* 		VLEV = 0.95 V (-5% - +10% Accuracy)	*/
-#define	VLEV_100		0x0090	/* 		VLEV = 1.00 V (-5% - +10% Accuracy)	*/
-#define	VLEV_105		0x00A0	/* 		VLEV = 1.05 V (-5% - +10% Accuracy)	*/
-#define	VLEV_110		0x00B0	/* 		VLEV = 1.10 V (-5% - +10% Accuracy)	*/
-#define	VLEV_115		0x00C0	/* 		VLEV = 1.15 V (-5% - +10% Accuracy)	*/
-#define	VLEV_120		0x00D0	/* 		VLEV = 1.20 V (-5% - +10% Accuracy)	*/
-#define	VLEV_125		0x00E0	/* 		VLEV = 1.25 V (-5% - +10% Accuracy)	*/
-#define	VLEV_130		0x00F0	/* 		VLEV = 1.30 V (-5% - +10% Accuracy)	*/
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate	*/
-#define	USBWE			0x0200	/* Enable USB Wakeup From Hibernate			*/
-#define	PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate			*/
-#define	CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
-#define	PHYCLKOE		CLKBUFOE	/* Alternative legacy name for the above */
-#define	SCKELOW		0x8000	/* Enable Drive CKE Low During Reset		*/
-
-/* PLL_STAT Masks																	*/
-#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled	*/
-#define	FULL_ON				0x0002	/* Processor In Full On Mode					*/
-#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled	*/
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached					*/
 
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
@@ -756,66 +704,6 @@
 #define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
 
 
-/* ********* WATCHDOG TIMER MASKS ******************** */
-
-/* Watchdog Timer WDOG_CTL Register Masks */
-
-#define WDEV(x) (((x)<<1) & 0x0006) /* event generated on roll over */
-#define WDEV_RESET 0x0000 /* generate reset event on roll over */
-#define WDEV_NMI 0x0002 /* generate NMI event on roll over */
-#define WDEV_GPI 0x0004 /* generate GP IRQ on roll over */
-#define WDEV_NONE 0x0006 /* no event on roll over */
-#define WDEN 0x0FF0 /* enable watchdog */
-#define WDDIS 0x0AD0 /* disable watchdog */
-#define WDRO 0x8000 /* watchdog rolled over latch */
-
-/* depreciated WDOG_CTL Register Masks for legacy code */
-
-
-#define ICTL WDEV
-#define ENABLE_RESET WDEV_RESET
-#define WDOG_RESET WDEV_RESET
-#define ENABLE_NMI WDEV_NMI
-#define WDOG_NMI WDEV_NMI
-#define ENABLE_GPI WDEV_GPI
-#define WDOG_GPI WDEV_GPI
-#define DISABLE_EVT WDEV_NONE
-#define WDOG_NONE WDEV_NONE
-
-#define TMR_EN WDEN
-#define TMR_DIS WDDIS
-#define TRO WDRO
-#define ICTL_P0 0x01
- #define ICTL_P1 0x02
-#define TRO_P 0x0F
-
-
-
-/* ***************  REAL TIME CLOCK MASKS  **************************/
-/* RTC_STAT and RTC_ALARM Masks										*/
-#define	RTC_SEC				0x0000003F	/* Real-Time Clock Seconds	*/
-#define	RTC_MIN				0x00000FC0	/* Real-Time Clock Minutes	*/
-#define	RTC_HR				0x0001F000	/* Real-Time Clock Hours	*/
-#define	RTC_DAY				0xFFFE0000	/* Real-Time Clock Days		*/
-
-/* RTC_ALARM Macro			z=day		y=hr	x=min	w=sec		*/
-#define SET_ALARM(z,y,x,w)	((((z)&0x7FFF)<<0x11)|(((y)&0x1F)<<0xC)|(((x)&0x3F)<<0x6)|((w)&0x3F))
-
-/* RTC_ICTL and RTC_ISTAT Masks																		*/
-#define	STOPWATCH			0x0001		/* Stopwatch Interrupt Enable								*/
-#define	ALARM				0x0002		/* Alarm Interrupt Enable									*/
-#define	SECOND				0x0004		/* Seconds (1 Hz) Interrupt Enable							*/
-#define	MINUTE				0x0008		/* Minutes Interrupt Enable									*/
-#define	HOUR				0x0010		/* Hours Interrupt Enable									*/
-#define	DAY					0x0020		/* 24 Hours (Days) Interrupt Enable							*/
-#define	DAY_ALARM			0x0040		/* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable	*/
-#define	WRITE_PENDING		0x4000		/* Write Pending Status										*/
-#define	WRITE_COMPLETE		0x8000		/* Write Complete Interrupt Enable							*/
-
-/* RTC_FAST / RTC_PREN Mask												*/
-#define PREN				0x0001	/* Enable Prescaler, RTC Runs @1 Hz	*/
-
-
 /* ************** UART CONTROLLER MASKS *************************/
 /* UARTx_LCR Masks												*/
 #define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select */
@@ -1372,33 +1260,6 @@
 
 
 /* **************************  DMA CONTROLLER MASKS  ********************************/
-/* DMAx_CONFIG, MDMA_yy_CONFIG Masks												*/
-#define DMAEN			0x0001		/* DMA Channel Enable							*/
-#define WNR				0x0002		/* Channel Direction (W/R*)						*/
-#define WDSIZE_8		0x0000		/* Transfer Word Size = 8						*/
-#define WDSIZE_16		0x0004		/* Transfer Word Size = 16						*/
-#define WDSIZE_32		0x0008		/* Transfer Word Size = 32						*/
-#define DMA2D			0x0010		/* DMA Mode (2D/1D*)							*/
-#define RESTART			0x0020		/* DMA Buffer Clear								*/
-#define DI_SEL			0x0040		/* Data Interrupt Timing Select					*/
-#define DI_EN			0x0080		/* Data Interrupt Enable						*/
-#define NDSIZE_0		0x0000		/* Next Descriptor Size = 0 (Stop/Autobuffer)	*/
-#define NDSIZE_1		0x0100		/* Next Descriptor Size = 1						*/
-#define NDSIZE_2		0x0200		/* Next Descriptor Size = 2						*/
-#define NDSIZE_3		0x0300		/* Next Descriptor Size = 3						*/
-#define NDSIZE_4		0x0400		/* Next Descriptor Size = 4						*/
-#define NDSIZE_5		0x0500		/* Next Descriptor Size = 5						*/
-#define NDSIZE_6		0x0600		/* Next Descriptor Size = 6						*/
-#define NDSIZE_7		0x0700		/* Next Descriptor Size = 7						*/
-#define NDSIZE_8		0x0800		/* Next Descriptor Size = 8						*/
-#define NDSIZE_9		0x0900		/* Next Descriptor Size = 9						*/
-#define NDSIZE	        	0x0900	/* Next Descriptor Size */
-#define DMAFLOW	        	0x7000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000		/* Stop Mode									*/
-#define DMAFLOW_AUTO		0x1000		/* Autobuffer Mode								*/
-#define DMAFLOW_ARRAY		0x4000		/* Descriptor Array Mode						*/
-#define DMAFLOW_SMALL		0x6000		/* Small Model Descriptor List Mode				*/
-#define DMAFLOW_LARGE		0x7000		/* Large Model Descriptor List Mode				*/
 
 /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
 #define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
@@ -1416,13 +1277,6 @@
 #define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
 #define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
 
-/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks						*/
-#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status	*/
-#define DMA_ERR			0x0002	/* DMA Error Interrupt Status		*/
-#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator	*/
-#define DMA_RUN			0x0008	/* DMA Channel Running Indicator	*/
-
-
 /*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
 /*  PPI_CONTROL Masks													*/
 #define PORT_EN			0x0001		/* PPI Port Enable					*/
@@ -1830,46 +1684,6 @@
 #define BNDMODE_CAPT     0x2000  /* boundary capture mode */
 #define BNDMODE_AEXT     0x3000  /* boundary auto-extend mode */
 
-/* Bit masks for OTP_CONTROL */
-
-#define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
-#define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
-#define                     nFIEN  0x0
-#define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
-#define                 nFTESTDEC  0x0
-#define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
-#define                  nFWRTEST  0x0
-#define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
-#define                    nFRDEN  0x0
-#define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
-#define                    nFWREN  0x0
-
-/* Bit masks for OTP_BEN */
-
-#define                      FBEN  0xffff     /* OTP/Fuse Byte Enable */
-
-/* Bit masks for OTP_STATUS */
-
-#define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
-#define                    nFCOMP  0x0
-#define                    FERROR  0x2        /* OTP/Fuse Access Error */
-#define                   nFERROR  0x0
-#define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
-#define                 nMMRGLOAD  0x0
-#define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
-#define                 nMMRGLOCK  0x0
-#define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
-#define                   nFPGMEN  0x0
-
-/* Bit masks for OTP_TIMING */
-
-#define                   USECDIV  0xff       /* Micro Second Divider */
-#define                   READACC  0x7f00     /* Read Access Time */
-#define                   CPUMPRL  0x38000    /* Charge Pump Release Time */
-#define                   CPUMPSU  0xc0000    /* Charge Pump Setup Time */
-#define                   CPUMPHD  0xf00000   /* Charge Pump Hold Time */
-#define                   PGMTIME  0xff000000 /* Program Time */
-
 /* Bit masks for SECURE_SYSSWT */
 
 #define                   EMUDABL  0x1        /* Emulation Disable. */
diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig
index 848ac6f..1f8cbe9 100644
--- a/arch/blackfin/mach-bf527/Kconfig
+++ b/arch/blackfin/mach-bf527/Kconfig
@@ -1,3 +1,7 @@
+config BF52x
+	def_bool y
+	depends on (BF522 || BF523 || BF524 || BF525 || BF526 || BF527)
+
 if (BF52x)
 
 source "arch/blackfin/mach-bf527/boards/Kconfig"
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index f1996b1..7ab0800 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -15,9 +15,6 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/etherdevice.h>
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-#include <linux/usb/isp1362.h>
-#endif
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -65,7 +62,7 @@
 };
 
 static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
+	.name           = "isp1760",
 	.id             = 0,
 	.dev = {
 		.platform_data = &isp1760_priv,
@@ -317,45 +314,6 @@
 };
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-static struct resource isp1362_hcd_resources[] = {
-	{
-		.start = 0x20360000,
-		.end = 0x20360000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20360004,
-		.end = 0x20360004,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct isp1362_platform_data isp1362_priv = {
-	.sel15Kres = 1,
-	.clknotstop = 0,
-	.oc_enable = 0,
-	.int_act_high = 0,
-	.int_edge_triggered = 0,
-	.remote_wakeup_connected = 0,
-	.no_power_switching = 1,
-	.power_switching_mode = 0,
-};
-
-static struct platform_device isp1362_hcd_device = {
-	.name = "isp1362-hcd",
-	.id = 0,
-	.dev = {
-		.platform_data = &isp1362_priv,
-	},
-	.num_resources = ARRAY_SIZE(isp1362_hcd_resources),
-	.resource = isp1362_hcd_resources,
-};
-#endif
-
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
@@ -841,10 +799,6 @@
 	&sl811_hcd_device,
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-	&isp1362_hcd_device,
-#endif
-
 #if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
 	&bfin_isp1760_device,
 #endif
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index f09665f..5294fdd 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -13,9 +13,6 @@
 #include <linux/mtd/physmap.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-#include <linux/usb/isp1362.h>
-#endif
 #include <linux/i2c.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -63,7 +60,7 @@
 };
 
 static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
+	.name           = "isp1760",
 	.id             = 0,
 	.dev = {
 		.platform_data = &isp1760_priv,
@@ -373,45 +370,6 @@
 };
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-static struct resource isp1362_hcd_resources[] = {
-	{
-		.start = 0x20360000,
-		.end = 0x20360000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20360004,
-		.end = 0x20360004,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct isp1362_platform_data isp1362_priv = {
-	.sel15Kres = 1,
-	.clknotstop = 0,
-	.oc_enable = 0,
-	.int_act_high = 0,
-	.int_edge_triggered = 0,
-	.remote_wakeup_connected = 0,
-	.no_power_switching = 1,
-	.power_switching_mode = 0,
-};
-
-static struct platform_device isp1362_hcd_device = {
-	.name = "isp1362-hcd",
-	.id = 0,
-	.dev = {
-		.platform_data = &isp1362_priv,
-	},
-	.num_resources = ARRAY_SIZE(isp1362_hcd_resources),
-	.resource = isp1362_hcd_resources,
-};
-#endif
-
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
@@ -688,12 +646,6 @@
 };
 #endif  /* spi master and devices */
 
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-static struct platform_device bfin_fb_device = {
-	.name = "bf537-lq035",
-};
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 #ifdef CONFIG_SERIAL_BFIN_UART0
@@ -850,7 +802,7 @@
 };
 #endif
 
-#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
 #include <linux/input.h>
 #include <asm/bfin_rotary.h>
 
@@ -924,10 +876,6 @@
 	&sl811_hcd_device,
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-	&isp1362_hcd_device,
-#endif
-
 #if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
 	&bfin_isp1760_device,
 #endif
@@ -957,10 +905,6 @@
 	&bfin_spi0_device,
 #endif
 
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-	&bfin_fb_device,
-#endif
-
 #if defined(CONFIG_FB_BFIN_T350MCQB) || defined(CONFIG_FB_BFIN_T350MCQB_MODULE)
 	&bf52x_t350mcqb_device,
 #endif
@@ -991,7 +935,7 @@
 	&bfin_device_gpiokeys,
 #endif
 
-#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
 	&bfin_rotary_device,
 #endif
 
diff --git a/arch/blackfin/mach-bf527/include/mach/blackfin.h b/arch/blackfin/mach-bf527/include/mach/blackfin.h
index e7d6034..f714c5d 100644
--- a/arch/blackfin/mach-bf527/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf527/include/mach/blackfin.h
@@ -46,10 +46,4 @@
 #define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
 #define OFFSET_GCTL             0x24	/* Global Control Register              */
 
-/* PLL_DIV Masks													*/
-#define CCLK_DIV1 CSEL_DIV1	/*          CCLK = VCO / 1                                  */
-#define CCLK_DIV2 CSEL_DIV2	/*          CCLK = VCO / 2                                  */
-#define CCLK_DIV4 CSEL_DIV4	/*          CCLK = VCO / 4                                  */
-#define CCLK_DIV8 CSEL_DIV8	/*          CCLK = VCO / 8                                  */
-
 #endif
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF525.h b/arch/blackfin/mach-bf527/include/mach/cdefBF525.h
index dc3119e9..d7e2751 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF525.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF525.h
@@ -10,15 +10,8 @@
 /* include all Core registers and bit definitions */
 #include "defBF525.h"
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF525 */
-
-/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "cdefBF52x_base.h"
-
-/* The following are the #defines needed by ADSP-BF525 that are not in the common header */
+/* BF525 is BF522 + USB */
+#include "cdefBF522.h"
 
 /* USB Control Registers */
 
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF527.h b/arch/blackfin/mach-bf527/include/mach/cdefBF527.h
index d6579449..c7ba544 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF527.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF527.h
@@ -10,15 +10,8 @@
 /* include all Core registers and bit definitions */
 #include "defBF527.h"
 
-/* include core specific register pointer definitions */
-#include <asm/cdef_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */
-
-/* include cdefBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "cdefBF52x_base.h"
-
-/* The following are the #defines needed by ADSP-BF527 that are not in the common header */
+/* BF527 is BF525 + EMAC */
+#include "cdefBF525.h"
 
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
 
@@ -185,417 +178,4 @@
 #define bfin_read_EMAC_TXC_ABORT()		bfin_read32(EMAC_TXC_ABORT)
 #define bfin_write_EMAC_TXC_ABORT(val)		bfin_write32(EMAC_TXC_ABORT, val)
 
-/* USB Control Registers */
-
-#define bfin_read_USB_FADDR()			bfin_read16(USB_FADDR)
-#define bfin_write_USB_FADDR(val)		bfin_write16(USB_FADDR, val)
-#define bfin_read_USB_POWER()			bfin_read16(USB_POWER)
-#define bfin_write_USB_POWER(val)		bfin_write16(USB_POWER, val)
-#define bfin_read_USB_INTRTX()			bfin_read16(USB_INTRTX)
-#define bfin_write_USB_INTRTX(val)		bfin_write16(USB_INTRTX, val)
-#define bfin_read_USB_INTRRX()			bfin_read16(USB_INTRRX)
-#define bfin_write_USB_INTRRX(val)		bfin_write16(USB_INTRRX, val)
-#define bfin_read_USB_INTRTXE()			bfin_read16(USB_INTRTXE)
-#define bfin_write_USB_INTRTXE(val)		bfin_write16(USB_INTRTXE, val)
-#define bfin_read_USB_INTRRXE()			bfin_read16(USB_INTRRXE)
-#define bfin_write_USB_INTRRXE(val)		bfin_write16(USB_INTRRXE, val)
-#define bfin_read_USB_INTRUSB()			bfin_read16(USB_INTRUSB)
-#define bfin_write_USB_INTRUSB(val)		bfin_write16(USB_INTRUSB, val)
-#define bfin_read_USB_INTRUSBE()		bfin_read16(USB_INTRUSBE)
-#define bfin_write_USB_INTRUSBE(val)		bfin_write16(USB_INTRUSBE, val)
-#define bfin_read_USB_FRAME()			bfin_read16(USB_FRAME)
-#define bfin_write_USB_FRAME(val)		bfin_write16(USB_FRAME, val)
-#define bfin_read_USB_INDEX()			bfin_read16(USB_INDEX)
-#define bfin_write_USB_INDEX(val)		bfin_write16(USB_INDEX, val)
-#define bfin_read_USB_TESTMODE()		bfin_read16(USB_TESTMODE)
-#define bfin_write_USB_TESTMODE(val)		bfin_write16(USB_TESTMODE, val)
-#define bfin_read_USB_GLOBINTR()		bfin_read16(USB_GLOBINTR)
-#define bfin_write_USB_GLOBINTR(val)		bfin_write16(USB_GLOBINTR, val)
-#define bfin_read_USB_GLOBAL_CTL()		bfin_read16(USB_GLOBAL_CTL)
-#define bfin_write_USB_GLOBAL_CTL(val)		bfin_write16(USB_GLOBAL_CTL, val)
-
-/* USB Packet Control Registers */
-
-#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
-#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
-#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
-#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
-#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
-#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
-#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
-#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
-#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
-#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
-#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
-#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
-#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
-#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
-#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
-#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
-#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
-#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
-#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
-#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
-#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
-#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
-#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
-#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
-#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
-#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
-
-/* USB Endpoint FIFO Registers */
-
-#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
-#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
-#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
-#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
-#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
-#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
-#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
-#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
-#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
-#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
-#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
-#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
-#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
-#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
-#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
-#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
-
-/* USB OTG Control Registers */
-
-#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
-#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
-#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
-#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
-#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
-#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
-
-/* USB Phy Control Registers */
-
-#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
-#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
-#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
-#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
-#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
-#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
-#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
-#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
-#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
-#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
-#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
-#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
-
-#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
-#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
-
-#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
-#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
-#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
-#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
-
-/* USB Endpoint 0 Control Registers */
-
-#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
-#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
-#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
-#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
-#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
-#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
-#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
-#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
-#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
-#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
-#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
-#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
-#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
-#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
-#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
-#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
-#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
-#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
-
-/* USB Endpoint 1 Control Registers */
-
-#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
-#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
-#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
-#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
-#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
-#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
-#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
-#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
-#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
-#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
-#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
-#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
-#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
-#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
-#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
-#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
-#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
-#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
-
-/* USB Endpoint 2 Control Registers */
-
-#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
-#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
-#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
-#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
-#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
-#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
-#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
-#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
-#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
-#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
-#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
-#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
-#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
-#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
-#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
-#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
-#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
-#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
-
-/* USB Endpoint 3 Control Registers */
-
-#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
-#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
-#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
-#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
-#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
-#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
-#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
-#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
-#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
-#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
-#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
-#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
-#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
-#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
-#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
-#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
-#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
-#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
-
-/* USB Endpoint 4 Control Registers */
-
-#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
-#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
-#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
-#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
-#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
-#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
-#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
-#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
-#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
-#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
-#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
-#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
-#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
-#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
-#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
-#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
-#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
-#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
-
-/* USB Endpoint 5 Control Registers */
-
-#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
-#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
-#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
-#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
-#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
-#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
-#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
-#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
-#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
-#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
-#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
-#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
-#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
-#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
-#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
-#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
-#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
-#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
-
-/* USB Endpoint 6 Control Registers */
-
-#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
-#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
-#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
-#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
-#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
-#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
-#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
-#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
-#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
-#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
-#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
-#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
-#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
-#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
-#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
-#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
-#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
-#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
-
-/* USB Endpoint 7 Control Registers */
-
-#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
-#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
-#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
-#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
-#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
-#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
-#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
-#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
-#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
-#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
-#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
-#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
-#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
-#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
-#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
-#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
-#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
-#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
-
-#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
-#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
-
-/* USB Channel 0 Config Registers */
-
-#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
-#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
-#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
-#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
-#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
-#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
-#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
-#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
-#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
-#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
-
-/* USB Channel 1 Config Registers */
-
-#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
-#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
-#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
-#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
-#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
-#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
-#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
-#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
-#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
-#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
-
-/* USB Channel 2 Config Registers */
-
-#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
-#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
-#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
-#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
-#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
-#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
-#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
-#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
-#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
-#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
-
-/* USB Channel 3 Config Registers */
-
-#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
-#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
-#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
-#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
-#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
-#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
-#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
-#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
-#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
-#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
-
-/* USB Channel 4 Config Registers */
-
-#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
-#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
-#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
-#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
-#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
-#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
-#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
-#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
-#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
-#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
-
-/* USB Channel 5 Config Registers */
-
-#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
-#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
-#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
-#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
-#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
-#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
-#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
-#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
-#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
-#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
-
-/* USB Channel 6 Config Registers */
-
-#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
-#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
-#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
-#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
-#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
-#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
-#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
-#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
-#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
-#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
-
-/* USB Channel 7 Config Registers */
-
-#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
-#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
-#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
-#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
-#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
-#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
-#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
-#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
-#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
-#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
-
 #endif /* _CDEF_BF527_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
index 7014dde..12f2ad4 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
@@ -844,6 +844,7 @@
 #define bfin_write_PPI_CONTROL(val)		bfin_write16(PPI_CONTROL, val)
 #define bfin_read_PPI_STATUS()			bfin_read16(PPI_STATUS)
 #define bfin_write_PPI_STATUS(val)		bfin_write16(PPI_STATUS, val)
+#define bfin_clear_PPI_STATUS()			bfin_write_PPI_STATUS(0xFFFF)
 #define bfin_read_PPI_DELAY()			bfin_read16(PPI_DELAY)
 #define bfin_write_PPI_DELAY(val)		bfin_write16(PPI_DELAY, val)
 #define bfin_read_PPI_COUNT()			bfin_read16(PPI_COUNT)
@@ -1062,17 +1063,6 @@
 #define bfin_read_CNT_MIN()			bfin_read32(CNT_MIN)
 #define bfin_write_CNT_MIN(val)			bfin_write32(CNT_MIN, val)
 
-/* OTP/FUSE Registers */
-
-#define bfin_read_OTP_CONTROL()			bfin_read16(OTP_CONTROL)
-#define bfin_write_OTP_CONTROL(val)		bfin_write16(OTP_CONTROL, val)
-#define bfin_read_OTP_BEN()			bfin_read16(OTP_BEN)
-#define bfin_write_OTP_BEN(val)			bfin_write16(OTP_BEN, val)
-#define bfin_read_OTP_STATUS()			bfin_read16(OTP_STATUS)
-#define bfin_write_OTP_STATUS(val)		bfin_write16(OTP_STATUS, val)
-#define bfin_read_OTP_TIMING()			bfin_read32(OTP_TIMING)
-#define bfin_write_OTP_TIMING(val)		bfin_write32(OTP_TIMING, val)
-
 /* Security Registers */
 
 #define bfin_read_SECURE_SYSSWT()		bfin_read32(SECURE_SYSSWT)
@@ -1082,17 +1072,6 @@
 #define bfin_read_SECURE_STATUS()		bfin_read16(SECURE_STATUS)
 #define bfin_write_SECURE_STATUS(val)		bfin_write16(SECURE_STATUS, val)
 
-/* OTP Read/Write Data Buffer Registers */
-
-#define bfin_read_OTP_DATA0()			bfin_read32(OTP_DATA0)
-#define bfin_write_OTP_DATA0(val)		bfin_write32(OTP_DATA0, val)
-#define bfin_read_OTP_DATA1()			bfin_read32(OTP_DATA1)
-#define bfin_write_OTP_DATA1(val)		bfin_write32(OTP_DATA1, val)
-#define bfin_read_OTP_DATA2()			bfin_read32(OTP_DATA2)
-#define bfin_write_OTP_DATA2(val)		bfin_write32(OTP_DATA2, val)
-#define bfin_read_OTP_DATA3()			bfin_read32(OTP_DATA3)
-#define bfin_write_OTP_DATA3(val)		bfin_write32(OTP_DATA3, val)
-
 /* NFC Registers */
 
 #define bfin_read_NFC_CTL()			bfin_read16(NFC_CTL)
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF525.h b/arch/blackfin/mach-bf527/include/mach/defBF525.h
index 82abefc..c136f70 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF525.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF525.h
@@ -7,15 +7,8 @@
 #ifndef _DEF_BF525_H
 #define _DEF_BF525_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
-
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF525 */
-
-/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "defBF52x_base.h"
-
-/* The following are the #defines needed by ADSP-BF525 that are not in the common header */
+/* BF525 is BF522 + USB */
+#include "defBF522.h"
 
 /* USB Control Registers */
 
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF527.h b/arch/blackfin/mach-bf527/include/mach/defBF527.h
index 570a125..4dd58fb 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF527.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF527.h
@@ -7,15 +7,9 @@
 #ifndef _DEF_BF527_H
 #define _DEF_BF527_H
 
-/* Include all Core registers and bit definitions */
-#include <asm/def_LPBlackfin.h>
+/* BF527 is BF525 + EMAC */
+#include "defBF525.h"
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */
-
-/* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */
-#include "defBF52x_base.h"
-
-/* The following are the #defines needed by ADSP-BF527 that are not in the common header */
 /* 10/100 Ethernet Controller	(0xFFC03000 - 0xFFC031FF) */
 
 #define EMAC_OPMODE             0xFFC03000       /* Operating Mode Register                              */
@@ -394,673 +388,4 @@
 #define	TX_GE1024_CNT     0x00200000    /* 1024-Max-Byte TX Frames Sent                           */
 #define	TX_ABORT_CNT      0x00400000    /* TX Frames Aborted                                      */
 
-/* USB Control Registers */
-
-#define                        USB_FADDR  0xffc03800   /* Function address register */
-#define                        USB_POWER  0xffc03804   /* Power management register */
-#define                       USB_INTRTX  0xffc03808   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
-#define                       USB_INTRRX  0xffc0380c   /* Interrupt register for Rx endpoints 1 to 7 */
-#define                      USB_INTRTXE  0xffc03810   /* Interrupt enable register for IntrTx */
-#define                      USB_INTRRXE  0xffc03814   /* Interrupt enable register for IntrRx */
-#define                      USB_INTRUSB  0xffc03818   /* Interrupt register for common USB interrupts */
-#define                     USB_INTRUSBE  0xffc0381c   /* Interrupt enable register for IntrUSB */
-#define                        USB_FRAME  0xffc03820   /* USB frame number */
-#define                        USB_INDEX  0xffc03824   /* Index register for selecting the indexed endpoint registers */
-#define                     USB_TESTMODE  0xffc03828   /* Enabled USB 20 test modes */
-#define                     USB_GLOBINTR  0xffc0382c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
-#define                   USB_GLOBAL_CTL  0xffc03830   /* Global Clock Control for the core */
-
-/* USB Packet Control Registers */
-
-#define                USB_TX_MAX_PACKET  0xffc03840   /* Maximum packet size for Host Tx endpoint */
-#define                         USB_CSR0  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                        USB_TXCSR  0xffc03844   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                USB_RX_MAX_PACKET  0xffc03848   /* Maximum packet size for Host Rx endpoint */
-#define                        USB_RXCSR  0xffc0384c   /* Control Status register for Host Rx endpoint */
-#define                       USB_COUNT0  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                      USB_RXCOUNT  0xffc03850   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                       USB_TXTYPE  0xffc03854   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
-#define                    USB_NAKLIMIT0  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                   USB_TXINTERVAL  0xffc03858   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                       USB_RXTYPE  0xffc0385c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
-#define                   USB_RXINTERVAL  0xffc03860   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
-#define                      USB_TXCOUNT  0xffc03868   /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* USB Endpoint FIFO Registers */
-
-#define                     USB_EP0_FIFO  0xffc03880   /* Endpoint 0 FIFO */
-#define                     USB_EP1_FIFO  0xffc03888   /* Endpoint 1 FIFO */
-#define                     USB_EP2_FIFO  0xffc03890   /* Endpoint 2 FIFO */
-#define                     USB_EP3_FIFO  0xffc03898   /* Endpoint 3 FIFO */
-#define                     USB_EP4_FIFO  0xffc038a0   /* Endpoint 4 FIFO */
-#define                     USB_EP5_FIFO  0xffc038a8   /* Endpoint 5 FIFO */
-#define                     USB_EP6_FIFO  0xffc038b0   /* Endpoint 6 FIFO */
-#define                     USB_EP7_FIFO  0xffc038b8   /* Endpoint 7 FIFO */
-
-/* USB OTG Control Registers */
-
-#define                  USB_OTG_DEV_CTL  0xffc03900   /* OTG Device Control Register */
-#define                 USB_OTG_VBUS_IRQ  0xffc03904   /* OTG VBUS Control Interrupts */
-#define                USB_OTG_VBUS_MASK  0xffc03908   /* VBUS Control Interrupt Enable */
-
-/* USB Phy Control Registers */
-
-#define                     USB_LINKINFO  0xffc03948   /* Enables programming of some PHY-side delays */
-#define                        USB_VPLEN  0xffc0394c   /* Determines duration of VBUS pulse for VBUS charging */
-#define                      USB_HS_EOF1  0xffc03950   /* Time buffer for High-Speed transactions */
-#define                      USB_FS_EOF1  0xffc03954   /* Time buffer for Full-Speed transactions */
-#define                      USB_LS_EOF1  0xffc03958   /* Time buffer for Low-Speed transactions */
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define                   USB_APHY_CNTRL  0xffc039e0   /* Register that increases visibility of Analog PHY */
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define                   USB_APHY_CALIB  0xffc039e4   /* Register used to set some calibration values */
-
-#define                  USB_APHY_CNTRL2  0xffc039e8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc039ec   /* Used for reducing simulation time and simplifies FIFO testability */
-
-#define                  USB_PLLOSC_CTRL  0xffc039f0   /* Used to program different parameters for USB PLL and Oscillator */
-#define                   USB_SRP_CLKDIV  0xffc039f4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
-
-/* USB Endpoint 0 Control Registers */
-
-#define                USB_EP_NI0_TXMAXP  0xffc03a00   /* Maximum packet size for Host Tx endpoint0 */
-#define                 USB_EP_NI0_TXCSR  0xffc03a04   /* Control Status register for endpoint 0 */
-#define                USB_EP_NI0_RXMAXP  0xffc03a08   /* Maximum packet size for Host Rx endpoint0 */
-#define                 USB_EP_NI0_RXCSR  0xffc03a0c   /* Control Status register for Host Rx endpoint0 */
-#define               USB_EP_NI0_RXCOUNT  0xffc03a10   /* Number of bytes received in endpoint 0 FIFO */
-#define                USB_EP_NI0_TXTYPE  0xffc03a14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
-#define            USB_EP_NI0_TXINTERVAL  0xffc03a18   /* Sets the NAK response timeout on Endpoint 0 */
-#define                USB_EP_NI0_RXTYPE  0xffc03a1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
-#define            USB_EP_NI0_RXINTERVAL  0xffc03a20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
-#define               USB_EP_NI0_TXCOUNT  0xffc03a28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
-
-/* USB Endpoint 1 Control Registers */
-
-#define                USB_EP_NI1_TXMAXP  0xffc03a40   /* Maximum packet size for Host Tx endpoint1 */
-#define                 USB_EP_NI1_TXCSR  0xffc03a44   /* Control Status register for endpoint1 */
-#define                USB_EP_NI1_RXMAXP  0xffc03a48   /* Maximum packet size for Host Rx endpoint1 */
-#define                 USB_EP_NI1_RXCSR  0xffc03a4c   /* Control Status register for Host Rx endpoint1 */
-#define               USB_EP_NI1_RXCOUNT  0xffc03a50   /* Number of bytes received in endpoint1 FIFO */
-#define                USB_EP_NI1_TXTYPE  0xffc03a54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
-#define            USB_EP_NI1_TXINTERVAL  0xffc03a58   /* Sets the NAK response timeout on Endpoint1 */
-#define                USB_EP_NI1_RXTYPE  0xffc03a5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
-#define            USB_EP_NI1_RXINTERVAL  0xffc03a60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
-#define               USB_EP_NI1_TXCOUNT  0xffc03a68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
-
-/* USB Endpoint 2 Control Registers */
-
-#define                USB_EP_NI2_TXMAXP  0xffc03a80   /* Maximum packet size for Host Tx endpoint2 */
-#define                 USB_EP_NI2_TXCSR  0xffc03a84   /* Control Status register for endpoint2 */
-#define                USB_EP_NI2_RXMAXP  0xffc03a88   /* Maximum packet size for Host Rx endpoint2 */
-#define                 USB_EP_NI2_RXCSR  0xffc03a8c   /* Control Status register for Host Rx endpoint2 */
-#define               USB_EP_NI2_RXCOUNT  0xffc03a90   /* Number of bytes received in endpoint2 FIFO */
-#define                USB_EP_NI2_TXTYPE  0xffc03a94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
-#define            USB_EP_NI2_TXINTERVAL  0xffc03a98   /* Sets the NAK response timeout on Endpoint2 */
-#define                USB_EP_NI2_RXTYPE  0xffc03a9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
-#define            USB_EP_NI2_RXINTERVAL  0xffc03aa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
-#define               USB_EP_NI2_TXCOUNT  0xffc03aa8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
-
-/* USB Endpoint 3 Control Registers */
-
-#define                USB_EP_NI3_TXMAXP  0xffc03ac0   /* Maximum packet size for Host Tx endpoint3 */
-#define                 USB_EP_NI3_TXCSR  0xffc03ac4   /* Control Status register for endpoint3 */
-#define                USB_EP_NI3_RXMAXP  0xffc03ac8   /* Maximum packet size for Host Rx endpoint3 */
-#define                 USB_EP_NI3_RXCSR  0xffc03acc   /* Control Status register for Host Rx endpoint3 */
-#define               USB_EP_NI3_RXCOUNT  0xffc03ad0   /* Number of bytes received in endpoint3 FIFO */
-#define                USB_EP_NI3_TXTYPE  0xffc03ad4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
-#define            USB_EP_NI3_TXINTERVAL  0xffc03ad8   /* Sets the NAK response timeout on Endpoint3 */
-#define                USB_EP_NI3_RXTYPE  0xffc03adc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
-#define            USB_EP_NI3_RXINTERVAL  0xffc03ae0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
-#define               USB_EP_NI3_TXCOUNT  0xffc03ae8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
-
-/* USB Endpoint 4 Control Registers */
-
-#define                USB_EP_NI4_TXMAXP  0xffc03b00   /* Maximum packet size for Host Tx endpoint4 */
-#define                 USB_EP_NI4_TXCSR  0xffc03b04   /* Control Status register for endpoint4 */
-#define                USB_EP_NI4_RXMAXP  0xffc03b08   /* Maximum packet size for Host Rx endpoint4 */
-#define                 USB_EP_NI4_RXCSR  0xffc03b0c   /* Control Status register for Host Rx endpoint4 */
-#define               USB_EP_NI4_RXCOUNT  0xffc03b10   /* Number of bytes received in endpoint4 FIFO */
-#define                USB_EP_NI4_TXTYPE  0xffc03b14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
-#define            USB_EP_NI4_TXINTERVAL  0xffc03b18   /* Sets the NAK response timeout on Endpoint4 */
-#define                USB_EP_NI4_RXTYPE  0xffc03b1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
-#define            USB_EP_NI4_RXINTERVAL  0xffc03b20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
-#define               USB_EP_NI4_TXCOUNT  0xffc03b28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
-
-/* USB Endpoint 5 Control Registers */
-
-#define                USB_EP_NI5_TXMAXP  0xffc03b40   /* Maximum packet size for Host Tx endpoint5 */
-#define                 USB_EP_NI5_TXCSR  0xffc03b44   /* Control Status register for endpoint5 */
-#define                USB_EP_NI5_RXMAXP  0xffc03b48   /* Maximum packet size for Host Rx endpoint5 */
-#define                 USB_EP_NI5_RXCSR  0xffc03b4c   /* Control Status register for Host Rx endpoint5 */
-#define               USB_EP_NI5_RXCOUNT  0xffc03b50   /* Number of bytes received in endpoint5 FIFO */
-#define                USB_EP_NI5_TXTYPE  0xffc03b54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
-#define            USB_EP_NI5_TXINTERVAL  0xffc03b58   /* Sets the NAK response timeout on Endpoint5 */
-#define                USB_EP_NI5_RXTYPE  0xffc03b5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
-#define            USB_EP_NI5_RXINTERVAL  0xffc03b60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
-#define               USB_EP_NI5_TXCOUNT  0xffc03b68   /* Number of bytes to be written to the endpoint5 Tx FIFO */
-
-/* USB Endpoint 6 Control Registers */
-
-#define                USB_EP_NI6_TXMAXP  0xffc03b80   /* Maximum packet size for Host Tx endpoint6 */
-#define                 USB_EP_NI6_TXCSR  0xffc03b84   /* Control Status register for endpoint6 */
-#define                USB_EP_NI6_RXMAXP  0xffc03b88   /* Maximum packet size for Host Rx endpoint6 */
-#define                 USB_EP_NI6_RXCSR  0xffc03b8c   /* Control Status register for Host Rx endpoint6 */
-#define               USB_EP_NI6_RXCOUNT  0xffc03b90   /* Number of bytes received in endpoint6 FIFO */
-#define                USB_EP_NI6_TXTYPE  0xffc03b94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
-#define            USB_EP_NI6_TXINTERVAL  0xffc03b98   /* Sets the NAK response timeout on Endpoint6 */
-#define                USB_EP_NI6_RXTYPE  0xffc03b9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
-#define            USB_EP_NI6_RXINTERVAL  0xffc03ba0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
-#define               USB_EP_NI6_TXCOUNT  0xffc03ba8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
-
-/* USB Endpoint 7 Control Registers */
-
-#define                USB_EP_NI7_TXMAXP  0xffc03bc0   /* Maximum packet size for Host Tx endpoint7 */
-#define                 USB_EP_NI7_TXCSR  0xffc03bc4   /* Control Status register for endpoint7 */
-#define                USB_EP_NI7_RXMAXP  0xffc03bc8   /* Maximum packet size for Host Rx endpoint7 */
-#define                 USB_EP_NI7_RXCSR  0xffc03bcc   /* Control Status register for Host Rx endpoint7 */
-#define               USB_EP_NI7_RXCOUNT  0xffc03bd0   /* Number of bytes received in endpoint7 FIFO */
-#define                USB_EP_NI7_TXTYPE  0xffc03bd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
-#define            USB_EP_NI7_TXINTERVAL  0xffc03bd8   /* Sets the NAK response timeout on Endpoint7 */
-#define                USB_EP_NI7_RXTYPE  0xffc03bdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
-#define            USB_EP_NI7_RXINTERVAL  0xffc03bf0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
-#define               USB_EP_NI7_TXCOUNT  0xffc03bf8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
-
-#define                USB_DMA_INTERRUPT  0xffc03c00   /* Indicates pending interrupts for the DMA channels */
-
-/* USB Channel 0 Config Registers */
-
-#define                  USB_DMA0CONTROL  0xffc03c04   /* DMA master channel 0 configuration */
-#define                  USB_DMA0ADDRLOW  0xffc03c08   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0ADDRHIGH  0xffc03c0c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0COUNTLOW  0xffc03c10   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
-#define                USB_DMA0COUNTHIGH  0xffc03c14   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
-
-/* USB Channel 1 Config Registers */
-
-#define                  USB_DMA1CONTROL  0xffc03c24   /* DMA master channel 1 configuration */
-#define                  USB_DMA1ADDRLOW  0xffc03c28   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1ADDRHIGH  0xffc03c2c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1COUNTLOW  0xffc03c30   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
-#define                USB_DMA1COUNTHIGH  0xffc03c34   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
-
-/* USB Channel 2 Config Registers */
-
-#define                  USB_DMA2CONTROL  0xffc03c44   /* DMA master channel 2 configuration */
-#define                  USB_DMA2ADDRLOW  0xffc03c48   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2ADDRHIGH  0xffc03c4c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2COUNTLOW  0xffc03c50   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
-#define                USB_DMA2COUNTHIGH  0xffc03c54   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
-
-/* USB Channel 3 Config Registers */
-
-#define                  USB_DMA3CONTROL  0xffc03c64   /* DMA master channel 3 configuration */
-#define                  USB_DMA3ADDRLOW  0xffc03c68   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3ADDRHIGH  0xffc03c6c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3COUNTLOW  0xffc03c70   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
-#define                USB_DMA3COUNTHIGH  0xffc03c74   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
-
-/* USB Channel 4 Config Registers */
-
-#define                  USB_DMA4CONTROL  0xffc03c84   /* DMA master channel 4 configuration */
-#define                  USB_DMA4ADDRLOW  0xffc03c88   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4ADDRHIGH  0xffc03c8c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4COUNTLOW  0xffc03c90   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
-#define                USB_DMA4COUNTHIGH  0xffc03c94   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
-
-/* USB Channel 5 Config Registers */
-
-#define                  USB_DMA5CONTROL  0xffc03ca4   /* DMA master channel 5 configuration */
-#define                  USB_DMA5ADDRLOW  0xffc03ca8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5ADDRHIGH  0xffc03cac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5COUNTLOW  0xffc03cb0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
-#define                USB_DMA5COUNTHIGH  0xffc03cb4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
-
-/* USB Channel 6 Config Registers */
-
-#define                  USB_DMA6CONTROL  0xffc03cc4   /* DMA master channel 6 configuration */
-#define                  USB_DMA6ADDRLOW  0xffc03cc8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6ADDRHIGH  0xffc03ccc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6COUNTLOW  0xffc03cd0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
-#define                USB_DMA6COUNTHIGH  0xffc03cd4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
-
-/* USB Channel 7 Config Registers */
-
-#define                  USB_DMA7CONTROL  0xffc03ce4   /* DMA master channel 7 configuration */
-#define                  USB_DMA7ADDRLOW  0xffc03ce8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7ADDRHIGH  0xffc03cec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7COUNTLOW  0xffc03cf0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
-#define                USB_DMA7COUNTHIGH  0xffc03cf4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
-
-/* Bit masks for USB_FADDR */
-
-#define          FUNCTION_ADDRESS  0x7f       /* Function address */
-
-/* Bit masks for USB_POWER */
-
-#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define          nENABLE_SUSPENDM  0x0       
-#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define             nSUSPEND_MODE  0x0       
-#define               RESUME_MODE  0x4        /* DMA Mode */
-#define              nRESUME_MODE  0x0       
-#define                     RESET  0x8        /* Reset indicator */
-#define                    nRESET  0x0       
-#define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                  nHS_MODE  0x0       
-#define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                nHS_ENABLE  0x0       
-#define                 SOFT_CONN  0x40       /* Soft connect */
-#define                nSOFT_CONN  0x0       
-#define                ISO_UPDATE  0x80       /* Isochronous update */
-#define               nISO_UPDATE  0x0       
-
-/* Bit masks for USB_INTRTX */
-
-#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                   nEP0_TX  0x0       
-#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                   nEP1_TX  0x0       
-#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                   nEP2_TX  0x0       
-#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                   nEP3_TX  0x0       
-#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                   nEP4_TX  0x0       
-#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                   nEP5_TX  0x0       
-#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                   nEP6_TX  0x0       
-#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-#define                   nEP7_TX  0x0       
-
-/* Bit masks for USB_INTRRX */
-
-#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                   nEP1_RX  0x0       
-#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                   nEP2_RX  0x0       
-#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                   nEP3_RX  0x0       
-#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                   nEP4_RX  0x0       
-#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                   nEP5_RX  0x0       
-#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                   nEP6_RX  0x0       
-#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-#define                   nEP7_RX  0x0       
-
-/* Bit masks for USB_INTRTXE */
-
-#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                 nEP0_TX_E  0x0       
-#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                 nEP1_TX_E  0x0       
-#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                 nEP2_TX_E  0x0       
-#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                 nEP3_TX_E  0x0       
-#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                 nEP4_TX_E  0x0       
-#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                 nEP5_TX_E  0x0       
-#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                 nEP6_TX_E  0x0       
-#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-#define                 nEP7_TX_E  0x0       
-
-/* Bit masks for USB_INTRRXE */
-
-#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                 nEP1_RX_E  0x0       
-#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                 nEP2_RX_E  0x0       
-#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                 nEP3_RX_E  0x0       
-#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                 nEP4_RX_E  0x0       
-#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                 nEP5_RX_E  0x0       
-#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                 nEP6_RX_E  0x0       
-#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-#define                 nEP7_RX_E  0x0       
-
-/* Bit masks for USB_INTRUSB */
-
-#define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                nSUSPEND_B  0x0       
-#define                  RESUME_B  0x2        /* Resume indicator */
-#define                 nRESUME_B  0x0       
-#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define         nRESET_OR_BABLE_B  0x0       
-#define                     SOF_B  0x8        /* Start of frame */
-#define                    nSOF_B  0x0       
-#define                    CONN_B  0x10       /* Connection indicator */
-#define                   nCONN_B  0x0       
-#define                  DISCON_B  0x20       /* Disconnect indicator */
-#define                 nDISCON_B  0x0       
-#define             SESSION_REQ_B  0x40       /* Session Request */
-#define            nSESSION_REQ_B  0x0       
-#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-#define             nVBUS_ERROR_B  0x0       
-
-/* Bit masks for USB_INTRUSBE */
-
-#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define               nSUSPEND_BE  0x0       
-#define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define                nRESUME_BE  0x0       
-#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define        nRESET_OR_BABLE_BE  0x0       
-#define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   nSOF_BE  0x0       
-#define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                  nCONN_BE  0x0       
-#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define                nDISCON_BE  0x0       
-#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define           nSESSION_REQ_BE  0x0       
-#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-#define            nVBUS_ERROR_BE  0x0       
-
-/* Bit masks for USB_FRAME */
-
-#define              FRAME_NUMBER  0x7ff      /* Frame number */
-
-/* Bit masks for USB_INDEX */
-
-#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
-
-/* Bit masks for USB_GLOBAL_CTL */
-
-#define                GLOBAL_ENA  0x1        /* enables USB module */
-#define               nGLOBAL_ENA  0x0       
-#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define               nEP1_TX_ENA  0x0       
-#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define               nEP2_TX_ENA  0x0       
-#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define               nEP3_TX_ENA  0x0       
-#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define               nEP4_TX_ENA  0x0       
-#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define               nEP5_TX_ENA  0x0       
-#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define               nEP6_TX_ENA  0x0       
-#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define               nEP7_TX_ENA  0x0       
-#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define               nEP1_RX_ENA  0x0       
-#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define               nEP2_RX_ENA  0x0       
-#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define               nEP3_RX_ENA  0x0       
-#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define               nEP4_RX_ENA  0x0       
-#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define               nEP5_RX_ENA  0x0       
-#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define               nEP6_RX_ENA  0x0       
-#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-#define               nEP7_RX_ENA  0x0       
-
-/* Bit masks for USB_OTG_DEV_CTL */
-
-#define                   SESSION  0x1        /* session indicator */
-#define                  nSESSION  0x0       
-#define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 nHOST_REQ  0x0       
-#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                nHOST_MODE  0x0       
-#define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                    nVBUS0  0x0       
-#define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                    nVBUS1  0x0       
-#define                     LSDEV  0x20       /* Low-speed indicator */
-#define                    nLSDEV  0x0       
-#define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                    nFSDEV  0x0       
-#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-#define                 nB_DEVICE  0x0       
-
-/* Bit masks for USB_OTG_VBUS_IRQ */
-
-#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            nDRIVE_VBUS_ON  0x0       
-#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           nDRIVE_VBUS_OFF  0x0       
-#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define          nCHRG_VBUS_START  0x0       
-#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define            nCHRG_VBUS_END  0x0       
-#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define       nDISCHRG_VBUS_START  0x0       
-#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-#define         nDISCHRG_VBUS_END  0x0       
-
-/* Bit masks for USB_OTG_VBUS_MASK */
-
-#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        nDRIVE_VBUS_ON_ENA  0x0       
-#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       nDRIVE_VBUS_OFF_ENA  0x0       
-#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define      nCHRG_VBUS_START_ENA  0x0       
-#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define        nCHRG_VBUS_END_ENA  0x0       
-#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define   nDISCHRG_VBUS_START_ENA  0x0       
-#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-#define     nDISCHRG_VBUS_END_ENA  0x0       
-
-/* Bit masks for USB_CSR0 */
-
-#define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                 nRXPKTRDY  0x0       
-#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                 nTXPKTRDY  0x0       
-#define                STALL_SENT  0x4        /* STALL handshake sent */
-#define               nSTALL_SENT  0x0       
-#define                   DATAEND  0x8        /* Data end indicator */
-#define                  nDATAEND  0x0       
-#define                  SETUPEND  0x10       /* Setup end */
-#define                 nSETUPEND  0x0       
-#define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define                nSENDSTALL  0x0       
-#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define        nSERVICED_RXPKTRDY  0x0       
-#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define        nSERVICED_SETUPEND  0x0       
-#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define                nFLUSHFIFO  0x0       
-#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define         nSTALL_RECEIVED_H  0x0       
-#define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define               nSETUPPKT_H  0x0       
-#define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  nERROR_H  0x0       
-#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define                 nREQPKT_H  0x0       
-#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define              nSTATUSPKT_H  0x0       
-#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-#define            nNAK_TIMEOUT_H  0x0       
-
-/* Bit masks for USB_COUNT0 */
-
-#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
-
-/* Bit masks for USB_NAKLIMIT0 */
-
-#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
-
-/* Bit masks for USB_TX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_RX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_TXCSR */
-
-#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define               nTXPKTRDY_T  0x0       
-#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define         nFIFO_NOT_EMPTY_T  0x0       
-#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               nUNDERRUN_T  0x0       
-#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              nFLUSHFIFO_T  0x0       
-#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define             nSTALL_SEND_T  0x0       
-#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define             nSTALL_SENT_T  0x0       
-#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_T  0x0       
-#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define               nINCOMPTX_T  0x0       
-#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_T  0x0       
-#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define       nFORCE_DATATOGGLE_T  0x0       
-#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_T  0x0       
-#define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                    nISO_T  0x0       
-#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                nAUTOSET_T  0x0       
-#define                  ERROR_TH  0x4        /* error condition host mode */
-#define                 nERROR_TH  0x0       
-#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_TH  0x0       
-#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-#define           nNAK_TIMEOUT_TH  0x0       
-
-/* Bit masks for USB_TXCOUNT */
-
-#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* Bit masks for USB_RXCSR */
-
-#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               nRXPKTRDY_R  0x0       
-#define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define              nFIFO_FULL_R  0x0       
-#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define                nOVERRUN_R  0x0       
-#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define              nDATAERROR_R  0x0       
-#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              nFLUSHFIFO_R  0x0       
-#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define             nSTALL_SEND_R  0x0       
-#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define             nSTALL_SENT_R  0x0       
-#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define       nCLEAR_DATATOGGLE_R  0x0       
-#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define               nINCOMPRX_R  0x0       
-#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define             nDMAREQMODE_R  0x0       
-#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define                nDISNYET_R  0x0       
-#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define             nDMAREQ_ENA_R  0x0       
-#define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define                    nISO_R  0x0       
-#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define              nAUTOCLEAR_R  0x0       
-#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 nERROR_RH  0x0       
-#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define                nREQPKT_RH  0x0       
-#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define        nSTALL_RECEIVED_RH  0x0       
-#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define              nINCOMPRX_RH  0x0       
-#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define            nDMAREQMODE_RH  0x0       
-#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-#define               nAUTOREQ_RH  0x0       
-
-/* Bit masks for USB_RXCOUNT */
-
-#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
-
-/* Bit masks for USB_TXTYPE */
-
-#define            TARGET_EP_NO_T  0xf        /* EP number */
-#define                PROTOCOL_T  0xc        /* transfer type */
-
-/* Bit masks for USB_TXINTERVAL */
-
-#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
-
-/* Bit masks for USB_RXTYPE */
-
-#define            TARGET_EP_NO_R  0xf        /* EP number */
-#define                PROTOCOL_R  0xc        /* transfer type */
-
-/* Bit masks for USB_RXINTERVAL */
-
-#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
-
-/* Bit masks for USB_DMA_INTERRUPT */
-
-#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                 nDMA0_INT  0x0       
-#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                 nDMA1_INT  0x0       
-#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                 nDMA2_INT  0x0       
-#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                 nDMA3_INT  0x0       
-#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                 nDMA4_INT  0x0       
-#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                 nDMA5_INT  0x0       
-#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                 nDMA6_INT  0x0       
-#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-#define                 nDMA7_INT  0x0       
-
-/* Bit masks for USB_DMAxCONTROL */
-
-#define                   DMA_ENA  0x1        /* DMA enable */
-#define                  nDMA_ENA  0x0       
-#define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                nDIRECTION  0x0       
-#define                      MODE  0x4        /* DMA Bus error */
-#define                     nMODE  0x0       
-#define                   INT_ENA  0x8        /* Interrupt enable */
-#define                  nINT_ENA  0x0       
-#define                     EPNUM  0xf0       /* EP number */
-#define                  BUSERROR  0x100      /* DMA Bus error */
-#define                 nBUSERROR  0x0       
-
-/* Bit masks for USB_DMAxADDRHIGH */
-
-#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxADDRLOW */
-
-#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTHIGH */
-
-#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTLOW */
-
-#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
-
 #endif /* _DEF_BF527_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
index b9dbb73..8b18b53 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF52x_base.h
@@ -586,58 +586,6 @@
 **				modifier UNLESS the lower order bits are saved and ORed back in when
 **				the macro is used.
 *************************************************************************************/
-/*
-** ********************* PLL AND RESET MASKS ****************************************/
-/* PLL_CTL Masks																	*/
-#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2					*/
-#define PLL_OFF			0x0002	/* PLL Not Powered									*/
-#define STOPCK			0x0008	/* Core Clock Off									*/
-#define PDWN			0x0020	/* Enter Deep Sleep Mode							*/
-#define	IN_DELAY		0x0040	/* Add 200ps Delay To EBIU Input Latches			*/
-#define	OUT_DELAY		0x0080	/* Add 200ps Delay To EBIU Output Signals			*/
-#define BYPASS			0x0100	/* Bypass the PLL									*/
-#define	MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors			*/
-/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
-#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
-
-/* PLL_DIV Masks														*/
-#define SSEL			0x000F	/* System Select						*/
-#define	CSEL			0x0030	/* Core Select							*/
-#define CSEL_DIV1		0x0000	/* 		CCLK = VCO / 1					*/
-#define CSEL_DIV2		0x0010	/* 		CCLK = VCO / 2					*/
-#define	CSEL_DIV4		0x0020	/* 		CCLK = VCO / 4					*/
-#define	CSEL_DIV8		0x0030	/* 		CCLK = VCO / 8					*/
-/* PLL_DIV Macros														*/
-#define SET_SSEL(x)		((x)&0xF)		/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
-
-/* VR_CTL Masks	*/
-#define	FREQ			0x3000	/* Switching Oscillator Frequency For Regulator	*/
-#define	HIBERNATE		0x0000	/* 		Powerdown/Bypass On-Board Regulation	*/
-
-#define	VLEV			0x00F0	/* Internal Voltage Level					*/
-#define	VLEV_085 		0x0060	/* 		VLEV = 0.85 V (-5% - +10% Accuracy)	*/
-#define	VLEV_090		0x0070	/* 		VLEV = 0.90 V (-5% - +10% Accuracy)	*/
-#define	VLEV_095		0x0080	/* 		VLEV = 0.95 V (-5% - +10% Accuracy)	*/
-#define	VLEV_100		0x0090	/* 		VLEV = 1.00 V (-5% - +10% Accuracy)	*/
-#define	VLEV_105		0x00A0	/* 		VLEV = 1.05 V (-5% - +10% Accuracy)	*/
-#define	VLEV_110		0x00B0	/* 		VLEV = 1.10 V (-5% - +10% Accuracy)	*/
-#define	VLEV_115		0x00C0	/* 		VLEV = 1.15 V (-5% - +10% Accuracy)	*/
-#define	VLEV_120		0x00D0	/* 		VLEV = 1.20 V (-5% - +10% Accuracy)	*/
-#define	VLEV_125		0x00E0	/* 		VLEV = 1.25 V (-5% - +10% Accuracy)	*/
-#define	VLEV_130		0x00F0	/* 		VLEV = 1.30 V (-5% - +10% Accuracy)	*/
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate	*/
-#define	USBWE			0x0200	/* Enable USB Wakeup From Hibernate			*/
-#define	PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate			*/
-#define	CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
-#define	PHYCLKOE		CLKBUFOE	/* Alternative legacy name for the above */
-#define	SCKELOW		0x8000	/* Enable Drive CKE Low During Reset		*/
-
-/* PLL_STAT Masks																	*/
-#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled	*/
-#define	FULL_ON				0x0002	/* Processor In Full On Mode					*/
-#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled	*/
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached					*/
 
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
@@ -757,66 +705,6 @@
 #define IWR_DISABLE(x)	(0xFFFFFFFF ^ (1 << ((x)&0x1F))) 	/* Wakeup Disable Peripheral #x		*/
 
 
-/* ********* WATCHDOG TIMER MASKS ******************** */
-
-/* Watchdog Timer WDOG_CTL Register Masks */
-
-#define WDEV(x) (((x)<<1) & 0x0006) /* event generated on roll over */
-#define WDEV_RESET 0x0000 /* generate reset event on roll over */
-#define WDEV_NMI 0x0002 /* generate NMI event on roll over */
-#define WDEV_GPI 0x0004 /* generate GP IRQ on roll over */
-#define WDEV_NONE 0x0006 /* no event on roll over */
-#define WDEN 0x0FF0 /* enable watchdog */
-#define WDDIS 0x0AD0 /* disable watchdog */
-#define WDRO 0x8000 /* watchdog rolled over latch */
-
-/* depreciated WDOG_CTL Register Masks for legacy code */
-
-
-#define ICTL WDEV
-#define ENABLE_RESET WDEV_RESET
-#define WDOG_RESET WDEV_RESET
-#define ENABLE_NMI WDEV_NMI
-#define WDOG_NMI WDEV_NMI
-#define ENABLE_GPI WDEV_GPI
-#define WDOG_GPI WDEV_GPI
-#define DISABLE_EVT WDEV_NONE
-#define WDOG_NONE WDEV_NONE
-
-#define TMR_EN WDEN
-#define TMR_DIS WDDIS
-#define TRO WDRO
-#define ICTL_P0 0x01
- #define ICTL_P1 0x02
-#define TRO_P 0x0F
-
-
-
-/* ***************  REAL TIME CLOCK MASKS  **************************/
-/* RTC_STAT and RTC_ALARM Masks										*/
-#define	RTC_SEC				0x0000003F	/* Real-Time Clock Seconds	*/
-#define	RTC_MIN				0x00000FC0	/* Real-Time Clock Minutes	*/
-#define	RTC_HR				0x0001F000	/* Real-Time Clock Hours	*/
-#define	RTC_DAY				0xFFFE0000	/* Real-Time Clock Days		*/
-
-/* RTC_ALARM Macro			z=day		y=hr	x=min	w=sec		*/
-#define SET_ALARM(z,y,x,w)	((((z)&0x7FFF)<<0x11)|(((y)&0x1F)<<0xC)|(((x)&0x3F)<<0x6)|((w)&0x3F))
-
-/* RTC_ICTL and RTC_ISTAT Masks																		*/
-#define	STOPWATCH			0x0001		/* Stopwatch Interrupt Enable								*/
-#define	ALARM				0x0002		/* Alarm Interrupt Enable									*/
-#define	SECOND				0x0004		/* Seconds (1 Hz) Interrupt Enable							*/
-#define	MINUTE				0x0008		/* Minutes Interrupt Enable									*/
-#define	HOUR				0x0010		/* Hours Interrupt Enable									*/
-#define	DAY					0x0020		/* 24 Hours (Days) Interrupt Enable							*/
-#define	DAY_ALARM			0x0040		/* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable	*/
-#define	WRITE_PENDING		0x4000		/* Write Pending Status										*/
-#define	WRITE_COMPLETE		0x8000		/* Write Complete Interrupt Enable							*/
-
-/* RTC_FAST / RTC_PREN Mask												*/
-#define PREN				0x0001	/* Enable Prescaler, RTC Runs @1 Hz	*/
-
-
 /* ************** UART CONTROLLER MASKS *************************/
 /* UARTx_LCR Masks												*/
 #define WLS(x)		(((x)-5) & 0x03)	/* Word Length Select */
@@ -1381,33 +1269,6 @@
 
 
 /* **************************  DMA CONTROLLER MASKS  ********************************/
-/* DMAx_CONFIG, MDMA_yy_CONFIG Masks												*/
-#define DMAEN			0x0001		/* DMA Channel Enable							*/
-#define WNR				0x0002		/* Channel Direction (W/R*)						*/
-#define WDSIZE_8		0x0000		/* Transfer Word Size = 8						*/
-#define WDSIZE_16		0x0004		/* Transfer Word Size = 16						*/
-#define WDSIZE_32		0x0008		/* Transfer Word Size = 32						*/
-#define DMA2D			0x0010		/* DMA Mode (2D/1D*)							*/
-#define RESTART			0x0020		/* DMA Buffer Clear								*/
-#define DI_SEL			0x0040		/* Data Interrupt Timing Select					*/
-#define DI_EN			0x0080		/* Data Interrupt Enable						*/
-#define NDSIZE_0		0x0000		/* Next Descriptor Size = 0 (Stop/Autobuffer)	*/
-#define NDSIZE_1		0x0100		/* Next Descriptor Size = 1						*/
-#define NDSIZE_2		0x0200		/* Next Descriptor Size = 2						*/
-#define NDSIZE_3		0x0300		/* Next Descriptor Size = 3						*/
-#define NDSIZE_4		0x0400		/* Next Descriptor Size = 4						*/
-#define NDSIZE_5		0x0500		/* Next Descriptor Size = 5						*/
-#define NDSIZE_6		0x0600		/* Next Descriptor Size = 6						*/
-#define NDSIZE_7		0x0700		/* Next Descriptor Size = 7						*/
-#define NDSIZE_8		0x0800		/* Next Descriptor Size = 8						*/
-#define NDSIZE_9		0x0900		/* Next Descriptor Size = 9						*/
-#define NDSIZE	        	0x0900	/* Next Descriptor Size */
-#define DMAFLOW	        	0x7000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000		/* Stop Mode									*/
-#define DMAFLOW_AUTO		0x1000		/* Autobuffer Mode								*/
-#define DMAFLOW_ARRAY		0x4000		/* Descriptor Array Mode						*/
-#define DMAFLOW_SMALL		0x6000		/* Small Model Descriptor List Mode				*/
-#define DMAFLOW_LARGE		0x7000		/* Large Model Descriptor List Mode				*/
 
 /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
 #define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)	*/
@@ -1425,13 +1286,6 @@
 #define	PMAP_UART1RX	0xA000	/* 		UART1 Port Receive DMA						*/
 #define	PMAP_UART1TX	0xB000	/* 		UART1 Port Transmit DMA						*/
 
-/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks						*/
-#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status	*/
-#define DMA_ERR			0x0002	/* DMA Error Interrupt Status		*/
-#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator	*/
-#define DMA_RUN			0x0008	/* DMA Channel Running Indicator	*/
-
-
 /*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
 /*  PPI_CONTROL Masks													*/
 #define PORT_EN			0x0001		/* PPI Port Enable					*/
@@ -1843,46 +1697,6 @@
 #define BNDMODE_CAPT     0x2000  /* boundary capture mode */
 #define BNDMODE_AEXT     0x3000  /* boundary auto-extend mode */
 
-/* Bit masks for OTP_CONTROL */
-
-#define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
-#define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
-#define                     nFIEN  0x0
-#define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
-#define                 nFTESTDEC  0x0
-#define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
-#define                  nFWRTEST  0x0
-#define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
-#define                    nFRDEN  0x0
-#define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
-#define                    nFWREN  0x0
-
-/* Bit masks for OTP_BEN */
-
-#define                      FBEN  0xffff     /* OTP/Fuse Byte Enable */
-
-/* Bit masks for OTP_STATUS */
-
-#define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
-#define                    nFCOMP  0x0
-#define                    FERROR  0x2        /* OTP/Fuse Access Error */
-#define                   nFERROR  0x0
-#define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
-#define                 nMMRGLOAD  0x0
-#define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
-#define                 nMMRGLOCK  0x0
-#define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
-#define                   nFPGMEN  0x0
-
-/* Bit masks for OTP_TIMING */
-
-#define                   USECDIV  0xff       /* Micro Second Divider */
-#define                   READACC  0x7f00     /* Read Access Time */
-#define                   CPUMPRL  0x38000    /* Charge Pump Release Time */
-#define                   CPUMPSU  0xc0000    /* Charge Pump Setup Time */
-#define                   CPUMPHD  0xf00000   /* Charge Pump Hold Time */
-#define                   PGMTIME  0xff000000 /* Program Time */
-
 /* Bit masks for SECURE_SYSSWT */
 
 #define                   EMUDABL  0x1        /* Emulation Disable. */
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index 43f43a0..4adceb0 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -166,7 +166,6 @@
 #if defined(CONFIG_BFIN_SPI_ADC) || defined(CONFIG_BFIN_SPI_ADC_MODULE)
 /* SPI ADC chip */
 static struct bfin5xx_spi_chip spi_adc_chip_info = {
-	.ctl_reg = 0x1000,
 	.enable_dma = 1,         /* use dma transfer with this chip*/
 	.bits_per_word = 16,
 };
@@ -174,7 +173,6 @@
 
 #if defined(CONFIG_SND_BLACKFIN_AD1836) || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE)
 static struct bfin5xx_spi_chip ad1836_spi_chip_info = {
-	.ctl_reg = 0x1000,
 	.enable_dma = 0,
 	.bits_per_word = 16,
 };
@@ -258,12 +256,6 @@
 };
 #endif  /* spi master and devices */
 
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-static struct platform_device bfin_fb_device = {
-	.name = "bf537-fb",
-};
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 	{
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index 644be5e..8ec42ba 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -20,6 +20,7 @@
 #endif
 #include <asm/irq.h>
 #include <asm/bfin5xx_spi.h>
+#include <asm/portmux.h>
 
 /*
  * Name the Board for the /proc/cpuinfo
@@ -107,20 +108,6 @@
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
-/*
- * CPOL (Clock Polarity)
- *  0 - Active high SCK
- *  1 - Active low SCK
- *  CPHA (Clock Phase) Selects transfer format and operation mode
- *  0 - SCLK toggles from middle of the first data bit, slave select
- *      pins controlled by hardware.
- *  1 - SCLK toggles from beginning of first data bit, slave select
- *      pins controller by user software.
- * 	.ctl_reg = 0x1c00,		 *  CPOL=1,CPHA=1,Sandisk 1G work
- * NO NO	.ctl_reg = 0x1800,		 *  CPOL=1,CPHA=0
- * NO NO	.ctl_reg = 0x1400,		 *  CPOL=0,CPHA=1
- */
-	.ctl_reg = 0x1000,		/* CPOL=0,CPHA=0,Sandisk 1G work */
 	.enable_dma = 0,		/* if 1 - block!!! */
 	.bits_per_word = 8,
 };
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 82f70ef..6d68dcf 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -321,12 +321,6 @@
 };
 #endif  /* spi master and devices */
 
-#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
-static struct platform_device bfin_fb_device = {
-	.name = "bf537-fb",
-};
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 	{
diff --git a/arch/blackfin/mach-bf533/include/mach/defBF532.h b/arch/blackfin/mach-bf533/include/mach/defBF532.h
index 02b328e..e9ff491 100644
--- a/arch/blackfin/mach-bf533/include/mach/defBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/defBF532.h
@@ -370,72 +370,6 @@
 /* System MMR Register Bits */
 /******************************************************************************* */
 
-/* ********************* PLL AND RESET MASKS ************************ */
-
-/* PLL_CTL Masks */
-#define PLL_CLKIN			0x0000  /* Pass CLKIN to PLL */
-#define PLL_CLKIN_DIV2			0x0001  /* Pass CLKIN/2 to PLL */
-#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2					*/
-#define PLL_OFF				0x0002  /* Shut off PLL clocks */
-#define STOPCK_OFF			0x0008  /* Core clock off */
-#define STOPCK				0x0008	/* Core Clock Off									*/
-#define PDWN				0x0020  /* Put the PLL in a Deep Sleep state */
-#if !defined(__ADSPBF538__)
-/* this file is included in defBF538.h but IN_DELAY/OUT_DELAY are different */
-# define IN_DELAY        0x0040  /* Add 200ps Delay To EBIU Input Latches */
-# define OUT_DELAY       0x0080  /* Add 200ps Delay To EBIU Output Signals */
-#endif
-#define BYPASS				0x0100  /* Bypass the PLL */
-/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
-#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
-
-/* PLL_DIV Masks */
-#define SSEL				0x000F	/* System Select						*/
-#define	CSEL				0x0030	/* Core Select							*/
-
-#define SCLK_DIV(x)  (x)	/* SCLK = VCO / x */
-
-#define CCLK_DIV1              0x00000000	/* CCLK = VCO / 1 */
-#define CCLK_DIV2              0x00000010	/* CCLK = VCO / 2 */
-#define CCLK_DIV4              0x00000020	/* CCLK = VCO / 4 */
-#define CCLK_DIV8              0x00000030	/* CCLK = VCO / 8 */
-/* PLL_DIV Macros														*/
-#define SET_SSEL(x)			((x)&0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
-
-/* PLL_STAT Masks																	*/
-#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled    */
-#define	FULL_ON				0x0002	/* Processor In Full On Mode                                    */
-#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled   */
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached                                 */
-
-/* VR_CTL Masks																	*/
-#define	FREQ			0x0003	/* Switching Oscillator Frequency For Regulator	*/
-#define	HIBERNATE		0x0000	/* 		Powerdown/Bypass On-Board Regulation	*/
-#define	FREQ_333		0x0001	/* 		Switching Frequency Is 333 kHz			*/
-#define	FREQ_667		0x0002	/* 		Switching Frequency Is 667 kHz			*/
-#define	FREQ_1000		0x0003	/* 		Switching Frequency Is 1 MHz			*/
-
-#define GAIN			0x000C	/* Voltage Level Gain	*/
-#define	GAIN_5			0x0000	/* 		GAIN = 5		*/
-#define	GAIN_10			0x0004	/* 		GAIN = 10		*/
-#define	GAIN_20			0x0008	/* 		GAIN = 20		*/
-#define	GAIN_50			0x000C	/* 		GAIN = 50		*/
-
-#define	VLEV			0x00F0	/* Internal Voltage Level					*/
-#define	VLEV_085 		0x0060	/* 		VLEV = 0.85 V (-5% - +10% Accuracy)	*/
-#define	VLEV_090		0x0070	/* 		VLEV = 0.90 V (-5% - +10% Accuracy)	*/
-#define	VLEV_095		0x0080	/* 		VLEV = 0.95 V (-5% - +10% Accuracy)	*/
-#define	VLEV_100		0x0090	/* 		VLEV = 1.00 V (-5% - +10% Accuracy)	*/
-#define	VLEV_105		0x00A0	/* 		VLEV = 1.05 V (-5% - +10% Accuracy)	*/
-#define	VLEV_110		0x00B0	/* 		VLEV = 1.10 V (-5% - +10% Accuracy)	*/
-#define	VLEV_115		0x00C0	/* 		VLEV = 1.15 V (-5% - +10% Accuracy)	*/
-#define	VLEV_120		0x00D0	/* 		VLEV = 1.20 V (-5% - +10% Accuracy)	*/
-#define	VLEV_125		0x00E0	/*              VLEV = 1.25 V (-5% - +10% Accuracy)     */
-#define	VLEV_130		0x00F0	/*              VLEV = 1.30 V (-5% - +10% Accuracy)     */
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate	*/
-#define	SCKELOW			0x8000	/* Do Not Drive SCKE High During Reset After Hibernate */
-
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
 #define CHIPID_FAMILY          0x0FFFF000
@@ -703,54 +637,7 @@
 
 /* **********  DMA CONTROLLER MASKS  *********************8 */
 
-/*DMAx_CONFIG, MDMA_yy_CONFIG Masks */
-#define DMAEN	        0x00000001	/* Channel Enable */
-#define WNR	   	0x00000002	/* Channel Direction (W/R*) */
-#define WDSIZE_8	0x00000000	/* Word Size 8 bits */
-#define WDSIZE_16	0x00000004	/* Word Size 16 bits */
-#define WDSIZE_32	0x00000008	/* Word Size 32 bits */
-#define DMA2D	        0x00000010	/* 2D/1D* Mode */
-#define RESTART         0x00000020	/* Restart */
-#define DI_SEL	        0x00000040	/* Data Interrupt Select */
-#define DI_EN	        0x00000080	/* Data Interrupt Enable */
-#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer)   */
-#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1                                             */
-#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2                                             */
-#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3                                             */
-#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4                                             */
-#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5                                             */
-#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6                                             */
-#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7                                             */
-#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8                                             */
-#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9                                             */
-#define NDSIZE	        0x00000900	/* Next Descriptor Size */
-#define DMAFLOW	        0x00007000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000	/* Stop Mode */
-#define DMAFLOW_AUTO		0x1000	/* Autobuffer Mode */
-#define DMAFLOW_ARRAY		0x4000	/* Descriptor Array Mode */
-#define DMAFLOW_SMALL		0x6000	/* Small Model Descriptor List Mode */
-#define DMAFLOW_LARGE		0x7000	/* Large Model Descriptor List Mode */
-
-#define DMAEN_P	            	0	/* Channel Enable */
-#define WNR_P	            	1	/* Channel Direction (W/R*) */
-#define DMA2D_P	        	4	/* 2D/1D* Mode */
-#define RESTART_P	      	5	/* Restart */
-#define DI_SEL_P	     	6	/* Data Interrupt Select */
-#define DI_EN_P	            	7	/* Data Interrupt Enable */
-
-/*DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks */
-
-#define DMA_DONE		0x00000001	/* DMA Done Indicator */
-#define DMA_ERR	        	0x00000002	/* DMA Error Indicator */
-#define DFETCH	            	0x00000004	/* Descriptor Fetch Indicator */
-#define DMA_RUN	            	0x00000008	/* DMA Running Indicator */
-
-#define DMA_DONE_P	    	0	/* DMA Done Indicator */
-#define DMA_ERR_P     		1	/* DMA Error Indicator */
-#define DFETCH_P     		2	/* Descriptor Fetch Indicator */
-#define DMA_RUN_P     		3	/* DMA Running Indicator */
-
-/*DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
 
 #define CTYPE	            0x00000040	/* DMA Channel Type Indicator */
 #define CTYPE_P             6	/* DMA Channel Type Indicator BIT POSITION */
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 9ba2904..4e0afda 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -13,9 +13,6 @@
 #include <linux/mtd/partitions.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-#include <linux/usb/isp1362.h>
-#endif
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
@@ -147,45 +144,6 @@
 };
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-static struct resource isp1362_hcd_resources[] = {
-	{
-		.start = 0x20360000,
-		.end = 0x20360000,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = 0x20360004,
-		.end = 0x20360004,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
-	},
-};
-
-static struct isp1362_platform_data isp1362_priv = {
-	.sel15Kres = 1,
-	.clknotstop = 0,
-	.oc_enable = 0,
-	.int_act_high = 0,
-	.int_edge_triggered = 0,
-	.remote_wakeup_connected = 0,
-	.no_power_switching = 1,
-	.power_switching_mode = 0,
-};
-
-static struct platform_device isp1362_hcd_device = {
-	.name = "isp1362-hcd",
-	.id = 0,
-	.dev = {
-		.platform_data = &isp1362_priv,
-	},
-	.num_resources = ARRAY_SIZE(isp1362_hcd_resources),
-	.resource = isp1362_hcd_resources,
-};
-#endif
-
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
@@ -492,10 +450,6 @@
 	&sl811_hcd_device,
 #endif
 
-#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
-	&isp1362_hcd_device,
-#endif
-
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 	&smc91x_device,
 #endif
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index c46baa5..ac9b52e 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -9,6 +9,7 @@
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -25,6 +26,8 @@
 #include <linux/i2c.h>
 #include <linux/usb/sl811.h>
 #include <linux/spi/mmc_spi.h>
+#include <linux/leds.h>
+#include <linux/input.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/reboot.h>
@@ -65,7 +68,7 @@
 };
 
 static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
+	.name           = "isp1760",
 	.id             = 0,
 	.dev = {
 		.platform_data = &isp1760_priv,
@@ -76,7 +79,6 @@
 #endif
 
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
-#include <linux/input.h>
 #include <linux/gpio_keys.h>
 
 static struct gpio_keys_button bfin_gpio_keys_table[] = {
@@ -195,28 +197,6 @@
 };
 #endif
 
-#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE)
-static struct resource ax88180_resources[] = {
-	[0] = {
-		.start	= 0x20300000,
-		.end	= 0x20300000 + 0x8000,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PF7,
-		.end	= IRQ_PF7,
-		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL),
-	},
-};
-
-static struct platform_device ax88180_device = {
-	.name		= "ax88180",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(ax88180_resources),
-	.resource	= ax88180_resources,
-};
-#endif
-
 #if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
 static struct resource sl811_hcd_resources[] = {
 	{
@@ -272,8 +252,8 @@
 		.end = 0x20360004,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
-		.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
+		.start = IRQ_PF3,
+		.end = IRQ_PF3,
 		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
 	},
 };
@@ -300,6 +280,44 @@
 };
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+unsigned short bfin_can_peripherals[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can_resources[] = {
+	{
+		.start = 0xFFC02A00,
+		.end = 0xFFC02FFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN_RX,
+		.end = IRQ_CAN_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN_TX,
+		.end = IRQ_CAN_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN_ERROR,
+		.end = IRQ_CAN_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can_device = {
+	.name = "bfin_can",
+	.num_resources = ARRAY_SIZE(bfin_can_resources),
+	.resource = bfin_can_resources,
+	.dev = {
+		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+	},
+};
+#endif
+
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 static struct platform_device bfin_mii_bus = {
 	.name = "bfin_mii_bus",
@@ -514,15 +532,14 @@
 };
 #endif
 
-#if defined(CONFIG_INPUT_EVAL_AD7147EBZ)
-#include <linux/input.h>
+#if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
 #include <linux/input/ad714x.h>
 static struct bfin5xx_spi_chip ad7147_spi_chip_info = {
 	.enable_dma = 0,
 	.bits_per_word = 16,
 };
 
-static struct ad714x_slider_plat slider_plat[] = {
+static struct ad714x_slider_plat ad7147_spi_slider_plat[] = {
 	{
 		.start_stage = 0,
 		.end_stage = 7,
@@ -530,7 +547,7 @@
 	},
 };
 
-static struct ad714x_button_plat button_plat[] = {
+static struct ad714x_button_plat ad7147_spi_button_plat[] = {
 	{
 		.keycode = BTN_FORWARD,
 		.l_mask = 0,
@@ -557,11 +574,11 @@
 		.h_mask = 0x400,
 	},
 };
-static struct ad714x_platform_data ad7147_platfrom_data = {
+static struct ad714x_platform_data ad7147_spi_platform_data = {
 	.slider_num = 1,
 	.button_num = 5,
-	.slider = slider_plat,
-	.button = button_plat,
+	.slider = ad7147_spi_slider_plat,
+	.button = ad7147_spi_button_plat,
 	.stage_cfg_reg =  {
 		{0xFBFF, 0x1FFF, 0, 0x2626, 1600, 1600, 1600, 1600},
 		{0xEFFF, 0x1FFF, 0, 0x2626, 1650, 1650, 1650, 1650},
@@ -580,10 +597,9 @@
 };
 #endif
 
-#if defined(CONFIG_INPUT_EVAL_AD7142EB)
-#include <linux/input.h>
+#if defined(CONFIG_INPUT_AD714X_I2C) || defined(CONFIG_INPUT_AD714X_I2C_MODULE)
 #include <linux/input/ad714x.h>
-static struct ad714x_button_plat button_plat[] = {
+static struct ad714x_button_plat ad7142_i2c_button_plat[] = {
 	{
 		.keycode = BTN_1,
 		.l_mask = 0,
@@ -605,9 +621,9 @@
 		.h_mask = 0x8,
 	},
 };
-static struct ad714x_platform_data ad7142_platfrom_data = {
+static struct ad714x_platform_data ad7142_i2c_platform_data = {
 	.button_num = 4,
-	.button = button_plat,
+	.button = ad7142_i2c_button_plat,
 	.stage_cfg_reg =  {
 		/* fixme: figure out right setting for all comoponent according
 		 * to hardware feature of EVAL-AD7142EB board */
@@ -696,8 +712,7 @@
 #endif
 
 #if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
-#include <linux/input.h>
-#include <linux/spi/adxl34x.h>
+#include <linux/input/adxl34x.h>
 static const struct adxl34x_platform_data adxl34x_info = {
 	.x_axis_offset = 0,
 	.y_axis_offset = 0,
@@ -721,9 +736,7 @@
 	.ev_code_y = ABS_Y,		/* EV_REL */
 	.ev_code_z = ABS_Z,		/* EV_REL */
 
-	.ev_code_tap_x = BTN_TOUCH,		/* EV_KEY */
-	.ev_code_tap_y = BTN_TOUCH,		/* EV_KEY */
-	.ev_code_tap_z = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z */
 
 /*	.ev_code_ff = KEY_F,*/		/* EV_KEY */
 /*	.ev_code_act_inactivity = KEY_A,*/	/* EV_KEY */
@@ -761,6 +774,47 @@
 };
 #endif
 
+#if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
+static struct bfin5xx_spi_chip adf7021_spi_chip_info = {
+	.bits_per_word = 16,
+	.cs_gpio = GPIO_PF10,
+};
+
+#include <linux/spi/adf702x.h>
+#define TXREG 0x0160A470
+static const u32 adf7021_regs[] = {
+	0x09608FA0,
+	0x00575011,
+	0x00A7F092,
+	0x2B141563,
+	0x81F29E94,
+	0x00003155,
+	0x050A4F66,
+	0x00000007,
+	0x00000008,
+	0x000231E9,
+	0x3296354A,
+	0x891A2B3B,
+	0x00000D9C,
+	0x0000000D,
+	0x0000000E,
+	0x0000000F,
+};
+
+static struct adf702x_platform_data adf7021_platform_data = {
+	.regs_base = (void *)SPORT1_TCR1,
+	.dma_ch_rx = CH_SPORT1_RX,
+	.dma_ch_tx = CH_SPORT1_TX,
+	.irq_sport_err = IRQ_SPORT1_ERROR,
+	.gpio_int_rfs = GPIO_PF8,
+	.pin_req = {P_SPORT1_DTPRI, P_SPORT1_RFS, P_SPORT1_DRPRI,
+			P_SPORT1_RSCLK, P_SPORT1_TSCLK, 0},
+	.adf702x_model = MODEL_ADF7021,
+	.adf702x_regs = adf7021_regs,
+	.tx_reg = TXREG,
+};
+#endif
+
 #if defined(CONFIG_MTD_DATAFLASH) \
 	|| defined(CONFIG_MTD_DATAFLASH_MODULE)
 
@@ -794,6 +848,13 @@
 };
 #endif
 
+#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_adxl34x_chip_info = {
+	.enable_dma = 0,         /* use dma transfer with this chip*/
+	.bits_per_word = 8,
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -855,7 +916,7 @@
 	},
 #endif
 
-#if defined(CONFIG_INPUT_EVAL_AD7147EBZ)
+#if defined(CONFIG_INPUT_AD714X_SPI) || defined(CONFIG_INPUT_AD714X_SPI_MODULE)
 	{
 		.modalias = "ad714x_captouch",
 		.max_speed_hz = 1000000,     /* max spi clock (SCK) speed in HZ */
@@ -863,7 +924,7 @@
 		.bus_num = 0,
 		.chip_select = 5,
 		.mode = SPI_MODE_3,
-		.platform_data = &ad7147_platfrom_data,
+		.platform_data = &ad7147_spi_platform_data,
 		.controller_data = &ad7147_spi_chip_info,
 	},
 #endif
@@ -932,6 +993,30 @@
 		.mode = SPI_MODE_0,
 	},
 #endif
+#if defined(CONFIG_INPUT_ADXL34X_SPI) || defined(CONFIG_INPUT_ADXL34X_SPI_MODULE)
+	{
+		.modalias	= "adxl34x",
+		.platform_data	= &adxl34x_info,
+		.irq		= IRQ_PF6,
+		.max_speed_hz	= 5000000,    /* max spi clock (SCK) speed in HZ */
+		.bus_num	= 0,
+		.chip_select	= 2,
+		.controller_data = &spi_adxl34x_chip_info,
+		.mode = SPI_MODE_3,
+	},
+#endif
+#if defined(CONFIG_ADF702X) || defined(CONFIG_ADF702X_MODULE)
+	{
+		.modalias = "adf702x",
+		.max_speed_hz = 16000000,     /* max spi clock (SCK) speed in HZ */
+		.bus_num = 0,
+		.chip_select = 0,	/* GPIO controlled SSEL */
+		.controller_data = &adf7021_spi_chip_info,
+		.platform_data = &adf7021_platform_data,
+		.mode = SPI_MODE_0,
+	},
+#endif
+
 };
 
 #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
@@ -1175,7 +1260,6 @@
 #endif
 
 #if defined(CONFIG_KEYBOARD_ADP5588) || defined(CONFIG_KEYBOARD_ADP5588_MODULE)
-#include <linux/input.h>
 #include <linux/i2c/adp5588.h>
 static const unsigned short adp5588_keymap[ADP5588_KEYMAPSIZE] = {
 	[0]	 = KEY_GRAVE,
@@ -1268,35 +1352,33 @@
 	 *  ADP5520/5501 Backlight Data
 	 */
 
-static struct adp5520_backlight_platfrom_data adp5520_backlight_data = {
-	.fade_in 		= FADE_T_1200ms,
-	.fade_out 		= FADE_T_1200ms,
-	.fade_led_law 		= BL_LAW_LINEAR,
-	.en_ambl_sens 		= 1,
-	.abml_filt 		= BL_AMBL_FILT_640ms,
-	.l1_daylight_max 	= BL_CUR_mA(15),
-	.l1_daylight_dim 	= BL_CUR_mA(0),
-	.l2_office_max 		= BL_CUR_mA(7),
-	.l2_office_dim 		= BL_CUR_mA(0),
-	.l3_dark_max 		= BL_CUR_mA(3),
-	.l3_dark_dim 		= BL_CUR_mA(0),
-	.l2_trip 		= L2_COMP_CURR_uA(700),
-	.l2_hyst 		= L2_COMP_CURR_uA(50),
-	.l3_trip 		= L3_COMP_CURR_uA(80),
-	.l3_hyst 		= L3_COMP_CURR_uA(20),
+static struct adp5520_backlight_platform_data adp5520_backlight_data = {
+	.fade_in		= ADP5520_FADE_T_1200ms,
+	.fade_out		= ADP5520_FADE_T_1200ms,
+	.fade_led_law		= ADP5520_BL_LAW_LINEAR,
+	.en_ambl_sens		= 1,
+	.abml_filt		= ADP5520_BL_AMBL_FILT_640ms,
+	.l1_daylight_max	= ADP5520_BL_CUR_mA(15),
+	.l1_daylight_dim	= ADP5520_BL_CUR_mA(0),
+	.l2_office_max		= ADP5520_BL_CUR_mA(7),
+	.l2_office_dim		= ADP5520_BL_CUR_mA(0),
+	.l3_dark_max		= ADP5520_BL_CUR_mA(3),
+	.l3_dark_dim		= ADP5520_BL_CUR_mA(0),
+	.l2_trip		= ADP5520_L2_COMP_CURR_uA(700),
+	.l2_hyst		= ADP5520_L2_COMP_CURR_uA(50),
+	.l3_trip		= ADP5520_L3_COMP_CURR_uA(80),
+	.l3_hyst		= ADP5520_L3_COMP_CURR_uA(20),
 };
 
 	/*
 	 *  ADP5520/5501 LEDs Data
 	 */
 
-#include <linux/leds.h>
-
 static struct led_info adp5520_leds[] = {
 	{
 		.name = "adp5520-led1",
 		.default_trigger = "none",
-		.flags = FLAG_ID_ADP5520_LED1_ADP5501_LED0 | LED_OFFT_600ms,
+		.flags = FLAG_ID_ADP5520_LED1_ADP5501_LED0 | ADP5520_LED_OFFT_600ms,
 	},
 #ifdef ADP5520_EN_ALL_LEDS
 	{
@@ -1312,51 +1394,50 @@
 #endif
 };
 
-static struct adp5520_leds_platfrom_data adp5520_leds_data = {
+static struct adp5520_leds_platform_data adp5520_leds_data = {
 	.num_leds = ARRAY_SIZE(adp5520_leds),
 	.leds = adp5520_leds,
-	.fade_in = FADE_T_600ms,
-	.fade_out = FADE_T_600ms,
-	.led_on_time = LED_ONT_600ms,
+	.fade_in = ADP5520_FADE_T_600ms,
+	.fade_out = ADP5520_FADE_T_600ms,
+	.led_on_time = ADP5520_LED_ONT_600ms,
 };
 
 	/*
 	 *  ADP5520 GPIO Data
 	 */
 
-static struct adp5520_gpio_platfrom_data adp5520_gpio_data = {
+static struct adp5520_gpio_platform_data adp5520_gpio_data = {
 	.gpio_start = 50,
-	.gpio_en_mask = GPIO_C1 | GPIO_C2 | GPIO_R2,
-	.gpio_pullup_mask = GPIO_C1 | GPIO_C2 | GPIO_R2,
+	.gpio_en_mask = ADP5520_GPIO_C1 | ADP5520_GPIO_C2 | ADP5520_GPIO_R2,
+	.gpio_pullup_mask = ADP5520_GPIO_C1 | ADP5520_GPIO_C2 | ADP5520_GPIO_R2,
 };
 
 	/*
 	 *  ADP5520 Keypad Data
 	 */
 
-#include <linux/input.h>
 static const unsigned short adp5520_keymap[ADP5520_KEYMAPSIZE] = {
-	[KEY(0, 0)]	= KEY_GRAVE,
-	[KEY(0, 1)]	= KEY_1,
-	[KEY(0, 2)]	= KEY_2,
-	[KEY(0, 3)]	= KEY_3,
-	[KEY(1, 0)]	= KEY_4,
-	[KEY(1, 1)]	= KEY_5,
-	[KEY(1, 2)]	= KEY_6,
-	[KEY(1, 3)]	= KEY_7,
-	[KEY(2, 0)]	= KEY_8,
-	[KEY(2, 1)]	= KEY_9,
-	[KEY(2, 2)]	= KEY_0,
-	[KEY(2, 3)]	= KEY_MINUS,
-	[KEY(3, 0)]	= KEY_EQUAL,
-	[KEY(3, 1)]	= KEY_BACKSLASH,
-	[KEY(3, 2)]	= KEY_BACKSPACE,
-	[KEY(3, 3)]	= KEY_ENTER,
+	[ADP5520_KEY(0, 0)]	= KEY_GRAVE,
+	[ADP5520_KEY(0, 1)]	= KEY_1,
+	[ADP5520_KEY(0, 2)]	= KEY_2,
+	[ADP5520_KEY(0, 3)]	= KEY_3,
+	[ADP5520_KEY(1, 0)]	= KEY_4,
+	[ADP5520_KEY(1, 1)]	= KEY_5,
+	[ADP5520_KEY(1, 2)]	= KEY_6,
+	[ADP5520_KEY(1, 3)]	= KEY_7,
+	[ADP5520_KEY(2, 0)]	= KEY_8,
+	[ADP5520_KEY(2, 1)]	= KEY_9,
+	[ADP5520_KEY(2, 2)]	= KEY_0,
+	[ADP5520_KEY(2, 3)]	= KEY_MINUS,
+	[ADP5520_KEY(3, 0)]	= KEY_EQUAL,
+	[ADP5520_KEY(3, 1)]	= KEY_BACKSLASH,
+	[ADP5520_KEY(3, 2)]	= KEY_BACKSPACE,
+	[ADP5520_KEY(3, 3)]	= KEY_ENTER,
 };
 
-static struct adp5520_keys_platfrom_data adp5520_keys_data = {
-	.rows_en_mask	= ROW_R3 | ROW_R2 | ROW_R1 | ROW_R0,
-	.cols_en_mask	= COL_C3 | COL_C2 | COL_C1 | COL_C0,
+static struct adp5520_keys_platform_data adp5520_keys_data = {
+	.rows_en_mask	= ADP5520_ROW_R3 | ADP5520_ROW_R2 | ADP5520_ROW_R1 | ADP5520_ROW_R0,
+	.cols_en_mask	= ADP5520_COL_C3 | ADP5520_COL_C2 | ADP5520_COL_C1 | ADP5520_COL_C0,
 	.keymap		= adp5520_keymap,
 	.keymapsize	= ARRAY_SIZE(adp5520_keymap),
 	.repeat		= 0,
@@ -1366,50 +1447,81 @@
 	 *  ADP5520/5501 Multifuction Device Init Data
 	 */
 
-static struct adp5520_subdev_info adp5520_subdevs[] = {
-	{
-		.name = "adp5520-backlight",
-		.id = ID_ADP5520,
-		.platform_data = &adp5520_backlight_data,
-	},
-	{
-		.name = "adp5520-led",
-		.id = ID_ADP5520,
-		.platform_data = &adp5520_leds_data,
-	},
-	{
-		.name = "adp5520-gpio",
-		.id = ID_ADP5520,
-		.platform_data = &adp5520_gpio_data,
-	},
-	{
-		.name = "adp5520-keys",
-		.id = ID_ADP5520,
-		.platform_data = &adp5520_keys_data,
-	},
-};
-
 static struct adp5520_platform_data adp5520_pdev_data = {
-	.num_subdevs = ARRAY_SIZE(adp5520_subdevs),
-	.subdevs = adp5520_subdevs,
+	.backlight = &adp5520_backlight_data,
+	.leds = &adp5520_leds_data,
+	.gpio = &adp5520_gpio_data,
+	.keys = &adp5520_keys_data,
 };
 
 #endif
 
 #if defined(CONFIG_GPIO_ADP5588) || defined(CONFIG_GPIO_ADP5588_MODULE)
 #include <linux/i2c/adp5588.h>
-static struct adp5588_gpio_platfrom_data adp5588_gpio_data = {
+static struct adp5588_gpio_platform_data adp5588_gpio_data = {
 	.gpio_start = 50,
 	.pullup_dis_mask = 0,
 };
 #endif
 
+#if defined(CONFIG_BACKLIGHT_ADP8870) || defined(CONFIG_BACKLIGHT_ADP8870_MODULE)
+#include <linux/i2c/adp8870.h>
+static struct led_info adp8870_leds[] = {
+	{
+		.name = "adp8870-led7",
+		.default_trigger = "none",
+		.flags = ADP8870_LED_D7 | ADP8870_LED_OFFT_600ms,
+	},
+};
+
+
+static struct adp8870_backlight_platform_data adp8870_pdata = {
+	.bl_led_assign = ADP8870_BL_D1 | ADP8870_BL_D2 | ADP8870_BL_D3 |
+			 ADP8870_BL_D4 | ADP8870_BL_D5 | ADP8870_BL_D6,	/* 1 = Backlight 0 = Individual LED */
+	.pwm_assign = 0,				/* 1 = Enables PWM mode */
+
+	.bl_fade_in = ADP8870_FADE_T_1200ms,		/* Backlight Fade-In Timer */
+	.bl_fade_out = ADP8870_FADE_T_1200ms,		/* Backlight Fade-Out Timer */
+	.bl_fade_law = ADP8870_FADE_LAW_CUBIC1,		/* fade-on/fade-off transfer characteristic */
+
+	.en_ambl_sens = 1,				/* 1 = enable ambient light sensor */
+	.abml_filt = ADP8870_BL_AMBL_FILT_320ms,	/* Light sensor filter time */
+
+	.l1_daylight_max = ADP8870_BL_CUR_mA(20),	/* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l1_daylight_dim = ADP8870_BL_CUR_mA(0),	/* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l2_bright_max = ADP8870_BL_CUR_mA(14),		/* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l2_bright_dim = ADP8870_BL_CUR_mA(0),		/* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l3_office_max = ADP8870_BL_CUR_mA(6),		/* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l3_office_dim = ADP8870_BL_CUR_mA(0),		/* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l4_indoor_max = ADP8870_BL_CUR_mA(3),		/* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l4_indor_dim = ADP8870_BL_CUR_mA(0),		/* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l5_dark_max = ADP8870_BL_CUR_mA(2),		/* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+	.l5_dark_dim = ADP8870_BL_CUR_mA(0),		/* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+
+	.l2_trip = ADP8870_L2_COMP_CURR_uA(710),	/* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+	.l2_hyst = ADP8870_L2_COMP_CURR_uA(73),		/* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+	.l3_trip = ADP8870_L3_COMP_CURR_uA(389),	/* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+	.l3_hyst = ADP8870_L3_COMP_CURR_uA(54),		/* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+	.l4_trip = ADP8870_L4_COMP_CURR_uA(167),	/* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+	.l4_hyst = ADP8870_L4_COMP_CURR_uA(16),		/* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+	.l5_trip = ADP8870_L5_COMP_CURR_uA(43),		/* use L5_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+	.l5_hyst = ADP8870_L5_COMP_CURR_uA(11),		/* use L6_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+
+	.leds = adp8870_leds,
+	.num_leds = ARRAY_SIZE(adp8870_leds),
+	.led_fade_law = ADP8870_FADE_LAW_SQUARE,	/* fade-on/fade-off transfer characteristic */
+	.led_fade_in = ADP8870_FADE_T_600ms,
+	.led_fade_out = ADP8870_FADE_T_600ms,
+	.led_on_time = ADP8870_LED_ONT_200ms,
+};
+#endif
+
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_INPUT_EVAL_AD7142EB)
+#if defined(CONFIG_INPUT_AD714X_I2C) || defined(CONFIG_INPUT_AD714X_I2C_MODULE)
 	{
 		I2C_BOARD_INFO("ad7142_captouch", 0x2C),
 		.irq = IRQ_PG5,
-		.platform_data = (void *)&ad7142_platfrom_data,
+		.platform_data = (void *)&ad7142_i2c_platform_data,
 	},
 #endif
 #if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
@@ -1462,6 +1574,32 @@
 		I2C_BOARD_INFO("bfin-adv7393", 0x2B),
 	},
 #endif
+#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE)
+	{
+		I2C_BOARD_INFO("bf537-lq035-ad5280", 0x2C),
+	},
+#endif
+#if defined(CONFIG_BACKLIGHT_ADP8870) || defined(CONFIG_BACKLIGHT_ADP8870_MODULE)
+	{
+		I2C_BOARD_INFO("adp8870", 0x2B),
+		.platform_data = (void *)&adp8870_pdata,
+	},
+#endif
+#if defined(CONFIG_SND_SOC_ADAU1371) || defined(CONFIG_SND_SOC_ADAU1371_MODULE)
+	{
+		I2C_BOARD_INFO("adau1371", 0x1A),
+	},
+#endif
+#if defined(CONFIG_SND_SOC_ADAU1761) || defined(CONFIG_SND_SOC_ADAU1761_MODULE)
+	{
+		I2C_BOARD_INFO("adau1761", 0x38),
+	},
+#endif
+#if defined(CONFIG_AD525X_DPOT) || defined(CONFIG_AD525X_DPOT_MODULE)
+	{
+		I2C_BOARD_INFO("ad5258", 0x18),
+	},
+#endif
 };
 
 #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -1602,8 +1740,8 @@
 	&dm9000_device,
 #endif
 
-#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE)
-	&ax88180_device,
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+	&bfin_can_device,
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h
index 17fab44..8b29141 100644
--- a/arch/blackfin/mach-bf537/include/mach/bf537.h
+++ b/arch/blackfin/mach-bf537/include/mach/bf537.h
@@ -9,16 +9,6 @@
 #ifndef __MACH_BF537_H__
 #define __MACH_BF537_H__
 
-/* Masks for generic ERROR IRQ demultiplexing used in int-priority-sc.c */
-
-#define SPI_ERR_MASK (TXCOL | RBSY | MODF | TXE)	/* SPI_STAT */
-#define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF)	/* SPORTx_STAT */
-#define PPI_ERR_MASK (0xFFFF & ~FLD)	/* PPI_STATUS */
-#define EMAC_ERR_MASK (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE)	/* EMAC_SYSTAT */
-#define UART_ERR_MASK_STAT1 (0x4)	/* UARTx_IIR */
-#define UART_ERR_MASK_STAT0 (0x2)	/* UARTx_IIR */
-#define CAN_ERR_MASK  (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF)	/* CAN_GIF */
-
 #define OFFSET_(x) ((x) & 0x0000FFFF)
 
 /*some misc defines*/
diff --git a/arch/blackfin/mach-bf537/include/mach/blackfin.h b/arch/blackfin/mach-bf537/include/mach/blackfin.h
index eab006d..a12d4b6 100644
--- a/arch/blackfin/mach-bf537/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf537/include/mach/blackfin.h
@@ -40,10 +40,4 @@
 #define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
 #define OFFSET_GCTL             0x24	/* Global Control Register              */
 
-/* PLL_DIV Masks													*/
-#define CCLK_DIV1 CSEL_DIV1	/*          CCLK = VCO / 1                                  */
-#define CCLK_DIV2 CSEL_DIV2	/*          CCLK = VCO / 2                                  */
-#define CCLK_DIV4 CSEL_DIV4	/*          CCLK = VCO / 4                                  */
-#define CCLK_DIV8 CSEL_DIV8	/*          CCLK = VCO / 8                                  */
-
 #endif
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h
index a6d20ca..066d5c2 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h
@@ -958,67 +958,6 @@
 **				modifier UNLESS the lower order bits are saved and ORed back in when
 **				the macro is used.
 *************************************************************************************/
-/*
-** ********************* PLL AND RESET MASKS ****************************************/
-/* PLL_CTL Masks																	*/
-#define DF				0x0001	/* 0: PLL = CLKIN, 1: PLL = CLKIN/2                                     */
-#define PLL_OFF			0x0002	/* PLL Not Powered                                                                      */
-#define STOPCK			0x0008	/* Core Clock Off                                                                       */
-#define PDWN			0x0020	/* Enter Deep Sleep Mode                                                        */
-#define	IN_DELAY		0x0040	/* Add 200ps Delay To EBIU Input Latches                        */
-#define	OUT_DELAY		0x0080	/* Add 200ps Delay To EBIU Output Signals                       */
-#define BYPASS			0x0100	/* Bypass the PLL                                                                       */
-#define	MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors                       */
-/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
-#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL         */
-
-/* PLL_DIV Masks														*/
-#define SSEL			0x000F	/* System Select                                                */
-#define	CSEL			0x0030	/* Core Select                                                  */
-#define CSEL_DIV1		0x0000	/*              CCLK = VCO / 1                                  */
-#define CSEL_DIV2		0x0010	/*              CCLK = VCO / 2                                  */
-#define	CSEL_DIV4		0x0020	/*              CCLK = VCO / 4                                  */
-#define	CSEL_DIV8		0x0030	/*              CCLK = VCO / 8                                  */
-/* PLL_DIV Macros														*/
-#define SET_SSEL(x)		((x)&0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL  */
-
-/* VR_CTL Masks																	*/
-#define	FREQ			0x0003	/* Switching Oscillator Frequency For Regulator */
-#define	HIBERNATE		0x0000	/*              Powerdown/Bypass On-Board Regulation    */
-#define	FREQ_333		0x0001	/*              Switching Frequency Is 333 kHz                  */
-#define	FREQ_667		0x0002	/*              Switching Frequency Is 667 kHz                  */
-#define	FREQ_1000		0x0003	/*              Switching Frequency Is 1 MHz                    */
-
-#define GAIN			0x000C	/* Voltage Level Gain   */
-#define	GAIN_5			0x0000	/*              GAIN = 5                */
-#define	GAIN_10			0x0004	/*              GAIN = 10               */
-#define	GAIN_20			0x0008	/*              GAIN = 20               */
-#define	GAIN_50			0x000C	/*              GAIN = 50               */
-
-#define	VLEV			0x00F0	/* Internal Voltage Level                                       */
-#define	VLEV_085 		0x0060	/*              VLEV = 0.85 V (-5% - +10% Accuracy)     */
-#define	VLEV_090		0x0070	/*              VLEV = 0.90 V (-5% - +10% Accuracy)     */
-#define	VLEV_095		0x0080	/*              VLEV = 0.95 V (-5% - +10% Accuracy)     */
-#define	VLEV_100		0x0090	/*              VLEV = 1.00 V (-5% - +10% Accuracy)     */
-#define	VLEV_105		0x00A0	/*              VLEV = 1.05 V (-5% - +10% Accuracy)     */
-#define	VLEV_110		0x00B0	/*              VLEV = 1.10 V (-5% - +10% Accuracy)     */
-#define	VLEV_115		0x00C0	/*              VLEV = 1.15 V (-5% - +10% Accuracy)     */
-#define	VLEV_120		0x00D0	/*              VLEV = 1.20 V (-5% - +10% Accuracy)     */
-#define	VLEV_125		0x00E0	/*              VLEV = 1.25 V (-5% - +10% Accuracy)     */
-#define	VLEV_130		0x00F0	/*              VLEV = 1.30 V (-5% - +10% Accuracy)     */
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate       */
-#define	CANWE			0x0200	/* Enable CAN Wakeup From Hibernate			*/
-#define	PHYWE			0x0400	/* Enable PHY Wakeup From Hibernate			*/
-#define	CLKBUFOE		0x4000	/* CLKIN Buffer Output Enable */
-#define	PHYCLKOE		CLKBUFOE	/* Alternative legacy name for the above */
-#define	SCKELOW		0x8000	/* Enable Drive CKE Low During Reset		*/
-
-/* PLL_STAT Masks																	*/
-#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled    */
-#define	FULL_ON				0x0002	/* Processor In Full On Mode                                    */
-#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled   */
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached                                 */
 
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
@@ -1645,34 +1584,6 @@
 #define BGSTAT			0x0020	/* Bus Grant Status                                             */
 
 /* **************************  DMA CONTROLLER MASKS  ********************************/
-/* DMAx_CONFIG, MDMA_yy_CONFIG Masks												*/
-#define DMAEN			0x0001	/* DMA Channel Enable                                                   */
-#define WNR				0x0002	/* Channel Direction (W/R*)                                             */
-#define WDSIZE_8		0x0000	/* Transfer Word Size = 8                                               */
-#define WDSIZE_16		0x0004	/* Transfer Word Size = 16                                              */
-#define WDSIZE_32		0x0008	/* Transfer Word Size = 32                                              */
-#define DMA2D			0x0010	/* DMA Mode (2D/1D*)                                                    */
-#define RESTART			0x0020	/* DMA Buffer Clear                                                             */
-#define DI_SEL			0x0040	/* Data Interrupt Timing Select                                 */
-#define DI_EN			0x0080	/* Data Interrupt Enable                                                */
-#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer)   */
-#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1                                             */
-#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2                                             */
-#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3                                             */
-#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4                                             */
-#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5                                             */
-#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6                                             */
-#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7                                             */
-#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8                                             */
-#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9                                             */
-#define NDSIZE	        	0x0900	/* Next Descriptor Size */
-
-#define DMAFLOW	        	0x7000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000	/* Stop Mode */
-#define DMAFLOW_AUTO		0x1000	/* Autobuffer Mode */
-#define DMAFLOW_ARRAY		0x4000	/* Descriptor Array Mode */
-#define DMAFLOW_SMALL		0x6000	/* Small Model Descriptor List Mode */
-#define DMAFLOW_LARGE		0x7000	/* Large Model Descriptor List Mode */
 
 /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks								*/
 #define CTYPE			0x0040	/* DMA Channel Type Indicator (Memory/Peripheral*)      */
@@ -1690,12 +1601,6 @@
 #define	PMAP_UART1RX	0xA000	/*              UART1 Port Receive DMA                                          */
 #define	PMAP_UART1TX	0xB000	/*              UART1 Port Transmit DMA                                         */
 
-/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks						*/
-#define DMA_DONE		0x0001	/* DMA Completion Interrupt Status      */
-#define DMA_ERR			0x0002	/* DMA Error Interrupt Status           */
-#define DFETCH			0x0004	/* DMA Descriptor Fetch Indicator       */
-#define DMA_RUN			0x0008	/* DMA Channel Running Indicator        */
-
 /*  ************  PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
 /*  PPI_CONTROL Masks													*/
 #define PORT_EN			0x0001	/* PPI Port Enable                                      */
diff --git a/arch/blackfin/mach-bf538/Makefile b/arch/blackfin/mach-bf538/Makefile
index 8cd2719..c0be54f 100644
--- a/arch/blackfin/mach-bf538/Makefile
+++ b/arch/blackfin/mach-bf538/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-y := ints-priority.o dma.o
+obj-$(CONFIG_GPIOLIB)	+= ext-gpio.o
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index 14af5c2..c296bb1 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -151,6 +151,44 @@
 #endif
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+unsigned short bfin_can_peripherals[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can_resources[] = {
+	{
+		.start = 0xFFC02A00,
+		.end = 0xFFC02FFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN_RX,
+		.end = IRQ_CAN_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN_TX,
+		.end = IRQ_CAN_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN_ERROR,
+		.end = IRQ_CAN_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can_device = {
+	.name = "bfin_can",
+	.num_resources = ARRAY_SIZE(bfin_can_resources),
+	.resource = bfin_can_resources,
+	.dev = {
+		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+	},
+};
+#endif
+
 /*
  *  USB-LAN EzExtender board
  *  Driver needs to know address, irq and flag pin.
@@ -610,6 +648,10 @@
 #endif
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+	&bfin_can_device,
+#endif
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 	&smc91x_device,
 #endif
diff --git a/arch/blackfin/mach-bf538/ext-gpio.c b/arch/blackfin/mach-bf538/ext-gpio.c
new file mode 100644
index 0000000..180b125
--- /dev/null
+++ b/arch/blackfin/mach-bf538/ext-gpio.c
@@ -0,0 +1,123 @@
+/*
+ * GPIOLIB interface for BF538/9 PORT C, D, and E GPIOs
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+
+#define DEFINE_REG(reg, off) \
+static inline u16 read_##reg(void __iomem *port) \
+	{ return bfin_read16(port + off); } \
+static inline void write_##reg(void __iomem *port, u16 v) \
+	{ bfin_write16(port + off, v); }
+
+DEFINE_REG(PORTIO, 0x00)
+DEFINE_REG(PORTIO_CLEAR, 0x10)
+DEFINE_REG(PORTIO_SET, 0x20)
+DEFINE_REG(PORTIO_DIR, 0x40)
+DEFINE_REG(PORTIO_INEN, 0x50)
+
+static void __iomem *gpio_chip_to_mmr(struct gpio_chip *chip)
+{
+	switch (chip->base) {
+	default: /* not really needed, but keeps gcc happy */
+	case GPIO_PC0: return (void __iomem *)PORTCIO;
+	case GPIO_PD0: return (void __iomem *)PORTDIO;
+	case GPIO_PE0: return (void __iomem *)PORTEIO;
+	}
+}
+
+static int bf538_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+	void __iomem *port = gpio_chip_to_mmr(chip);
+	return !!(read_PORTIO(port) & (1u << gpio));
+}
+
+static void bf538_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+	void __iomem *port = gpio_chip_to_mmr(chip);
+	if (value)
+		write_PORTIO_SET(port, (1u << gpio));
+	else
+		write_PORTIO_CLEAR(port, (1u << gpio));
+}
+
+static int bf538_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+	void __iomem *port = gpio_chip_to_mmr(chip);
+	write_PORTIO_DIR(port, read_PORTIO_DIR(port) & ~(1u << gpio));
+	write_PORTIO_INEN(port, read_PORTIO_INEN(port) | (1u << gpio));
+	return 0;
+}
+
+static int bf538_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+	void __iomem *port = gpio_chip_to_mmr(chip);
+	write_PORTIO_INEN(port, read_PORTIO_INEN(port) & ~(1u << gpio));
+	bf538_gpio_set_value(port, gpio, value);
+	write_PORTIO_DIR(port, read_PORTIO_DIR(port) | (1u << gpio));
+	return 0;
+}
+
+static int bf538_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+	return bfin_special_gpio_request(chip->base + gpio, chip->label);
+}
+
+static void bf538_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+	return bfin_special_gpio_free(chip->base + gpio);
+}
+
+/* We don't set the irq fields as these banks cannot generate interrupts */
+
+static struct gpio_chip bf538_portc_chip = {
+	.label = "GPIO-PC",
+	.direction_input = bf538_gpio_direction_input,
+	.get = bf538_gpio_get_value,
+	.direction_output = bf538_gpio_direction_output,
+	.set = bf538_gpio_set_value,
+	.request = bf538_gpio_request,
+	.free = bf538_gpio_free,
+	.base = GPIO_PC0,
+	.ngpio = GPIO_PC9 - GPIO_PC0 + 1,
+};
+
+static struct gpio_chip bf538_portd_chip = {
+	.label = "GPIO-PD",
+	.direction_input = bf538_gpio_direction_input,
+	.get = bf538_gpio_get_value,
+	.direction_output = bf538_gpio_direction_output,
+	.set = bf538_gpio_set_value,
+	.request = bf538_gpio_request,
+	.free = bf538_gpio_free,
+	.base = GPIO_PD0,
+	.ngpio = GPIO_PD13 - GPIO_PD0 + 1,
+};
+
+static struct gpio_chip bf538_porte_chip = {
+	.label = "GPIO-PE",
+	.direction_input = bf538_gpio_direction_input,
+	.get = bf538_gpio_get_value,
+	.direction_output = bf538_gpio_direction_output,
+	.set = bf538_gpio_set_value,
+	.request = bf538_gpio_request,
+	.free = bf538_gpio_free,
+	.base = GPIO_PE0,
+	.ngpio = GPIO_PE15 - GPIO_PE0 + 1,
+};
+
+static int __init bf538_extgpio_setup(void)
+{
+	return gpiochip_add(&bf538_portc_chip) |
+		gpiochip_add(&bf538_portd_chip) |
+		gpiochip_add(&bf538_porte_chip);
+}
+arch_initcall(bf538_extgpio_setup);
diff --git a/arch/blackfin/mach-bf538/include/mach/blackfin.h b/arch/blackfin/mach-bf538/include/mach/blackfin.h
index 278e894..08b5eab 100644
--- a/arch/blackfin/mach-bf538/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf538/include/mach/blackfin.h
@@ -37,10 +37,4 @@
 #define OFFSET_SCR              0x1C	/* SCR Scratch Register                 */
 #define OFFSET_GCTL             0x24	/* Global Control Register              */
 
-/* PLL_DIV Masks													*/
-#define CCLK_DIV1 CSEL_DIV1	/*          CCLK = VCO / 1                                  */
-#define CCLK_DIV2 CSEL_DIV2	/*          CCLK = VCO / 2                                  */
-#define CCLK_DIV4 CSEL_DIV4	/*          CCLK = VCO / 4                                  */
-#define CCLK_DIV8 CSEL_DIV8	/*          CCLK = VCO / 8                                  */
-
 #endif
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF539.h b/arch/blackfin/mach-bf538/include/mach/defBF539.h
index 5f6c34d..fac563e 100644
--- a/arch/blackfin/mach-bf538/include/mach/defBF539.h
+++ b/arch/blackfin/mach-bf538/include/mach/defBF539.h
@@ -468,31 +468,31 @@
 /* General-Purpose Ports  (0xFFC01500 -	0xFFC015FF)	 */
 
 /* GPIO	Port C Register	Names */
-#define	GPIO_C_CNFG			0xFFC01500	/* GPIO	Pin Port C Configuration Register */
-#define	GPIO_C_D			0xFFC01510	/* GPIO	Pin Port C Data	Register */
-#define	GPIO_C_C			0xFFC01520	/* Clear GPIO Pin Port C Register */
-#define	GPIO_C_S			0xFFC01530	/* Set GPIO Pin	Port C Register */
-#define	GPIO_C_T			0xFFC01540	/* Toggle GPIO Pin Port	C Register */
-#define	GPIO_C_DIR			0xFFC01550	/* GPIO	Pin Port C Direction Register */
-#define	GPIO_C_INEN			0xFFC01560	/* GPIO	Pin Port C Input Enable	Register */
+#define PORTCIO_FER			0xFFC01500	/* GPIO	Pin Port C Configuration Register */
+#define PORTCIO				0xFFC01510	/* GPIO	Pin Port C Data	Register */
+#define PORTCIO_CLEAR			0xFFC01520	/* Clear GPIO Pin Port C Register */
+#define PORTCIO_SET			0xFFC01530	/* Set GPIO Pin	Port C Register */
+#define PORTCIO_TOGGLE			0xFFC01540	/* Toggle GPIO Pin Port	C Register */
+#define PORTCIO_DIR			0xFFC01550	/* GPIO	Pin Port C Direction Register */
+#define PORTCIO_INEN			0xFFC01560	/* GPIO	Pin Port C Input Enable	Register */
 
 /* GPIO	Port D Register	Names */
-#define	GPIO_D_CNFG			0xFFC01504	/* GPIO	Pin Port D Configuration Register */
-#define	GPIO_D_D			0xFFC01514	/* GPIO	Pin Port D Data	Register */
-#define	GPIO_D_C			0xFFC01524	/* Clear GPIO Pin Port D Register */
-#define	GPIO_D_S			0xFFC01534	/* Set GPIO Pin	Port D Register */
-#define	GPIO_D_T			0xFFC01544	/* Toggle GPIO Pin Port	D Register */
-#define	GPIO_D_DIR			0xFFC01554	/* GPIO	Pin Port D Direction Register */
-#define	GPIO_D_INEN			0xFFC01564	/* GPIO	Pin Port D Input Enable	Register */
+#define PORTDIO_FER			0xFFC01504	/* GPIO	Pin Port D Configuration Register */
+#define PORTDIO				0xFFC01514	/* GPIO	Pin Port D Data	Register */
+#define PORTDIO_CLEAR			0xFFC01524	/* Clear GPIO Pin Port D Register */
+#define PORTDIO_SET			0xFFC01534	/* Set GPIO Pin	Port D Register */
+#define PORTDIO_TOGGLE			0xFFC01544	/* Toggle GPIO Pin Port	D Register */
+#define PORTDIO_DIR			0xFFC01554	/* GPIO	Pin Port D Direction Register */
+#define PORTDIO_INEN			0xFFC01564	/* GPIO	Pin Port D Input Enable	Register */
 
 /* GPIO	Port E Register	Names */
-#define	GPIO_E_CNFG			0xFFC01508	/* GPIO	Pin Port E Configuration Register */
-#define	GPIO_E_D			0xFFC01518	/* GPIO	Pin Port E Data	Register */
-#define	GPIO_E_C			0xFFC01528	/* Clear GPIO Pin Port E Register */
-#define	GPIO_E_S			0xFFC01538	/* Set GPIO Pin	Port E Register */
-#define	GPIO_E_T			0xFFC01548	/* Toggle GPIO Pin Port	E Register */
-#define	GPIO_E_DIR			0xFFC01558	/* GPIO	Pin Port E Direction Register */
-#define	GPIO_E_INEN			0xFFC01568	/* GPIO	Pin Port E Input Enable	Register */
+#define PORTEIO_FER			0xFFC01508	/* GPIO	Pin Port E Configuration Register */
+#define PORTEIO				0xFFC01518	/* GPIO	Pin Port E Data	Register */
+#define PORTEIO_CLEAR			0xFFC01528	/* Clear GPIO Pin Port E Register */
+#define PORTEIO_SET			0xFFC01538	/* Set GPIO Pin	Port E Register */
+#define PORTEIO_TOGGLE			0xFFC01548	/* Toggle GPIO Pin Port	E Register */
+#define PORTEIO_DIR			0xFFC01558	/* GPIO	Pin Port E Direction Register */
+#define PORTEIO_INEN			0xFFC01568	/* GPIO	Pin Port E Input Enable	Register */
 
 /* DMA Controller 1 Traffic Control Registers (0xFFC01B00 - 0xFFC01BFF) */
 
@@ -1422,81 +1422,6 @@
 /* System MMR Register Bits and	Macros */
 /******************************************************************************* */
 
-/* ********************* PLL AND RESET MASKS ************************ */
-/* PLL_CTL Masks */
-#define	PLL_CLKIN			0x0000	/* Pass	CLKIN to PLL */
-#define	PLL_CLKIN_DIV2		0x0001	/* Pass	CLKIN/2	to PLL */
-#define	DF					0x0001	 /* 0: PLL = CLKIN, 1: PLL = CLKIN/2 */
-#define	PLL_OFF				0x0002	/* Shut	off PLL	clocks */
-
-#define	STOPCK				0x0008	/* Core	Clock Off		 */
-#define	PDWN				0x0020	/* Put the PLL in a Deep Sleep state */
-#define	IN_DELAY			0x0014	/* EBIU	Input Delay Select */
-#define	OUT_DELAY			0x00C0	/* EBIU	Output Delay Select */
-#define	BYPASS				0x0100	/* Bypass the PLL */
-#define	MSEL			0x7E00	/* Multiplier Select For CCLK/VCO Factors */
-
-/* PLL_CTL Macros				 */
-#ifdef _MISRA_RULES
-#define	SET_MSEL(x)		(((x)&0x3Fu) <<	0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
-#define	SET_OUT_DELAY(x)	(((x)&0x03u) <<	0x6)
-#define	SET_IN_DELAY(x)		((((x)&0x02u) << 0x3) |	(((x)&0x01u) <<	0x2))
-#else
-#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
-#define	SET_OUT_DELAY(x)	(((x)&0x03) << 0x6)
-#define	SET_IN_DELAY(x)		((((x)&0x02) <<	0x3) | (((x)&0x01) << 0x2))
-#endif /* _MISRA_RULES */
-
-/* PLL_DIV Masks */
-#define	SSEL				0x000F	/* System Select */
-#define	CSEL				0x0030	/* Core	Select */
-#define	CSEL_DIV1		0x0000	/*		CCLK = VCO / 1 */
-#define	CSEL_DIV2		0x0010	/*		CCLK = VCO / 2 */
-#define	CSEL_DIV4		0x0020	/*		CCLK = VCO / 4 */
-#define	CSEL_DIV8		0x0030	/*		CCLK = VCO / 8 */
-
-#define	SCLK_DIV(x)			(x)		/* SCLK	= VCO /	x */
-
-/* PLL_DIV Macros							 */
-#ifdef _MISRA_RULES
-#define	SET_SSEL(x)			((x)&0xFu)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
-#else
-#define	SET_SSEL(x)			((x)&0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
-#endif /* _MISRA_RULES */
-
-/* PLL_STAT Masks										 */
-#define	ACTIVE_PLLENABLED	0x0001	/* Processor In	Active Mode With PLL Enabled */
-#define	FULL_ON				0x0002	/* Processor In	Full On	Mode */
-#define	ACTIVE_PLLDISABLED	0x0004	/* Processor In	Active Mode With PLL Disabled */
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been	Reached */
-
-/* VR_CTL Masks										 */
-#define	FREQ			0x0003	/* Switching Oscillator	Frequency For Regulator */
-#define	HIBERNATE		0x0000	/*		Powerdown/Bypass On-Board Regulation */
-#define	FREQ_333		0x0001	/*		Switching Frequency Is 333 kHz */
-#define	FREQ_667		0x0002	/*		Switching Frequency Is 667 kHz */
-#define	FREQ_1000		0x0003	/*		Switching Frequency Is 1 MHz */
-
-#define	GAIN			0x000C	/* Voltage Level Gain */
-#define	GAIN_5			0x0000	/*		GAIN = 5 */
-#define	GAIN_10			0x0004	/*		GAIN = 10 */
-#define	GAIN_20			0x0008	/*		GAIN = 20 */
-#define	GAIN_50			0x000C	/*		GAIN = 50 */
-
-#define	VLEV			0x00F0	/* Internal Voltage Level - Only Program Values	Within Specifications */
-#define	VLEV_100		0x0090	/*	VLEV = 1.00 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_105		0x00A0	/*	VLEV = 1.05 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_110		0x00B0	/*	VLEV = 1.10 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_115		0x00C0	/*	VLEV = 1.15 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_120		0x00D0	/*	VLEV = 1.20 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_125		0x00E0	/*	VLEV = 1.25 V (See Datasheet for Regulator Tolerance) */
-#define	VLEV_130		0x00F0	/*	VLEV = 1.30 V (See Datasheet for Regulator Tolerance) */
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From	Hibernate */
-#define	CANWE			0x0200	/* Enable CAN Wakeup From Hibernate */
-#define	MXVRWE			0x0400	/* Enable MXVR Wakeup From Hibernate */
-#define	SCKELOW			0x8000	/* Do Not Drive	SCKE High During Reset After Hibernate */
-
 /* SWRST Mask */
 #define	SYSTEM_RESET	0x0007	/* Initiates A System Software Reset */
 #define	DOUBLE_FAULT	0x0008	/* Core	Double Fault Causes Reset */
@@ -1609,91 +1534,6 @@
 #endif /* _MISRA_RULES */
 
 
-/* ********* WATCHDOG TIMER MASKS ******************** */
-/* Watchdog Timer WDOG_CTL Register Masks */
-#ifdef _MISRA_RULES
-#define	WDEV(x)			(((x)<<1) & 0x0006u)	/* event generated on roll over */
-#else
-#define	WDEV(x)			(((x)<<1) & 0x0006)	/* event generated on roll over */
-#endif /* _MISRA_RULES */
-#define	WDEV_RESET		0x0000				/* generate reset event	on roll	over */
-#define	WDEV_NMI		0x0002				/* generate NMI	event on roll over */
-#define	WDEV_GPI		0x0004				/* generate GP IRQ on roll over */
-#define	WDEV_NONE		0x0006				/* no event on roll over */
-#define	WDEN			0x0FF0				/* enable watchdog */
-#define	WDDIS			0x0AD0				/* disable watchdog */
-#define	WDRO			0x8000				/* watchdog rolled over	latch */
-
-/* deprecated WDOG_CTL Register	Masks for legacy code */
-#define	ICTL WDEV
-#define	ENABLE_RESET	WDEV_RESET
-#define	WDOG_RESET		WDEV_RESET
-#define	ENABLE_NMI		WDEV_NMI
-#define	WDOG_NMI		WDEV_NMI
-#define	ENABLE_GPI		WDEV_GPI
-#define	WDOG_GPI		WDEV_GPI
-#define	DISABLE_EVT	WDEV_NONE
-#define	WDOG_NONE		WDEV_NONE
-
-#define	TMR_EN			WDEN
-#define	WDOG_DISABLE		WDDIS
-#define	TRO			WDRO
-
-#define	ICTL_P0			0x01
-#define	ICTL_P1			0x02
-#define	TRO_P			0x0F
-
-
-/* ***************  REAL TIME CLOCK MASKS  **************************/
-/* RTC_STAT and	RTC_ALARM register */
-#define	RTSEC		0x0000003F	/* Real-Time Clock Seconds */
-#define	RTMIN		0x00000FC0	/* Real-Time Clock Minutes */
-#define	RTHR		0x0001F000	/* Real-Time Clock Hours */
-#define	RTDAY		0xFFFE0000	/* Real-Time Clock Days */
-
-/* RTC_ICTL register */
-#define	SWIE		0x0001		/* Stopwatch Interrupt Enable */
-#define	AIE			0x0002		/* Alarm Interrupt Enable */
-#define	SIE			0x0004		/* Seconds (1 Hz) Interrupt Enable */
-#define	MIE			0x0008		/* Minutes Interrupt Enable */
-#define	HIE			0x0010		/* Hours Interrupt Enable */
-#define	DIE			0x0020		/* 24 Hours (Days) Interrupt Enable */
-#define	DAIE		0x0040		/* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable */
-#define	WCIE		0x8000		/* Write Complete Interrupt Enable */
-
-/* RTC_ISTAT register */
-#define	SWEF		0x0001		/* Stopwatch Event Flag */
-#define	AEF			0x0002		/* Alarm Event Flag */
-#define	SEF			0x0004		/* Seconds (1 Hz) Event	Flag */
-#define	MEF			0x0008		/* Minutes Event Flag */
-#define	HEF			0x0010		/* Hours Event Flag */
-#define	DEF			0x0020		/* 24 Hours (Days) Event Flag */
-#define	DAEF		0x0040		/* Day Alarm (Day, Hour, Minute, Second) Event Flag */
-#define	WPS			0x4000		/* Write Pending Status	(RO) */
-#define	WCOM		0x8000		/* Write Complete */
-
-/* RTC_FAST Mask (RTC_PREN Mask) */
-#define	ENABLE_PRESCALE	     0x00000001	 /* Enable prescaler so	RTC runs at 1 Hz */
-#define	PREN		     0x00000001
-		/* ** Must be set after	power-up for proper operation of RTC */
-
-/* Deprecated RTC_STAT and RTC_ALARM Masks			 */
-#define	RTC_SEC			RTSEC	/* Real-Time Clock Seconds */
-#define	RTC_MIN			RTMIN	/* Real-Time Clock Minutes */
-#define	RTC_HR			RTHR	/* Real-Time Clock Hours */
-#define	RTC_DAY			RTDAY	/* Real-Time Clock Days */
-
-/* Deprecated RTC_ICTL/RTC_ISTAT Masks											 */
-#define	STOPWATCH		SWIE		/* Stopwatch Interrupt Enable	 */
-#define	ALARM			AIE		/* Alarm Interrupt Enable		 */
-#define	SECOND			SIE		/* Seconds (1 Hz) Interrupt Enable */
-#define	MINUTE			MIE		/* Minutes Interrupt Enable		 */
-#define	HOUR			HIE		/* Hours Interrupt Enable		 */
-#define	DAY				DIE		/* 24 Hours (Days) Interrupt Enable */
-#define	DAY_ALARM		DAIE		/* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable */
-#define	WRITE_COMPLETE	WCIE		/* Write Complete Interrupt Enable */
-
-
 /* ***************************** UART CONTROLLER MASKS ********************** */
 /* UARTx_LCR Register */
 #ifdef _MISRA_RULES
@@ -1917,52 +1757,6 @@
 
 
 /* **********  DMA CONTROLLER MASKS  ***********************/
-/* DMAx_CONFIG,	MDMA_yy_CONFIG Masks */
-#define	DMAEN		0x0001	/* Channel Enable */
-#define	WNR			0x0002	/* Channel Direction (W/R*) */
-#define	WDSIZE_8	0x0000	/* Word	Size 8 bits */
-#define	WDSIZE_16	0x0004	/* Word	Size 16	bits */
-#define	WDSIZE_32	0x0008	/* Word	Size 32	bits */
-#define	DMA2D		0x0010	/* 2D/1D* Mode */
-#define	RESTART		0x0020	/* Restart */
-#define	DI_SEL		0x0040	/* Data	Interrupt Select */
-#define	DI_EN		0x0080	/* Data	Interrupt Enable */
-#define	NDSIZE		0x0900	/* Next	Descriptor Size */
-#define	NDSIZE_0	0x0000	/* Next	Descriptor Size	= 0 (Stop/Autobuffer) */
-#define	NDSIZE_1	0x0100	/* Next	Descriptor Size	= 1 */
-#define	NDSIZE_2	0x0200	/* Next	Descriptor Size	= 2 */
-#define	NDSIZE_3	0x0300	/* Next	Descriptor Size	= 3 */
-#define	NDSIZE_4	0x0400	/* Next	Descriptor Size	= 4 */
-#define	NDSIZE_5	0x0500	/* Next	Descriptor Size	= 5 */
-#define	NDSIZE_6	0x0600	/* Next	Descriptor Size	= 6 */
-#define	NDSIZE_7	0x0700	/* Next	Descriptor Size	= 7 */
-#define	NDSIZE_8	0x0800	/* Next	Descriptor Size	= 8 */
-#define	NDSIZE_9	0x0900	/* Next	Descriptor Size	= 9 */
-
-#define DMAFLOW			0x7000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000	/* Stop Mode */
-#define DMAFLOW_AUTO		0x1000	/* Autobuffer Mode */
-#define DMAFLOW_ARRAY		0x4000	/* Descriptor Array Mode */
-#define DMAFLOW_SMALL		0x6000	/* Small Model Descriptor List Mode */
-#define DMAFLOW_LARGE		0x7000	/* Large Model Descriptor List Mode */
-
-#define	DMAEN_P		0x0		/* Channel Enable */
-#define	WNR_P		0x1		/* Channel Direction (W/R*) */
-#define	DMA2D_P		0x4		/* 2D/1D* Mode */
-#define	RESTART_P	0x5		/* Restart */
-#define	DI_SEL_P	0x6		/* Data	Interrupt Select */
-#define	DI_EN_P		0x7		/* Data	Interrupt Enable */
-
-/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks */
-#define	DMA_DONE	0x0001	/* DMA Done Indicator */
-#define	DMA_ERR		0x0002	/* DMA Error Indicator */
-#define	DFETCH		0x0004	/* Descriptor Fetch Indicator */
-#define	DMA_RUN		0x0008	/* DMA Running Indicator */
-
-#define	DMA_DONE_P	0x0		/* DMA Done Indicator */
-#define	DMA_ERR_P	0x1		/* DMA Error Indicator */
-#define	DFETCH_P	0x2		/* Descriptor Fetch Indicator */
-#define	DMA_RUN_P	0x3		/* DMA Running Indicator */
 
 /* DMAx_PERIPHERAL_MAP,	MDMA_yy_PERIPHERAL_MAP Masks */
 
@@ -2625,1019 +2419,6 @@
 #define	RCV_FULL	0x000C		/*		Receive	FIFO Full (2 Bytes To Read) */
 
 
-/********************************* MXVR	MASKS ****************************************/
-
-/* MXVR_CONFIG Masks */
-
-#define	MXVREN	  0x00000001lu
-#define	MMSM	  0x00000002lu
-#define	ACTIVE	  0x00000004lu
-#define	SDELAY	  0x00000008lu
-#define	NCMRXEN	  0x00000010lu
-#define	RWRRXEN	  0x00000020lu
-#define	MTXEN	  0x00000040lu
-#define	MTXON	  0x00000080lu /*legacy*/
-#define	MTXONB	  0x00000080lu
-#define	EPARITY	  0x00000100lu
-#define	MSB	  0x00001E00lu
-#define	APRXEN	  0x00002000lu
-#define	WAKEUP	  0x00004000lu
-#define	LMECH	  0x00008000lu
-
-#ifdef _MISRA_RULES
-#define	SET_MSB(x)     (((x)&0xFu) << 0x9)
-#else
-#define	SET_MSB(x)     (((x)&0xF) << 0x9)
-#endif /* _MISRA_RULES */
-
-
-/* MXVR_PLL_CTL_0 Masks */
-
-#define	MXTALCEN  0x00000001lu
-#define	MXTALFEN  0x00000002lu
-#define	MPLLMS	  0x00000008lu
-#define	MXTALMUL  0x00000030lu
-#define	MPLLEN	  0x00000040lu
-#define	MPLLEN0	  0x00000040lu /* legacy */
-#define	MPLLEN1	  0x00000080lu /* legacy */
-#define	MMCLKEN	  0x00000100lu
-#define	MMCLKMUL  0x00001E00lu
-#define	MPLLRSTB  0x00002000lu
-#define	MPLLRSTB0 0x00002000lu /* legacy */
-#define	MPLLRSTB1 0x00004000lu /* legacy */
-#define	MBCLKEN	  0x00010000lu
-#define	MBCLKDIV  0x001E0000lu
-#define	MPLLCDR	  0x00200000lu
-#define	MPLLCDR0  0x00200000lu /* legacy */
-#define	MPLLCDR1  0x00400000lu /* legacy */
-#define	INVRX	  0x00800000lu
-#define	MFSEN	  0x01000000lu
-#define	MFSDIV	  0x1E000000lu
-#define	MFSSEL	  0x60000000lu
-#define	MFSSYNC	  0x80000000lu
-
-#define	MXTALMUL_256FS	 0x00000000lu /* legacy */
-#define	MXTALMUL_384FS	 0x00000010lu /* legacy */
-#define	MXTALMUL_512FS	 0x00000020lu /* legacy */
-#define	MXTALMUL_1024FS	 0x00000030lu
-
-#define	MMCLKMUL_1024FS	 0x00000000lu
-#define	MMCLKMUL_512FS	 0x00000200lu
-#define	MMCLKMUL_256FS	 0x00000400lu
-#define	MMCLKMUL_128FS	 0x00000600lu
-#define	MMCLKMUL_64FS	 0x00000800lu
-#define	MMCLKMUL_32FS	 0x00000A00lu
-#define	MMCLKMUL_16FS	 0x00000C00lu
-#define	MMCLKMUL_8FS	 0x00000E00lu
-#define	MMCLKMUL_4FS	 0x00001000lu
-#define	MMCLKMUL_2FS	 0x00001200lu
-#define	MMCLKMUL_1FS	 0x00001400lu
-#define	MMCLKMUL_1536FS	 0x00001A00lu
-#define	MMCLKMUL_768FS	 0x00001C00lu
-#define	MMCLKMUL_384FS	 0x00001E00lu
-
-#define	MBCLKDIV_DIV2	 0x00020000lu
-#define	MBCLKDIV_DIV4	 0x00040000lu
-#define	MBCLKDIV_DIV8	 0x00060000lu
-#define	MBCLKDIV_DIV16	 0x00080000lu
-#define	MBCLKDIV_DIV32	 0x000A0000lu
-#define	MBCLKDIV_DIV64	 0x000C0000lu
-#define	MBCLKDIV_DIV128	 0x000E0000lu
-#define	MBCLKDIV_DIV256	 0x00100000lu
-#define	MBCLKDIV_DIV512	 0x00120000lu
-#define	MBCLKDIV_DIV1024 0x00140000lu
-
-#define	MFSDIV_DIV2	 0x02000000lu
-#define	MFSDIV_DIV4	 0x04000000lu
-#define	MFSDIV_DIV8	 0x06000000lu
-#define	MFSDIV_DIV16	 0x08000000lu
-#define	MFSDIV_DIV32	 0x0A000000lu
-#define	MFSDIV_DIV64	 0x0C000000lu
-#define	MFSDIV_DIV128	 0x0E000000lu
-#define	MFSDIV_DIV256	 0x10000000lu
-#define	MFSDIV_DIV512	 0x12000000lu
-#define	MFSDIV_DIV1024	 0x14000000lu
-
-#define	MFSSEL_CLOCK	 0x00000000lu
-#define	MFSSEL_PULSE_HI	 0x20000000lu
-#define	MFSSEL_PULSE_LO	 0x40000000lu
-
-
-/* MXVR_PLL_CTL_1 Masks */
-
-#define	MSTO	   0x00000001lu
-#define	MSTO0	   0x00000001lu	/* legacy */
-#define	MHOGGD	   0x00000004lu
-#define	MHOGGD0	   0x00000004lu	/* legacy */
-#define	MHOGGD1	   0x00000008lu	/* legacy */
-#define	MSHAPEREN  0x00000010lu
-#define	MSHAPEREN0 0x00000010lu	/* legacy */
-#define	MSHAPEREN1 0x00000020lu	/* legacy */
-#define	MPLLCNTEN  0x00008000lu
-#define	MPLLCNT	   0xFFFF0000lu
-
-#ifdef _MISRA_RULES
-#define	SET_MPLLCNT(x)	   (((x)&0xFFFFu) << 0x10)
-#else
-#define	SET_MPLLCNT(x)	   (((x)&0xFFFF) << 0x10)
-#endif /* _MISRA_RULES */
-
-
-/* MXVR_PLL_CTL_2 Masks */
-
-#define	MSHAPERSEL 0x00000007lu
-#define	MCPSEL	   0x000000E0lu
-
-/* MXVR_INT_STAT_0 Masks */
-
-#define	NI2A  0x00000001lu
-#define	NA2I  0x00000002lu
-#define	SBU2L 0x00000004lu
-#define	SBL2U 0x00000008lu
-#define	PRU   0x00000010lu
-#define	MPRU  0x00000020lu
-#define	DRU   0x00000040lu
-#define	MDRU  0x00000080lu
-#define	SBU   0x00000100lu
-#define	ATU   0x00000200lu
-#define	FCZ0  0x00000400lu
-#define	FCZ1  0x00000800lu
-#define	PERR  0x00001000lu
-#define	MH2L  0x00002000lu
-#define	ML2H  0x00004000lu
-#define	WUP   0x00008000lu
-#define	FU2L  0x00010000lu
-#define	FL2U  0x00020000lu
-#define	BU2L  0x00040000lu
-#define	BL2U  0x00080000lu
-#define	PCZ   0x00400000lu
-#define	FERR  0x00800000lu
-#define	CMR   0x01000000lu
-#define	CMROF 0x02000000lu
-#define	CMTS  0x04000000lu
-#define	CMTC  0x08000000lu
-#define	RWRC  0x10000000lu
-#define	BCZ   0x20000000lu
-#define	BMERR 0x40000000lu
-#define	DERR  0x80000000lu
-
-
-/* MXVR_INT_EN_0 Masks */
-
-#define	NI2AEN	NI2A
-#define	NA2IEN	NA2I
-#define	SBU2LEN	SBU2L
-#define	SBL2UEN	SBL2U
-#define	PRUEN	PRU
-#define	MPRUEN	MPRU
-#define	DRUEN	DRU
-#define	MDRUEN	MDRU
-#define	SBUEN	SBU
-#define	ATUEN	ATU
-#define	FCZ0EN	FCZ0
-#define	FCZ1EN	FCZ1
-#define	PERREN	PERR
-#define	MH2LEN	MH2L
-#define	ML2HEN	ML2H
-#define	WUPEN	WUP
-#define	FU2LEN	FU2L
-#define	FL2UEN	FL2U
-#define	BU2LEN	BU2L
-#define	BL2UEN	BL2U
-#define	PCZEN	PCZ
-#define	FERREN	FERR
-#define	CMREN	CMR
-#define	CMROFEN	CMROF
-#define	CMTSEN	CMTS
-#define	CMTCEN	CMTC
-#define	RWRCEN	RWRC
-#define	BCZEN	BCZ
-#define	BMERREN	BMERR
-#define	DERREN	DERR
-
-
-/* MXVR_INT_STAT_1 Masks */
-
-#define	APR   0x00000004lu
-#define	APROF 0x00000008lu
-#define	APTS  0x00000040lu
-#define	APTC  0x00000080lu
-#define	APRCE 0x00000400lu
-#define	APRPE 0x00000800lu
-
-#define	HDONE0 0x00000001lu
-#define	DONE0  0x00000002lu
-#define	HDONE1 0x00000010lu
-#define	DONE1  0x00000020lu
-#define	HDONE2 0x00000100lu
-#define	DONE2  0x00000200lu
-#define	HDONE3 0x00001000lu
-#define	DONE3  0x00002000lu
-#define	HDONE4 0x00010000lu
-#define	DONE4  0x00020000lu
-#define	HDONE5 0x00100000lu
-#define	DONE5  0x00200000lu
-#define	HDONE6 0x01000000lu
-#define	DONE6  0x02000000lu
-#define	HDONE7 0x10000000lu
-#define	DONE7  0x20000000lu
-
-#define	DONEX(x) (0x00000002 <<	(4 * (x)))
-#define	HDONEX(x) (0x00000001 << (4 * (x)))
-
-
-/* MXVR_INT_EN_1 Masks */
-
-#define	APREN	APR
-#define	APROFEN	APROF
-#define	APTSEN	APTS
-#define	APTCEN	APTC
-#define	APRCEEN	APRCE
-#define	APRPEEN	APRPE
-
-#define	HDONEEN0 HDONE0
-#define	DONEEN0	 DONE0
-#define	HDONEEN1 HDONE1
-#define	DONEEN1	 DONE1
-#define	HDONEEN2 HDONE2
-#define	DONEEN2	 DONE2
-#define	HDONEEN3 HDONE3
-#define	DONEEN3	 DONE3
-#define	HDONEEN4 HDONE4
-#define	DONEEN4	 DONE4
-#define	HDONEEN5 HDONE5
-#define	DONEEN5	 DONE5
-#define	HDONEEN6 HDONE6
-#define	DONEEN6	 DONE6
-#define	HDONEEN7 HDONE7
-#define	DONEEN7	 DONE7
-
-#define	DONEENX(x) (0x00000002 << (4 * (x)))
-#define	HDONEENX(x) (0x00000001	<< (4 *	(x)))
-
-
-/* MXVR_STATE_0	Masks */
-
-#define	NACT	 0x00000001lu
-#define	SBLOCK	 0x00000002lu
-#define	PFDLOCK	 0x00000004lu
-#define	PFDLOCK0 0x00000004lu /* legacy */
-#define	PDD	 0x00000008lu
-#define	PDD0	 0x00000008lu /* legacy */
-#define	PVCO	 0x00000010lu
-#define	PVCO0	 0x00000010lu /* legacy */
-#define	PFDLOCK1 0x00000020lu /* legacy */
-#define	PDD1	 0x00000040lu /* legacy */
-#define	PVCO1	 0x00000080lu /* legacy */
-#define	APBSY	 0x00000100lu
-#define	APARB	 0x00000200lu
-#define	APTX	 0x00000400lu
-#define	APRX	 0x00000800lu
-#define	CMBSY	 0x00001000lu
-#define	CMARB	 0x00002000lu
-#define	CMTX	 0x00004000lu
-#define	CMRX	 0x00008000lu
-#define	MRXONB	 0x00010000lu
-#define	RGSIP	 0x00020000lu
-#define	DALIP	 0x00040000lu
-#define	ALIP	 0x00080000lu
-#define	RRDIP	 0x00100000lu
-#define	RWRIP	 0x00200000lu
-#define	FLOCK	 0x00400000lu
-#define	BLOCK	 0x00800000lu
-#define	RSB	 0x0F000000lu
-#define	DERRNUM	 0xF0000000lu
-
-
-/* MXVR_STATE_1	Masks */
-
-#define	STXNUMB	    0x0000000Flu
-#define	SRXNUMB	    0x000000F0lu
-#define	APCONT	    0x00000100lu
-#define	DMAACTIVEX  0x00FF0000lu
-#define	DMAACTIVE0  0x00010000lu
-#define	DMAACTIVE1  0x00020000lu
-#define	DMAACTIVE2  0x00040000lu
-#define	DMAACTIVE3  0x00080000lu
-#define	DMAACTIVE4  0x00100000lu
-#define	DMAACTIVE5  0x00200000lu
-#define	DMAACTIVE6  0x00400000lu
-#define	DMAACTIVE7  0x00800000lu
-#define	DMAPMENX    0xFF000000lu
-#define	DMAPMEN0    0x01000000lu
-#define	DMAPMEN1    0x02000000lu
-#define	DMAPMEN2    0x04000000lu
-#define	DMAPMEN3    0x08000000lu
-#define	DMAPMEN4    0x10000000lu
-#define	DMAPMEN5    0x20000000lu
-#define	DMAPMEN6    0x40000000lu
-#define	DMAPMEN7    0x80000000lu
-
-
-/* MXVR_POSITION Masks */
-
-#define	PVALID	     0x8000
-#define	POSITION     0x003F
-
-
-/* MXVR_MAX_POSITION Masks */
-
-#define	MPVALID	     0x8000
-#define	MPOSITION    0x003F
-
-
-/* MXVR_DELAY Masks */
-
-#define	DVALID	     0x8000
-#define	DELAY	     0x003F
-
-
-/* MXVR_MAX_DELAY Masks */
-
-#define	MDVALID	     0x8000
-#define	MDELAY	     0x003F
-
-
-/* MXVR_LADDR Masks */
-
-#define	LVALID	     0x80000000lu
-#define	LADDR	     0x0000FFFFlu
-
-
-/* MXVR_GADDR Masks */
-
-#define	GVALID	     0x8000
-#define	GADDRL	     0x00FF
-
-
-/* MXVR_AADDR Masks */
-
-#define	AVALID	     0x80000000lu
-#define	AADDR	     0x0000FFFFlu
-
-
-/* MXVR_ALLOC_0	Masks */
-
-#define	CIU0	     0x00000080lu
-#define	CIU1	     0x00008000lu
-#define	CIU2	     0x00800000lu
-#define	CIU3	     0x80000000lu
-
-#define	CL0	     0x0000007Flu
-#define	CL1	     0x00007F00lu
-#define	CL2	     0x007F0000lu
-#define	CL3	     0x7F000000lu
-
-
-/* MXVR_ALLOC_1	Masks */
-
-#define	CIU4	     0x00000080lu
-#define	CIU5	     0x00008000lu
-#define	CIU6	     0x00800000lu
-#define	CIU7	     0x80000000lu
-
-#define	CL4	     0x0000007Flu
-#define	CL5	     0x00007F00lu
-#define	CL6	     0x007F0000lu
-#define	CL7	     0x7F000000lu
-
-
-/* MXVR_ALLOC_2	Masks */
-
-#define	CIU8	     0x00000080lu
-#define	CIU9	     0x00008000lu
-#define	CIU10	     0x00800000lu
-#define	CIU11	     0x80000000lu
-
-#define	CL8	     0x0000007Flu
-#define	CL9	     0x00007F00lu
-#define	CL10	     0x007F0000lu
-#define	CL11	     0x7F000000lu
-
-
-/* MXVR_ALLOC_3	Masks */
-
-#define	CIU12	     0x00000080lu
-#define	CIU13	     0x00008000lu
-#define	CIU14	     0x00800000lu
-#define	CIU15	     0x80000000lu
-
-#define	CL12	     0x0000007Flu
-#define	CL13	     0x00007F00lu
-#define	CL14	     0x007F0000lu
-#define	CL15	     0x7F000000lu
-
-
-/* MXVR_ALLOC_4	Masks */
-
-#define	CIU16	     0x00000080lu
-#define	CIU17	     0x00008000lu
-#define	CIU18	     0x00800000lu
-#define	CIU19	     0x80000000lu
-
-#define	CL16	     0x0000007Flu
-#define	CL17	     0x00007F00lu
-#define	CL18	     0x007F0000lu
-#define	CL19	     0x7F000000lu
-
-
-/* MXVR_ALLOC_5	Masks */
-
-#define	CIU20	     0x00000080lu
-#define	CIU21	     0x00008000lu
-#define	CIU22	     0x00800000lu
-#define	CIU23	     0x80000000lu
-
-#define	CL20	     0x0000007Flu
-#define	CL21	     0x00007F00lu
-#define	CL22	     0x007F0000lu
-#define	CL23	     0x7F000000lu
-
-
-/* MXVR_ALLOC_6	Masks */
-
-#define	CIU24	     0x00000080lu
-#define	CIU25	     0x00008000lu
-#define	CIU26	     0x00800000lu
-#define	CIU27	     0x80000000lu
-
-#define	CL24	     0x0000007Flu
-#define	CL25	     0x00007F00lu
-#define	CL26	     0x007F0000lu
-#define	CL27	     0x7F000000lu
-
-
-/* MXVR_ALLOC_7	Masks */
-
-#define	CIU28	     0x00000080lu
-#define	CIU29	     0x00008000lu
-#define	CIU30	     0x00800000lu
-#define	CIU31	     0x80000000lu
-
-#define	CL28	     0x0000007Flu
-#define	CL29	     0x00007F00lu
-#define	CL30	     0x007F0000lu
-#define	CL31	     0x7F000000lu
-
-
-/* MXVR_ALLOC_8	Masks */
-
-#define	CIU32	     0x00000080lu
-#define	CIU33	     0x00008000lu
-#define	CIU34	     0x00800000lu
-#define	CIU35	     0x80000000lu
-
-#define	CL32	     0x0000007Flu
-#define	CL33	     0x00007F00lu
-#define	CL34	     0x007F0000lu
-#define	CL35	     0x7F000000lu
-
-
-/* MXVR_ALLOC_9	Masks */
-
-#define	CIU36	     0x00000080lu
-#define	CIU37	     0x00008000lu
-#define	CIU38	     0x00800000lu
-#define	CIU39	     0x80000000lu
-
-#define	CL36	     0x0000007Flu
-#define	CL37	     0x00007F00lu
-#define	CL38	     0x007F0000lu
-#define	CL39	     0x7F000000lu
-
-
-/* MXVR_ALLOC_10 Masks */
-
-#define	CIU40	     0x00000080lu
-#define	CIU41	     0x00008000lu
-#define	CIU42	     0x00800000lu
-#define	CIU43	     0x80000000lu
-
-#define	CL40	     0x0000007Flu
-#define	CL41	     0x00007F00lu
-#define	CL42	     0x007F0000lu
-#define	CL43	     0x7F000000lu
-
-
-/* MXVR_ALLOC_11 Masks */
-
-#define	CIU44	     0x00000080lu
-#define	CIU45	     0x00008000lu
-#define	CIU46	     0x00800000lu
-#define	CIU47	     0x80000000lu
-
-#define	CL44	     0x0000007Flu
-#define	CL45	     0x00007F00lu
-#define	CL46	     0x007F0000lu
-#define	CL47	     0x7F000000lu
-
-
-/* MXVR_ALLOC_12 Masks */
-
-#define	CIU48	     0x00000080lu
-#define	CIU49	     0x00008000lu
-#define	CIU50	     0x00800000lu
-#define	CIU51	     0x80000000lu
-
-#define	CL48	     0x0000007Flu
-#define	CL49	     0x00007F00lu
-#define	CL50	     0x007F0000lu
-#define	CL51	     0x7F000000lu
-
-
-/* MXVR_ALLOC_13 Masks */
-
-#define	CIU52	     0x00000080lu
-#define	CIU53	     0x00008000lu
-#define	CIU54	     0x00800000lu
-#define	CIU55	     0x80000000lu
-
-#define	CL52	     0x0000007Flu
-#define	CL53	     0x00007F00lu
-#define	CL54	     0x007F0000lu
-#define	CL55	     0x7F000000lu
-
-
-/* MXVR_ALLOC_14 Masks */
-
-#define	CIU56	     0x00000080lu
-#define	CIU57	     0x00008000lu
-#define	CIU58	     0x00800000lu
-#define	CIU59	     0x80000000lu
-
-#define	CL56	     0x0000007Flu
-#define	CL57	     0x00007F00lu
-#define	CL58	     0x007F0000lu
-#define	CL59	     0x7F000000lu
-
-
-/* MXVR_SYNC_LCHAN_0 Masks */
-
-#define	LCHANPC0     0x0000000Flu
-#define	LCHANPC1     0x000000F0lu
-#define	LCHANPC2     0x00000F00lu
-#define	LCHANPC3     0x0000F000lu
-#define	LCHANPC4     0x000F0000lu
-#define	LCHANPC5     0x00F00000lu
-#define	LCHANPC6     0x0F000000lu
-#define	LCHANPC7     0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_1 Masks */
-
-#define	LCHANPC8     0x0000000Flu
-#define	LCHANPC9     0x000000F0lu
-#define	LCHANPC10    0x00000F00lu
-#define	LCHANPC11    0x0000F000lu
-#define	LCHANPC12    0x000F0000lu
-#define	LCHANPC13    0x00F00000lu
-#define	LCHANPC14    0x0F000000lu
-#define	LCHANPC15    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_2 Masks */
-
-#define	LCHANPC16    0x0000000Flu
-#define	LCHANPC17    0x000000F0lu
-#define	LCHANPC18    0x00000F00lu
-#define	LCHANPC19    0x0000F000lu
-#define	LCHANPC20    0x000F0000lu
-#define	LCHANPC21    0x00F00000lu
-#define	LCHANPC22    0x0F000000lu
-#define	LCHANPC23    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_3 Masks */
-
-#define	LCHANPC24    0x0000000Flu
-#define	LCHANPC25    0x000000F0lu
-#define	LCHANPC26    0x00000F00lu
-#define	LCHANPC27    0x0000F000lu
-#define	LCHANPC28    0x000F0000lu
-#define	LCHANPC29    0x00F00000lu
-#define	LCHANPC30    0x0F000000lu
-#define	LCHANPC31    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_4 Masks */
-
-#define	LCHANPC32    0x0000000Flu
-#define	LCHANPC33    0x000000F0lu
-#define	LCHANPC34    0x00000F00lu
-#define	LCHANPC35    0x0000F000lu
-#define	LCHANPC36    0x000F0000lu
-#define	LCHANPC37    0x00F00000lu
-#define	LCHANPC38    0x0F000000lu
-#define	LCHANPC39    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_5 Masks */
-
-#define	LCHANPC40    0x0000000Flu
-#define	LCHANPC41    0x000000F0lu
-#define	LCHANPC42    0x00000F00lu
-#define	LCHANPC43    0x0000F000lu
-#define	LCHANPC44    0x000F0000lu
-#define	LCHANPC45    0x00F00000lu
-#define	LCHANPC46    0x0F000000lu
-#define	LCHANPC47    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_6 Masks */
-
-#define	LCHANPC48    0x0000000Flu
-#define	LCHANPC49    0x000000F0lu
-#define	LCHANPC50    0x00000F00lu
-#define	LCHANPC51    0x0000F000lu
-#define	LCHANPC52    0x000F0000lu
-#define	LCHANPC53    0x00F00000lu
-#define	LCHANPC54    0x0F000000lu
-#define	LCHANPC55    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_7 Masks */
-
-#define	LCHANPC56    0x0000000Flu
-#define	LCHANPC57    0x000000F0lu
-#define	LCHANPC58    0x00000F00lu
-#define	LCHANPC59    0x0000F000lu
-
-
-/* MXVR_DMAx_CONFIG Masks */
-
-#define	MDMAEN	    0x00000001lu
-#define	DD	    0x00000002lu
-#define	LCHAN	    0x000003C0lu
-#define	BITSWAPEN   0x00000400lu
-#define	BYSWAPEN    0x00000800lu
-#define	MFLOW	    0x00007000lu
-#define	FIXEDPM	    0x00080000lu
-#define	STARTPAT    0x00300000lu
-#define	STOPPAT	    0x00C00000lu
-#define	COUNTPOS    0x1C000000lu
-
-#define	DD_TX	    0x00000000lu
-#define	DD_RX	    0x00000002lu
-
-#define	LCHAN_0	    0x00000000lu
-#define	LCHAN_1	    0x00000040lu
-#define	LCHAN_2	    0x00000080lu
-#define	LCHAN_3	    0x000000C0lu
-#define	LCHAN_4	    0x00000100lu
-#define	LCHAN_5	    0x00000140lu
-#define	LCHAN_6	    0x00000180lu
-#define	LCHAN_7	    0x000001C0lu
-
-#define	MFLOW_STOP  0x00000000lu
-#define	MFLOW_AUTO  0x00001000lu
-#define	MFLOW_PVC   0x00002000lu
-#define	MFLOW_PSS   0x00003000lu
-#define	MFLOW_PFC   0x00004000lu
-
-#define	STARTPAT_0  0x00000000lu
-#define	STARTPAT_1  0x00100000lu
-
-#define	STOPPAT_0   0x00000000lu
-#define	STOPPAT_1   0x00400000lu
-
-#define	COUNTPOS_0  0x00000000lu
-#define	COUNTPOS_1  0x04000000lu
-#define	COUNTPOS_2  0x08000000lu
-#define	COUNTPOS_3  0x0C000000lu
-#define	COUNTPOS_4  0x10000000lu
-#define	COUNTPOS_5  0x14000000lu
-#define	COUNTPOS_6  0x18000000lu
-#define	COUNTPOS_7  0x1C000000lu
-
-
-/* MXVR_AP_CTL Masks */
-
-#define	STARTAP	   0x00000001lu
-#define	CANCELAP   0x00000002lu
-#define	RESETAP	   0x00000004lu
-#define	APRBE0	   0x00004000lu
-#define	APRBE1	   0x00008000lu
-#define	APRBEX	   0x0000C000lu
-
-
-/* MXVR_CM_CTL Masks */
-
-#define	STARTCM	   0x00000001lu
-#define	CANCELCM   0x00000002lu
-#define	CMRBEX	   0xFFFF0000lu
-#define	CMRBE0	   0x00010000lu
-#define	CMRBE1	   0x00020000lu
-#define	CMRBE2	   0x00040000lu
-#define	CMRBE3	   0x00080000lu
-#define	CMRBE4	   0x00100000lu
-#define	CMRBE5	   0x00200000lu
-#define	CMRBE6	   0x00400000lu
-#define	CMRBE7	   0x00800000lu
-#define	CMRBE8	   0x01000000lu
-#define	CMRBE9	   0x02000000lu
-#define	CMRBE10	   0x04000000lu
-#define	CMRBE11	   0x08000000lu
-#define	CMRBE12	   0x10000000lu
-#define	CMRBE13	   0x20000000lu
-#define	CMRBE14	   0x40000000lu
-#define	CMRBE15	   0x80000000lu
-
-
-/* MXVR_PAT_DATA_x Masks */
-
-#define	MATCH_DATA_0 0x000000FFlu
-#define	MATCH_DATA_1 0x0000FF00lu
-#define	MATCH_DATA_2 0x00FF0000lu
-#define	MATCH_DATA_3 0xFF000000lu
-
-
-
-/* MXVR_PAT_EN_x Masks */
-
-#define	MATCH_EN_0_0 0x00000001lu
-#define	MATCH_EN_0_1 0x00000002lu
-#define	MATCH_EN_0_2 0x00000004lu
-#define	MATCH_EN_0_3 0x00000008lu
-#define	MATCH_EN_0_4 0x00000010lu
-#define	MATCH_EN_0_5 0x00000020lu
-#define	MATCH_EN_0_6 0x00000040lu
-#define	MATCH_EN_0_7 0x00000080lu
-
-#define	MATCH_EN_1_0 0x00000100lu
-#define	MATCH_EN_1_1 0x00000200lu
-#define	MATCH_EN_1_2 0x00000400lu
-#define	MATCH_EN_1_3 0x00000800lu
-#define	MATCH_EN_1_4 0x00001000lu
-#define	MATCH_EN_1_5 0x00002000lu
-#define	MATCH_EN_1_6 0x00004000lu
-#define	MATCH_EN_1_7 0x00008000lu
-
-#define	MATCH_EN_2_0 0x00010000lu
-#define	MATCH_EN_2_1 0x00020000lu
-#define	MATCH_EN_2_2 0x00040000lu
-#define	MATCH_EN_2_3 0x00080000lu
-#define	MATCH_EN_2_4 0x00100000lu
-#define	MATCH_EN_2_5 0x00200000lu
-#define	MATCH_EN_2_6 0x00400000lu
-#define	MATCH_EN_2_7 0x00800000lu
-
-#define	MATCH_EN_3_0 0x01000000lu
-#define	MATCH_EN_3_1 0x02000000lu
-#define	MATCH_EN_3_2 0x04000000lu
-#define	MATCH_EN_3_3 0x08000000lu
-#define	MATCH_EN_3_4 0x10000000lu
-#define	MATCH_EN_3_5 0x20000000lu
-#define	MATCH_EN_3_6 0x40000000lu
-#define	MATCH_EN_3_7 0x80000000lu
-
-
-/* MXVR_ROUTING_0 Masks */
-
-#define	MUTE_CH0	0x00000080lu
-#define	MUTE_CH1	0x00008000lu
-#define	MUTE_CH2	0x00800000lu
-#define	MUTE_CH3	0x80000000lu
-
-#define	TX_CH0		0x0000007Flu
-#define	TX_CH1		0x00007F00lu
-#define	TX_CH2		0x007F0000lu
-#define	TX_CH3		0x7F000000lu
-
-
-/* MXVR_ROUTING_1 Masks */
-
-#define	MUTE_CH4	0x00000080lu
-#define	MUTE_CH5	0x00008000lu
-#define	MUTE_CH6	0x00800000lu
-#define	MUTE_CH7	0x80000000lu
-
-#define	TX_CH4		0x0000007Flu
-#define	TX_CH5		0x00007F00lu
-#define	TX_CH6		0x007F0000lu
-#define	TX_CH7		0x7F000000lu
-
-
-/* MXVR_ROUTING_2 Masks */
-
-#define	MUTE_CH8	0x00000080lu
-#define	MUTE_CH9	0x00008000lu
-#define	MUTE_CH10	0x00800000lu
-#define	MUTE_CH11	0x80000000lu
-
-#define	TX_CH8		0x0000007Flu
-#define	TX_CH9		0x00007F00lu
-#define	TX_CH10		0x007F0000lu
-#define	TX_CH11		0x7F000000lu
-
-/* MXVR_ROUTING_3 Masks */
-
-#define	MUTE_CH12	0x00000080lu
-#define	MUTE_CH13	0x00008000lu
-#define	MUTE_CH14	0x00800000lu
-#define	MUTE_CH15	0x80000000lu
-
-#define	TX_CH12		0x0000007Flu
-#define	TX_CH13		0x00007F00lu
-#define	TX_CH14		0x007F0000lu
-#define	TX_CH15		0x7F000000lu
-
-
-/* MXVR_ROUTING_4 Masks */
-
-#define	MUTE_CH16	0x00000080lu
-#define	MUTE_CH17	0x00008000lu
-#define	MUTE_CH18	0x00800000lu
-#define	MUTE_CH19	0x80000000lu
-
-#define	TX_CH16		0x0000007Flu
-#define	TX_CH17		0x00007F00lu
-#define	TX_CH18		0x007F0000lu
-#define	TX_CH19		0x7F000000lu
-
-
-/* MXVR_ROUTING_5 Masks */
-
-#define	MUTE_CH20	0x00000080lu
-#define	MUTE_CH21	0x00008000lu
-#define	MUTE_CH22	0x00800000lu
-#define	MUTE_CH23	0x80000000lu
-
-#define	TX_CH20		0x0000007Flu
-#define	TX_CH21		0x00007F00lu
-#define	TX_CH22		0x007F0000lu
-#define	TX_CH23		0x7F000000lu
-
-
-/* MXVR_ROUTING_6 Masks */
-
-#define	MUTE_CH24	0x00000080lu
-#define	MUTE_CH25	0x00008000lu
-#define	MUTE_CH26	0x00800000lu
-#define	MUTE_CH27	0x80000000lu
-
-#define	TX_CH24		0x0000007Flu
-#define	TX_CH25		0x00007F00lu
-#define	TX_CH26		0x007F0000lu
-#define	TX_CH27		0x7F000000lu
-
-
-/* MXVR_ROUTING_7 Masks */
-
-#define	MUTE_CH28	0x00000080lu
-#define	MUTE_CH29	0x00008000lu
-#define	MUTE_CH30	0x00800000lu
-#define	MUTE_CH31	0x80000000lu
-
-#define	TX_CH28		0x0000007Flu
-#define	TX_CH29		0x00007F00lu
-#define	TX_CH30		0x007F0000lu
-#define	TX_CH31		0x7F000000lu
-
-
-/* MXVR_ROUTING_8 Masks */
-
-#define	MUTE_CH32	0x00000080lu
-#define	MUTE_CH33	0x00008000lu
-#define	MUTE_CH34	0x00800000lu
-#define	MUTE_CH35	0x80000000lu
-
-#define	TX_CH32		0x0000007Flu
-#define	TX_CH33		0x00007F00lu
-#define	TX_CH34		0x007F0000lu
-#define	TX_CH35		0x7F000000lu
-
-
-/* MXVR_ROUTING_9 Masks */
-
-#define	MUTE_CH36	0x00000080lu
-#define	MUTE_CH37	0x00008000lu
-#define	MUTE_CH38	0x00800000lu
-#define	MUTE_CH39	0x80000000lu
-
-#define	TX_CH36		0x0000007Flu
-#define	TX_CH37		0x00007F00lu
-#define	TX_CH38		0x007F0000lu
-#define	TX_CH39		0x7F000000lu
-
-
-/* MXVR_ROUTING_10 Masks */
-
-#define	MUTE_CH40	0x00000080lu
-#define	MUTE_CH41	0x00008000lu
-#define	MUTE_CH42	0x00800000lu
-#define	MUTE_CH43	0x80000000lu
-
-#define	TX_CH40		0x0000007Flu
-#define	TX_CH41		0x00007F00lu
-#define	TX_CH42		0x007F0000lu
-#define	TX_CH43		0x7F000000lu
-
-
-/* MXVR_ROUTING_11 Masks */
-
-#define	MUTE_CH44	0x00000080lu
-#define	MUTE_CH45	0x00008000lu
-#define	MUTE_CH46	0x00800000lu
-#define	MUTE_CH47	0x80000000lu
-
-#define	TX_CH44		0x0000007Flu
-#define	TX_CH45		0x00007F00lu
-#define	TX_CH46		0x007F0000lu
-#define	TX_CH47		0x7F000000lu
-
-
-/* MXVR_ROUTING_12 Masks */
-
-#define	MUTE_CH48	0x00000080lu
-#define	MUTE_CH49	0x00008000lu
-#define	MUTE_CH50	0x00800000lu
-#define	MUTE_CH51	0x80000000lu
-
-#define	TX_CH48		0x0000007Flu
-#define	TX_CH49		0x00007F00lu
-#define	TX_CH50		0x007F0000lu
-#define	TX_CH51		0x7F000000lu
-
-
-/* MXVR_ROUTING_13 Masks */
-
-#define	MUTE_CH52	0x00000080lu
-#define	MUTE_CH53	0x00008000lu
-#define	MUTE_CH54	0x00800000lu
-#define	MUTE_CH55	0x80000000lu
-
-#define	TX_CH52		0x0000007Flu
-#define	TX_CH53		0x00007F00lu
-#define	TX_CH54		0x007F0000lu
-#define	TX_CH55		0x7F000000lu
-
-
-/* MXVR_ROUTING_14 Masks */
-
-#define	MUTE_CH56	0x00000080lu
-#define	MUTE_CH57	0x00008000lu
-#define	MUTE_CH58	0x00800000lu
-#define	MUTE_CH59	0x80000000lu
-
-#define	TX_CH56		0x0000007Flu
-#define	TX_CH57		0x00007F00lu
-#define	TX_CH58		0x007F0000lu
-#define	TX_CH59		0x7F000000lu
-
-
-/* Control Message Receive Buffer (CMRB) Address Offsets */
-
-#define	CMRB_STRIDE	  0x00000016lu
-
-#define	CMRB_DST_OFFSET	  0x00000000lu
-#define	CMRB_SRC_OFFSET	  0x00000002lu
-#define	CMRB_DATA_OFFSET  0x00000005lu
-
-
-/* Control Message Transmit Buffer (CMTB) Address Offsets */
-
-#define	CMTB_PRIO_OFFSET    0x00000000lu
-#define	CMTB_DST_OFFSET	    0x00000002lu
-#define	CMTB_SRC_OFFSET	    0x00000004lu
-#define	CMTB_TYPE_OFFSET    0x00000006lu
-#define	CMTB_DATA_OFFSET    0x00000007lu
-
-#define	CMTB_ANSWER_OFFSET  0x0000000Alu
-
-#define	CMTB_STAT_N_OFFSET  0x00000018lu
-#define	CMTB_STAT_A_OFFSET  0x00000016lu
-#define	CMTB_STAT_D_OFFSET  0x0000000Elu
-#define	CMTB_STAT_R_OFFSET  0x00000014lu
-#define	CMTB_STAT_W_OFFSET  0x00000014lu
-#define	CMTB_STAT_G_OFFSET  0x00000014lu
-
-
-/* Asynchronous	Packet Receive Buffer (APRB) Address Offsets */
-
-#define	APRB_STRIDE	  0x00000400lu
-
-#define	APRB_DST_OFFSET	  0x00000000lu
-#define	APRB_LEN_OFFSET	  0x00000002lu
-#define	APRB_SRC_OFFSET	  0x00000004lu
-#define	APRB_DATA_OFFSET  0x00000006lu
-
-
-/* Asynchronous	Packet Transmit	Buffer (APTB) Address Offsets */
-
-#define	APTB_PRIO_OFFSET  0x00000000lu
-#define	APTB_DST_OFFSET	  0x00000002lu
-#define	APTB_LEN_OFFSET	  0x00000004lu
-#define	APTB_SRC_OFFSET	  0x00000006lu
-#define	APTB_DATA_OFFSET  0x00000008lu
-
-
-/* Remote Read Buffer (RRDB) Address Offsets */
-
-#define	RRDB_WADDR_OFFSET 0x00000100lu
-#define	RRDB_WLEN_OFFSET  0x00000101lu
-
-
-
 /* ************	 CONTROLLER AREA NETWORK (CAN) MASKS  ***************/
 /* CAN_CONTROL Masks					 */
 #define	SRS			0x0001	/* Software Reset */
diff --git a/arch/blackfin/mach-bf538/include/mach/gpio.h b/arch/blackfin/mach-bf538/include/mach/gpio.h
index 295c78a..0c346fb 100644
--- a/arch/blackfin/mach-bf538/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf538/include/mach/gpio.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Analog Devices Inc.
+ * Copyright (C) 2008-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
 
@@ -7,11 +7,8 @@
 #ifndef _MACH_GPIO_H_
 #define _MACH_GPIO_H_
 
-	/* FIXME:
-	 * For now only support PORTF GPIOs.
-	 * PORT C,D and E are for peripheral usage only
-	 */
 #define MAX_BLACKFIN_GPIOS 16
+#define BFIN_SPECIAL_GPIO_BANKS 3
 
 #define	GPIO_PF0	0	/* PF */
 #define	GPIO_PF1	1
diff --git a/arch/blackfin/mach-bf538/include/mach/portmux.h b/arch/blackfin/mach-bf538/include/mach/portmux.h
index 6121cf8..0083ba1 100644
--- a/arch/blackfin/mach-bf538/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf538/include/mach/portmux.h
@@ -7,7 +7,7 @@
 #ifndef _MACH_PORTMUX_H_
 #define _MACH_PORTMUX_H_
 
-#define MAX_RESOURCES	MAX_BLACKFIN_GPIOS
+#define MAX_RESOURCES	64
 
 #define P_TMR2		(P_DONTCARE)
 #define P_TMR1		(P_DONTCARE)
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
index a09623d..70189a0 100644
--- a/arch/blackfin/mach-bf548/Kconfig
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -1,3 +1,27 @@
+config BF542
+	def_bool y
+	depends on BF542_std || BF542M
+config BF544
+	def_bool y
+	depends on BF544_std || BF544M
+config BF547
+	def_bool y
+	depends on BF547_std || BF547M
+config BF548
+	def_bool y
+	depends on BF548_std || BF548M
+config BF549
+	def_bool y
+	depends on BF549_std || BF549M
+
+config BF54xM
+	def_bool y
+	depends on (BF542M || BF544M || BF547M || BF548M || BF549M)
+
+config BF54x
+	def_bool y
+	depends on (BF542 || BF544 || BF547 || BF548 || BF549)
+
 if (BF54x)
 
 source "arch/blackfin/mach-bf548/boards/Kconfig"
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 1a5286b..60193f7 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -62,7 +62,7 @@
 };
 
 static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
+	.name           = "isp1760",
 	.id             = 0,
 	.dev = {
 		.platform_data = &isp1760_priv,
@@ -154,7 +154,7 @@
 };
 #endif
 
-#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
 #include <asm/bfin_rotary.h>
 
 static struct bfin_rotary_platform_data bfin_rotary_data = {
@@ -186,7 +186,7 @@
 #endif
 
 #if defined(CONFIG_INPUT_ADXL34X) || defined(CONFIG_INPUT_ADXL34X_MODULE)
-#include <linux/spi/adxl34x.h>
+#include <linux/input/adxl34x.h>
 static const struct adxl34x_platform_data adxl34x_info = {
 	.x_axis_offset = 0,
 	.y_axis_offset = 0,
@@ -210,14 +210,17 @@
 	.ev_code_y = ABS_Y,		/* EV_REL */
 	.ev_code_z = ABS_Z,		/* EV_REL */
 
-	.ev_code_tap_x = BTN_TOUCH,		/* EV_KEY */
-	.ev_code_tap_y = BTN_TOUCH,		/* EV_KEY */
-	.ev_code_tap_z = BTN_TOUCH,		/* EV_KEY */
+	.ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY x,y,z */
 
 /*	.ev_code_ff = KEY_F,*/		/* EV_KEY */
 /*	.ev_code_act_inactivity = KEY_A,*/	/* EV_KEY */
 	.power_mode = ADXL_AUTO_SLEEP | ADXL_LINK,
 	.fifo_mode = ADXL_FIFO_STREAM,
+	.orientation_enable = ADXL_EN_ORIENTATION_3D,
+	.deadzone_angle = ADXL_DEADZONE_ANGLE_10p8,
+	.divisor_length = ADXL_LP_FILTER_DIVISOR_16,
+	/* EV_KEY {+Z, +Y, +X, -X, -Y, -Z} */
+	.ev_codes_orient_3d = {BTN_Z, BTN_Y, BTN_X, BTN_A, BTN_B, BTN_C},
 };
 #endif
 
@@ -461,6 +464,44 @@
 };
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+unsigned short bfin_can_peripherals[] = {
+	P_CAN0_RX, P_CAN0_TX, 0
+};
+
+static struct resource bfin_can_resources[] = {
+	{
+		.start = 0xFFC02A00,
+		.end = 0xFFC02FFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN0_RX,
+		.end = IRQ_CAN0_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN0_TX,
+		.end = IRQ_CAN0_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN0_ERROR,
+		.end = IRQ_CAN0_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can_device = {
+	.name = "bfin_can",
+	.num_resources = ARRAY_SIZE(bfin_can_resources),
+	.resource = bfin_can_resources,
+	.dev = {
+		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+	},
+};
+#endif
+
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
 static struct resource bfin_atapi_resources[] = {
 	{
@@ -953,6 +994,10 @@
 	&bfin_isp1760_device,
 #endif
 
+#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
+	&bfin_can_device,
+#endif
+
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
 	&bfin_atapi_device,
 #endif
@@ -974,7 +1019,7 @@
 	&bf54x_kpad_device,
 #endif
 
-#if defined(CONFIG_JOYSTICK_BFIN_ROTARY) || defined(CONFIG_JOYSTICK_BFIN_ROTARY_MODULE)
+#if defined(CONFIG_INPUT_BFIN_ROTARY) || defined(CONFIG_INPUT_BFIN_ROTARY_MODULE)
 	&bfin_rotary_device,
 #endif
 
diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h
index 7bead5c..751e5e1 100644
--- a/arch/blackfin/mach-bf548/include/mach/bf548.h
+++ b/arch/blackfin/mach-bf548/include/mach/bf548.h
@@ -81,18 +81,6 @@
 
 #define AMGCTLVAL	(V_AMBEN | V_AMCKEN)
 
-#if defined(CONFIG_BF542M)
-# define CONFIG_BF542
-#elif defined(CONFIG_BF544M)
-# define CONFIG_BF544
-#elif defined(CONFIG_BF547M)
-# define CONFIG_BF547
-#elif defined(CONFIG_BF548M)
-# define CONFIG_BF548
-#elif defined(CONFIG_BF549M)
-# define CONFIG_BF549
-#endif
-
 #if defined(CONFIG_BF542)
 # define CPU   "BF542"
 # define CPUID 0x27de
diff --git a/arch/blackfin/mach-bf548/include/mach/blackfin.h b/arch/blackfin/mach-bf548/include/mach/blackfin.h
index 13302b6..5684030 100644
--- a/arch/blackfin/mach-bf548/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf548/include/mach/blackfin.h
@@ -64,10 +64,4 @@
 #define OFFSET_THR              0x28	/* Transmit Holding register            */
 #define OFFSET_RBR              0x2C	/* Receive Buffer register              */
 
-/* PLL_DIV Masks */
-#define CCLK_DIV1 CSEL_DIV1	/* CCLK = VCO / 1 */
-#define CCLK_DIV2 CSEL_DIV2	/* CCLK = VCO / 2 */
-#define CCLK_DIV4 CSEL_DIV4	/* CCLK = VCO / 4 */
-#define CCLK_DIV8 CSEL_DIV8	/* CCLK = VCO / 8 */
-
 #endif
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF547.h b/arch/blackfin/mach-bf548/include/mach/cdefBF547.h
index 4234215..bc650e6 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF547.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF547.h
@@ -4,21 +4,21 @@
  * Licensed under the GPL-2 or later.
  */
 
-#ifndef _CDEF_BF548_H
-#define _CDEF_BF548_H
+#ifndef _CDEF_BF547_H
+#define _CDEF_BF547_H
 
 /* include all Core registers and bit definitions */
-#include "defBF548.h"
+#include "defBF547.h"
 
 /* include core sbfin_read_()ecific register pointer definitions */
 #include <asm/cdef_LPBlackfin.h>
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF547 */
 
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
+/* The following are the #defines needed by ADSP-BF547 that are not in the common header */
 
 /* Timer Registers */
 
@@ -805,4 +805,4 @@
 #define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
 #define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
 
-#endif /* _CDEF_BF548_H */
+#endif /* _CDEF_BF547_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF548.h b/arch/blackfin/mach-bf548/include/mach/cdefBF548.h
index df84180..3523e08 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF548.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF548.h
@@ -18,165 +18,8 @@
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
-
-/* Timer Registers */
-
-#define bfin_read_TIMER8_CONFIG()	bfin_read16(TIMER8_CONFIG)
-#define bfin_write_TIMER8_CONFIG(val)	bfin_write16(TIMER8_CONFIG, val)
-#define bfin_read_TIMER8_COUNTER()	bfin_read32(TIMER8_COUNTER)
-#define bfin_write_TIMER8_COUNTER(val)	bfin_write32(TIMER8_COUNTER, val)
-#define bfin_read_TIMER8_PERIOD()	bfin_read32(TIMER8_PERIOD)
-#define bfin_write_TIMER8_PERIOD(val)	bfin_write32(TIMER8_PERIOD, val)
-#define bfin_read_TIMER8_WIDTH()	bfin_read32(TIMER8_WIDTH)
-#define bfin_write_TIMER8_WIDTH(val)	bfin_write32(TIMER8_WIDTH, val)
-#define bfin_read_TIMER9_CONFIG()	bfin_read16(TIMER9_CONFIG)
-#define bfin_write_TIMER9_CONFIG(val)	bfin_write16(TIMER9_CONFIG, val)
-#define bfin_read_TIMER9_COUNTER()	bfin_read32(TIMER9_COUNTER)
-#define bfin_write_TIMER9_COUNTER(val)	bfin_write32(TIMER9_COUNTER, val)
-#define bfin_read_TIMER9_PERIOD()	bfin_read32(TIMER9_PERIOD)
-#define bfin_write_TIMER9_PERIOD(val)	bfin_write32(TIMER9_PERIOD, val)
-#define bfin_read_TIMER9_WIDTH()	bfin_read32(TIMER9_WIDTH)
-#define bfin_write_TIMER9_WIDTH(val)	bfin_write32(TIMER9_WIDTH, val)
-#define bfin_read_TIMER10_CONFIG()	bfin_read16(TIMER10_CONFIG)
-#define bfin_write_TIMER10_CONFIG(val)	bfin_write16(TIMER10_CONFIG, val)
-#define bfin_read_TIMER10_COUNTER()	bfin_read32(TIMER10_COUNTER)
-#define bfin_write_TIMER10_COUNTER(val)	bfin_write32(TIMER10_COUNTER, val)
-#define bfin_read_TIMER10_PERIOD()	bfin_read32(TIMER10_PERIOD)
-#define bfin_write_TIMER10_PERIOD(val)	bfin_write32(TIMER10_PERIOD, val)
-#define bfin_read_TIMER10_WIDTH()	bfin_read32(TIMER10_WIDTH)
-#define bfin_write_TIMER10_WIDTH(val)	bfin_write32(TIMER10_WIDTH, val)
-
-/* Timer Groubfin_read_() of 3 */
-
-#define bfin_read_TIMER_ENABLE1()	bfin_read16(TIMER_ENABLE1)
-#define bfin_write_TIMER_ENABLE1(val)	bfin_write16(TIMER_ENABLE1, val)
-#define bfin_read_TIMER_DISABLE1()	bfin_read16(TIMER_DISABLE1)
-#define bfin_write_TIMER_DISABLE1(val)	bfin_write16(TIMER_DISABLE1, val)
-#define bfin_read_TIMER_STATUS1()	bfin_read32(TIMER_STATUS1)
-#define bfin_write_TIMER_STATUS1(val)	bfin_write32(TIMER_STATUS1, val)
-
-/* SPORT0 Registers */
-
-#define bfin_read_SPORT0_TCR1()		bfin_read16(SPORT0_TCR1)
-#define bfin_write_SPORT0_TCR1(val)	bfin_write16(SPORT0_TCR1, val)
-#define bfin_read_SPORT0_TCR2()		bfin_read16(SPORT0_TCR2)
-#define bfin_write_SPORT0_TCR2(val)	bfin_write16(SPORT0_TCR2, val)
-#define bfin_read_SPORT0_TCLKDIV()	bfin_read16(SPORT0_TCLKDIV)
-#define bfin_write_SPORT0_TCLKDIV(val)	bfin_write16(SPORT0_TCLKDIV, val)
-#define bfin_read_SPORT0_TFSDIV()	bfin_read16(SPORT0_TFSDIV)
-#define bfin_write_SPORT0_TFSDIV(val)	bfin_write16(SPORT0_TFSDIV, val)
-#define bfin_read_SPORT0_TX()		bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX(val)	bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX()		bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX(val)	bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_RCR1()		bfin_read16(SPORT0_RCR1)
-#define bfin_write_SPORT0_RCR1(val)	bfin_write16(SPORT0_RCR1, val)
-#define bfin_read_SPORT0_RCR2()		bfin_read16(SPORT0_RCR2)
-#define bfin_write_SPORT0_RCR2(val)	bfin_write16(SPORT0_RCR2, val)
-#define bfin_read_SPORT0_RCLKDIV()	bfin_read16(SPORT0_RCLKDIV)
-#define bfin_write_SPORT0_RCLKDIV(val)	bfin_write16(SPORT0_RCLKDIV, val)
-#define bfin_read_SPORT0_RFSDIV()	bfin_read16(SPORT0_RFSDIV)
-#define bfin_write_SPORT0_RFSDIV(val)	bfin_write16(SPORT0_RFSDIV, val)
-#define bfin_read_SPORT0_STAT()		bfin_read16(SPORT0_STAT)
-#define bfin_write_SPORT0_STAT(val)	bfin_write16(SPORT0_STAT, val)
-#define bfin_read_SPORT0_CHNL()		bfin_read16(SPORT0_CHNL)
-#define bfin_write_SPORT0_CHNL(val)	bfin_write16(SPORT0_CHNL, val)
-#define bfin_read_SPORT0_MCMC1()	bfin_read16(SPORT0_MCMC1)
-#define bfin_write_SPORT0_MCMC1(val)	bfin_write16(SPORT0_MCMC1, val)
-#define bfin_read_SPORT0_MCMC2()	bfin_read16(SPORT0_MCMC2)
-#define bfin_write_SPORT0_MCMC2(val)	bfin_write16(SPORT0_MCMC2, val)
-#define bfin_read_SPORT0_MTCS0()	bfin_read32(SPORT0_MTCS0)
-#define bfin_write_SPORT0_MTCS0(val)	bfin_write32(SPORT0_MTCS0, val)
-#define bfin_read_SPORT0_MTCS1()	bfin_read32(SPORT0_MTCS1)
-#define bfin_write_SPORT0_MTCS1(val)	bfin_write32(SPORT0_MTCS1, val)
-#define bfin_read_SPORT0_MTCS2()	bfin_read32(SPORT0_MTCS2)
-#define bfin_write_SPORT0_MTCS2(val)	bfin_write32(SPORT0_MTCS2, val)
-#define bfin_read_SPORT0_MTCS3()	bfin_read32(SPORT0_MTCS3)
-#define bfin_write_SPORT0_MTCS3(val)	bfin_write32(SPORT0_MTCS3, val)
-#define bfin_read_SPORT0_MRCS0()	bfin_read32(SPORT0_MRCS0)
-#define bfin_write_SPORT0_MRCS0(val)	bfin_write32(SPORT0_MRCS0, val)
-#define bfin_read_SPORT0_MRCS1()	bfin_read32(SPORT0_MRCS1)
-#define bfin_write_SPORT0_MRCS1(val)	bfin_write32(SPORT0_MRCS1, val)
-#define bfin_read_SPORT0_MRCS2()	bfin_read32(SPORT0_MRCS2)
-#define bfin_write_SPORT0_MRCS2(val)	bfin_write32(SPORT0_MRCS2, val)
-#define bfin_read_SPORT0_MRCS3()	bfin_read32(SPORT0_MRCS3)
-#define bfin_write_SPORT0_MRCS3(val)	bfin_write32(SPORT0_MRCS3, val)
-
-/* EPPI0 Registers */
-
-#define bfin_read_EPPI0_STATUS()	bfin_read16(EPPI0_STATUS)
-#define bfin_write_EPPI0_STATUS(val)	bfin_write16(EPPI0_STATUS, val)
-#define bfin_read_EPPI0_HCOUNT()	bfin_read16(EPPI0_HCOUNT)
-#define bfin_write_EPPI0_HCOUNT(val)	bfin_write16(EPPI0_HCOUNT, val)
-#define bfin_read_EPPI0_HDELAY()	bfin_read16(EPPI0_HDELAY)
-#define bfin_write_EPPI0_HDELAY(val)	bfin_write16(EPPI0_HDELAY, val)
-#define bfin_read_EPPI0_VCOUNT()	bfin_read16(EPPI0_VCOUNT)
-#define bfin_write_EPPI0_VCOUNT(val)	bfin_write16(EPPI0_VCOUNT, val)
-#define bfin_read_EPPI0_VDELAY()	bfin_read16(EPPI0_VDELAY)
-#define bfin_write_EPPI0_VDELAY(val)	bfin_write16(EPPI0_VDELAY, val)
-#define bfin_read_EPPI0_FRAME()		bfin_read16(EPPI0_FRAME)
-#define bfin_write_EPPI0_FRAME(val)	bfin_write16(EPPI0_FRAME, val)
-#define bfin_read_EPPI0_LINE()		bfin_read16(EPPI0_LINE)
-#define bfin_write_EPPI0_LINE(val)	bfin_write16(EPPI0_LINE, val)
-#define bfin_read_EPPI0_CLKDIV()	bfin_read16(EPPI0_CLKDIV)
-#define bfin_write_EPPI0_CLKDIV(val)	bfin_write16(EPPI0_CLKDIV, val)
-#define bfin_read_EPPI0_CONTROL()	bfin_read32(EPPI0_CONTROL)
-#define bfin_write_EPPI0_CONTROL(val)	bfin_write32(EPPI0_CONTROL, val)
-#define bfin_read_EPPI0_FS1W_HBL()	bfin_read32(EPPI0_FS1W_HBL)
-#define bfin_write_EPPI0_FS1W_HBL(val)	bfin_write32(EPPI0_FS1W_HBL, val)
-#define bfin_read_EPPI0_FS1P_AVPL()	bfin_read32(EPPI0_FS1P_AVPL)
-#define bfin_write_EPPI0_FS1P_AVPL(val)	bfin_write32(EPPI0_FS1P_AVPL, val)
-#define bfin_read_EPPI0_FS2W_LVB()	bfin_read32(EPPI0_FS2W_LVB)
-#define bfin_write_EPPI0_FS2W_LVB(val)	bfin_write32(EPPI0_FS2W_LVB, val)
-#define bfin_read_EPPI0_FS2P_LAVF()	bfin_read32(EPPI0_FS2P_LAVF)
-#define bfin_write_EPPI0_FS2P_LAVF(val)	bfin_write32(EPPI0_FS2P_LAVF, val)
-#define bfin_read_EPPI0_CLIP()		bfin_read32(EPPI0_CLIP)
-#define bfin_write_EPPI0_CLIP(val)	bfin_write32(EPPI0_CLIP, val)
-
-/* UART2 Registers */
-
-#define bfin_read_UART2_DLL()		bfin_read16(UART2_DLL)
-#define bfin_write_UART2_DLL(val)	bfin_write16(UART2_DLL, val)
-#define bfin_read_UART2_DLH()		bfin_read16(UART2_DLH)
-#define bfin_write_UART2_DLH(val)	bfin_write16(UART2_DLH, val)
-#define bfin_read_UART2_GCTL()		bfin_read16(UART2_GCTL)
-#define bfin_write_UART2_GCTL(val)	bfin_write16(UART2_GCTL, val)
-#define bfin_read_UART2_LCR()		bfin_read16(UART2_LCR)
-#define bfin_write_UART2_LCR(val)	bfin_write16(UART2_LCR, val)
-#define bfin_read_UART2_MCR()		bfin_read16(UART2_MCR)
-#define bfin_write_UART2_MCR(val)	bfin_write16(UART2_MCR, val)
-#define bfin_read_UART2_LSR()		bfin_read16(UART2_LSR)
-#define bfin_write_UART2_LSR(val)	bfin_write16(UART2_LSR, val)
-#define bfin_read_UART2_MSR()		bfin_read16(UART2_MSR)
-#define bfin_write_UART2_MSR(val)	bfin_write16(UART2_MSR, val)
-#define bfin_read_UART2_SCR()		bfin_read16(UART2_SCR)
-#define bfin_write_UART2_SCR(val)	bfin_write16(UART2_SCR, val)
-#define bfin_read_UART2_IER_SET()	bfin_read16(UART2_IER_SET)
-#define bfin_write_UART2_IER_SET(val)	bfin_write16(UART2_IER_SET, val)
-#define bfin_read_UART2_IER_CLEAR()	bfin_read16(UART2_IER_CLEAR)
-#define bfin_write_UART2_IER_CLEAR(val)	bfin_write16(UART2_IER_CLEAR, val)
-#define bfin_read_UART2_RBR()		bfin_read16(UART2_RBR)
-#define bfin_write_UART2_RBR(val)	bfin_write16(UART2_RBR, val)
-
-/* Two Wire Interface Registers (TWI1) */
-
-/* SPI2  Registers */
-
-#define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
-#define bfin_write_SPI2_CTL(val)	bfin_write16(SPI2_CTL, val)
-#define bfin_read_SPI2_FLG()		bfin_read16(SPI2_FLG)
-#define bfin_write_SPI2_FLG(val)	bfin_write16(SPI2_FLG, val)
-#define bfin_read_SPI2_STAT()		bfin_read16(SPI2_STAT)
-#define bfin_write_SPI2_STAT(val)	bfin_write16(SPI2_STAT, val)
-#define bfin_read_SPI2_TDBR()		bfin_read16(SPI2_TDBR)
-#define bfin_write_SPI2_TDBR(val)	bfin_write16(SPI2_TDBR, val)
-#define bfin_read_SPI2_RDBR()		bfin_read16(SPI2_RDBR)
-#define bfin_write_SPI2_RDBR(val)	bfin_write16(SPI2_RDBR, val)
-#define bfin_read_SPI2_BAUD()		bfin_read16(SPI2_BAUD)
-#define bfin_write_SPI2_BAUD(val)	bfin_write16(SPI2_BAUD, val)
-#define bfin_read_SPI2_SHADOW()		bfin_read16(SPI2_SHADOW)
-#define bfin_write_SPI2_SHADOW(val)	bfin_write16(SPI2_SHADOW, val)
+/* The BF548 is like the BF547, but has additional CANs */
+#include "cdefBF547.h"
 
 /* CAN Controller 1 Config 1 Registers */
 
@@ -923,631 +766,4 @@
 #define bfin_read_CAN1_MB31_ID1()		bfin_read16(CAN1_MB31_ID1)
 #define bfin_write_CAN1_MB31_ID1(val)		bfin_write16(CAN1_MB31_ID1, val)
 
-/* ATAPI Registers */
-
-#define bfin_read_ATAPI_CONTROL()		bfin_read16(ATAPI_CONTROL)
-#define bfin_write_ATAPI_CONTROL(val)		bfin_write16(ATAPI_CONTROL, val)
-#define bfin_read_ATAPI_STATUS()		bfin_read16(ATAPI_STATUS)
-#define bfin_write_ATAPI_STATUS(val)		bfin_write16(ATAPI_STATUS, val)
-#define bfin_read_ATAPI_DEV_ADDR()		bfin_read16(ATAPI_DEV_ADDR)
-#define bfin_write_ATAPI_DEV_ADDR(val)		bfin_write16(ATAPI_DEV_ADDR, val)
-#define bfin_read_ATAPI_DEV_TXBUF()		bfin_read16(ATAPI_DEV_TXBUF)
-#define bfin_write_ATAPI_DEV_TXBUF(val)		bfin_write16(ATAPI_DEV_TXBUF, val)
-#define bfin_read_ATAPI_DEV_RXBUF()		bfin_read16(ATAPI_DEV_RXBUF)
-#define bfin_write_ATAPI_DEV_RXBUF(val)		bfin_write16(ATAPI_DEV_RXBUF, val)
-#define bfin_read_ATAPI_INT_MASK()		bfin_read16(ATAPI_INT_MASK)
-#define bfin_write_ATAPI_INT_MASK(val)		bfin_write16(ATAPI_INT_MASK, val)
-#define bfin_read_ATAPI_INT_STATUS()		bfin_read16(ATAPI_INT_STATUS)
-#define bfin_write_ATAPI_INT_STATUS(val)	bfin_write16(ATAPI_INT_STATUS, val)
-#define bfin_read_ATAPI_XFER_LEN()		bfin_read16(ATAPI_XFER_LEN)
-#define bfin_write_ATAPI_XFER_LEN(val)		bfin_write16(ATAPI_XFER_LEN, val)
-#define bfin_read_ATAPI_LINE_STATUS()		bfin_read16(ATAPI_LINE_STATUS)
-#define bfin_write_ATAPI_LINE_STATUS(val)	bfin_write16(ATAPI_LINE_STATUS, val)
-#define bfin_read_ATAPI_SM_STATE()		bfin_read16(ATAPI_SM_STATE)
-#define bfin_write_ATAPI_SM_STATE(val)		bfin_write16(ATAPI_SM_STATE, val)
-#define bfin_read_ATAPI_TERMINATE()		bfin_read16(ATAPI_TERMINATE)
-#define bfin_write_ATAPI_TERMINATE(val)		bfin_write16(ATAPI_TERMINATE, val)
-#define bfin_read_ATAPI_PIO_TFRCNT()		bfin_read16(ATAPI_PIO_TFRCNT)
-#define bfin_write_ATAPI_PIO_TFRCNT(val)	bfin_write16(ATAPI_PIO_TFRCNT, val)
-#define bfin_read_ATAPI_DMA_TFRCNT()		bfin_read16(ATAPI_DMA_TFRCNT)
-#define bfin_write_ATAPI_DMA_TFRCNT(val)	bfin_write16(ATAPI_DMA_TFRCNT, val)
-#define bfin_read_ATAPI_UMAIN_TFRCNT()		bfin_read16(ATAPI_UMAIN_TFRCNT)
-#define bfin_write_ATAPI_UMAIN_TFRCNT(val)	bfin_write16(ATAPI_UMAIN_TFRCNT, val)
-#define bfin_read_ATAPI_UDMAOUT_TFRCNT()	bfin_read16(ATAPI_UDMAOUT_TFRCNT)
-#define bfin_write_ATAPI_UDMAOUT_TFRCNT(val)	bfin_write16(ATAPI_UDMAOUT_TFRCNT, val)
-#define bfin_read_ATAPI_REG_TIM_0()		bfin_read16(ATAPI_REG_TIM_0)
-#define bfin_write_ATAPI_REG_TIM_0(val)		bfin_write16(ATAPI_REG_TIM_0, val)
-#define bfin_read_ATAPI_PIO_TIM_0()		bfin_read16(ATAPI_PIO_TIM_0)
-#define bfin_write_ATAPI_PIO_TIM_0(val)		bfin_write16(ATAPI_PIO_TIM_0, val)
-#define bfin_read_ATAPI_PIO_TIM_1()		bfin_read16(ATAPI_PIO_TIM_1)
-#define bfin_write_ATAPI_PIO_TIM_1(val)		bfin_write16(ATAPI_PIO_TIM_1, val)
-#define bfin_read_ATAPI_MULTI_TIM_0()		bfin_read16(ATAPI_MULTI_TIM_0)
-#define bfin_write_ATAPI_MULTI_TIM_0(val)	bfin_write16(ATAPI_MULTI_TIM_0, val)
-#define bfin_read_ATAPI_MULTI_TIM_1()		bfin_read16(ATAPI_MULTI_TIM_1)
-#define bfin_write_ATAPI_MULTI_TIM_1(val)	bfin_write16(ATAPI_MULTI_TIM_1, val)
-#define bfin_read_ATAPI_MULTI_TIM_2()		bfin_read16(ATAPI_MULTI_TIM_2)
-#define bfin_write_ATAPI_MULTI_TIM_2(val)	bfin_write16(ATAPI_MULTI_TIM_2, val)
-#define bfin_read_ATAPI_ULTRA_TIM_0()		bfin_read16(ATAPI_ULTRA_TIM_0)
-#define bfin_write_ATAPI_ULTRA_TIM_0(val)	bfin_write16(ATAPI_ULTRA_TIM_0, val)
-#define bfin_read_ATAPI_ULTRA_TIM_1()		bfin_read16(ATAPI_ULTRA_TIM_1)
-#define bfin_write_ATAPI_ULTRA_TIM_1(val)	bfin_write16(ATAPI_ULTRA_TIM_1, val)
-#define bfin_read_ATAPI_ULTRA_TIM_2()		bfin_read16(ATAPI_ULTRA_TIM_2)
-#define bfin_write_ATAPI_ULTRA_TIM_2(val)	bfin_write16(ATAPI_ULTRA_TIM_2, val)
-#define bfin_read_ATAPI_ULTRA_TIM_3()		bfin_read16(ATAPI_ULTRA_TIM_3)
-#define bfin_write_ATAPI_ULTRA_TIM_3(val)	bfin_write16(ATAPI_ULTRA_TIM_3, val)
-
-/* SDH Registers */
-
-#define bfin_read_SDH_PWR_CTL()		bfin_read16(SDH_PWR_CTL)
-#define bfin_write_SDH_PWR_CTL(val)	bfin_write16(SDH_PWR_CTL, val)
-#define bfin_read_SDH_CLK_CTL()		bfin_read16(SDH_CLK_CTL)
-#define bfin_write_SDH_CLK_CTL(val)	bfin_write16(SDH_CLK_CTL, val)
-#define bfin_read_SDH_ARGUMENT()	bfin_read32(SDH_ARGUMENT)
-#define bfin_write_SDH_ARGUMENT(val)	bfin_write32(SDH_ARGUMENT, val)
-#define bfin_read_SDH_COMMAND()		bfin_read16(SDH_COMMAND)
-#define bfin_write_SDH_COMMAND(val)	bfin_write16(SDH_COMMAND, val)
-#define bfin_read_SDH_RESP_CMD()	bfin_read16(SDH_RESP_CMD)
-#define bfin_write_SDH_RESP_CMD(val)	bfin_write16(SDH_RESP_CMD, val)
-#define bfin_read_SDH_RESPONSE0()	bfin_read32(SDH_RESPONSE0)
-#define bfin_write_SDH_RESPONSE0(val)	bfin_write32(SDH_RESPONSE0, val)
-#define bfin_read_SDH_RESPONSE1()	bfin_read32(SDH_RESPONSE1)
-#define bfin_write_SDH_RESPONSE1(val)	bfin_write32(SDH_RESPONSE1, val)
-#define bfin_read_SDH_RESPONSE2()	bfin_read32(SDH_RESPONSE2)
-#define bfin_write_SDH_RESPONSE2(val)	bfin_write32(SDH_RESPONSE2, val)
-#define bfin_read_SDH_RESPONSE3()	bfin_read32(SDH_RESPONSE3)
-#define bfin_write_SDH_RESPONSE3(val)	bfin_write32(SDH_RESPONSE3, val)
-#define bfin_read_SDH_DATA_TIMER()	bfin_read32(SDH_DATA_TIMER)
-#define bfin_write_SDH_DATA_TIMER(val)	bfin_write32(SDH_DATA_TIMER, val)
-#define bfin_read_SDH_DATA_LGTH()	bfin_read16(SDH_DATA_LGTH)
-#define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
-#define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
-#define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
-#define bfin_read_SDH_DATA_CNT()	bfin_read16(SDH_DATA_CNT)
-#define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
-#define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
-#define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
-#define bfin_read_SDH_STATUS_CLR()	bfin_read16(SDH_STATUS_CLR)
-#define bfin_write_SDH_STATUS_CLR(val)	bfin_write16(SDH_STATUS_CLR, val)
-#define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
-#define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
-#define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
-#define bfin_write_SDH_MASK1(val)	bfin_write32(SDH_MASK1, val)
-#define bfin_read_SDH_FIFO_CNT()	bfin_read16(SDH_FIFO_CNT)
-#define bfin_write_SDH_FIFO_CNT(val)	bfin_write16(SDH_FIFO_CNT, val)
-#define bfin_read_SDH_FIFO()		bfin_read32(SDH_FIFO)
-#define bfin_write_SDH_FIFO(val)	bfin_write32(SDH_FIFO, val)
-#define bfin_read_SDH_E_STATUS()	bfin_read16(SDH_E_STATUS)
-#define bfin_write_SDH_E_STATUS(val)	bfin_write16(SDH_E_STATUS, val)
-#define bfin_read_SDH_E_MASK()		bfin_read16(SDH_E_MASK)
-#define bfin_write_SDH_E_MASK(val)	bfin_write16(SDH_E_MASK, val)
-#define bfin_read_SDH_CFG()		bfin_read16(SDH_CFG)
-#define bfin_write_SDH_CFG(val)		bfin_write16(SDH_CFG, val)
-#define bfin_read_SDH_RD_WAIT_EN()	bfin_read16(SDH_RD_WAIT_EN)
-#define bfin_write_SDH_RD_WAIT_EN(val)	bfin_write16(SDH_RD_WAIT_EN, val)
-#define bfin_read_SDH_PID0()		bfin_read16(SDH_PID0)
-#define bfin_write_SDH_PID0(val)	bfin_write16(SDH_PID0, val)
-#define bfin_read_SDH_PID1()		bfin_read16(SDH_PID1)
-#define bfin_write_SDH_PID1(val)	bfin_write16(SDH_PID1, val)
-#define bfin_read_SDH_PID2()		bfin_read16(SDH_PID2)
-#define bfin_write_SDH_PID2(val)	bfin_write16(SDH_PID2, val)
-#define bfin_read_SDH_PID3()		bfin_read16(SDH_PID3)
-#define bfin_write_SDH_PID3(val)	bfin_write16(SDH_PID3, val)
-#define bfin_read_SDH_PID4()		bfin_read16(SDH_PID4)
-#define bfin_write_SDH_PID4(val)	bfin_write16(SDH_PID4, val)
-#define bfin_read_SDH_PID5()		bfin_read16(SDH_PID5)
-#define bfin_write_SDH_PID5(val)	bfin_write16(SDH_PID5, val)
-#define bfin_read_SDH_PID6()		bfin_read16(SDH_PID6)
-#define bfin_write_SDH_PID6(val)	bfin_write16(SDH_PID6, val)
-#define bfin_read_SDH_PID7()		bfin_read16(SDH_PID7)
-#define bfin_write_SDH_PID7(val)	bfin_write16(SDH_PID7, val)
-
-/* HOST Port Registers */
-
-#define bfin_read_HOST_CONTROL()	bfin_read16(HOST_CONTROL)
-#define bfin_write_HOST_CONTROL(val)	bfin_write16(HOST_CONTROL, val)
-#define bfin_read_HOST_STATUS()		bfin_read16(HOST_STATUS)
-#define bfin_write_HOST_STATUS(val)	bfin_write16(HOST_STATUS, val)
-#define bfin_read_HOST_TIMEOUT()	bfin_read16(HOST_TIMEOUT)
-#define bfin_write_HOST_TIMEOUT(val)	bfin_write16(HOST_TIMEOUT, val)
-
-/* USB Control Registers */
-
-#define bfin_read_USB_FADDR()		bfin_read16(USB_FADDR)
-#define bfin_write_USB_FADDR(val)	bfin_write16(USB_FADDR, val)
-#define bfin_read_USB_POWER()		bfin_read16(USB_POWER)
-#define bfin_write_USB_POWER(val)	bfin_write16(USB_POWER, val)
-#define bfin_read_USB_INTRTX()		bfin_read16(USB_INTRTX)
-#define bfin_write_USB_INTRTX(val)	bfin_write16(USB_INTRTX, val)
-#define bfin_read_USB_INTRRX()		bfin_read16(USB_INTRRX)
-#define bfin_write_USB_INTRRX(val)	bfin_write16(USB_INTRRX, val)
-#define bfin_read_USB_INTRTXE()		bfin_read16(USB_INTRTXE)
-#define bfin_write_USB_INTRTXE(val)	bfin_write16(USB_INTRTXE, val)
-#define bfin_read_USB_INTRRXE()		bfin_read16(USB_INTRRXE)
-#define bfin_write_USB_INTRRXE(val)	bfin_write16(USB_INTRRXE, val)
-#define bfin_read_USB_INTRUSB()		bfin_read16(USB_INTRUSB)
-#define bfin_write_USB_INTRUSB(val)	bfin_write16(USB_INTRUSB, val)
-#define bfin_read_USB_INTRUSBE()	bfin_read16(USB_INTRUSBE)
-#define bfin_write_USB_INTRUSBE(val)	bfin_write16(USB_INTRUSBE, val)
-#define bfin_read_USB_FRAME()		bfin_read16(USB_FRAME)
-#define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
-#define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
-#define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
-#define bfin_read_USB_TESTMODE()	bfin_read16(USB_TESTMODE)
-#define bfin_write_USB_TESTMODE(val)	bfin_write16(USB_TESTMODE, val)
-#define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
-#define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
-#define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
-#define bfin_write_USB_GLOBAL_CTL(val)		bfin_write16(USB_GLOBAL_CTL, val)
-
-/* USB Packet Control Registers */
-
-#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
-#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
-#define bfin_read_USB_CSR0()		bfin_read16(USB_CSR0)
-#define bfin_write_USB_CSR0(val)	bfin_write16(USB_CSR0, val)
-#define bfin_read_USB_TXCSR()		bfin_read16(USB_TXCSR)
-#define bfin_write_USB_TXCSR(val)	bfin_write16(USB_TXCSR, val)
-#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
-#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
-#define bfin_read_USB_RXCSR()		bfin_read16(USB_RXCSR)
-#define bfin_write_USB_RXCSR(val)	bfin_write16(USB_RXCSR, val)
-#define bfin_read_USB_COUNT0()		bfin_read16(USB_COUNT0)
-#define bfin_write_USB_COUNT0(val)	bfin_write16(USB_COUNT0, val)
-#define bfin_read_USB_RXCOUNT()		bfin_read16(USB_RXCOUNT)
-#define bfin_write_USB_RXCOUNT(val)	bfin_write16(USB_RXCOUNT, val)
-#define bfin_read_USB_TXTYPE()		bfin_read16(USB_TXTYPE)
-#define bfin_write_USB_TXTYPE(val)	bfin_write16(USB_TXTYPE, val)
-#define bfin_read_USB_NAKLIMIT0()	bfin_read16(USB_NAKLIMIT0)
-#define bfin_write_USB_NAKLIMIT0(val)	bfin_write16(USB_NAKLIMIT0, val)
-#define bfin_read_USB_TXINTERVAL()	bfin_read16(USB_TXINTERVAL)
-#define bfin_write_USB_TXINTERVAL(val)	bfin_write16(USB_TXINTERVAL, val)
-#define bfin_read_USB_RXTYPE()		bfin_read16(USB_RXTYPE)
-#define bfin_write_USB_RXTYPE(val)	bfin_write16(USB_RXTYPE, val)
-#define bfin_read_USB_RXINTERVAL()	bfin_read16(USB_RXINTERVAL)
-#define bfin_write_USB_RXINTERVAL(val)	bfin_write16(USB_RXINTERVAL, val)
-#define bfin_read_USB_TXCOUNT()		bfin_read16(USB_TXCOUNT)
-#define bfin_write_USB_TXCOUNT(val)	bfin_write16(USB_TXCOUNT, val)
-
-/* USB Endbfin_read_()oint FIFO Registers */
-
-#define bfin_read_USB_EP0_FIFO()	bfin_read16(USB_EP0_FIFO)
-#define bfin_write_USB_EP0_FIFO(val)	bfin_write16(USB_EP0_FIFO, val)
-#define bfin_read_USB_EP1_FIFO()	bfin_read16(USB_EP1_FIFO)
-#define bfin_write_USB_EP1_FIFO(val)	bfin_write16(USB_EP1_FIFO, val)
-#define bfin_read_USB_EP2_FIFO()	bfin_read16(USB_EP2_FIFO)
-#define bfin_write_USB_EP2_FIFO(val)	bfin_write16(USB_EP2_FIFO, val)
-#define bfin_read_USB_EP3_FIFO()	bfin_read16(USB_EP3_FIFO)
-#define bfin_write_USB_EP3_FIFO(val)	bfin_write16(USB_EP3_FIFO, val)
-#define bfin_read_USB_EP4_FIFO()	bfin_read16(USB_EP4_FIFO)
-#define bfin_write_USB_EP4_FIFO(val)	bfin_write16(USB_EP4_FIFO, val)
-#define bfin_read_USB_EP5_FIFO()	bfin_read16(USB_EP5_FIFO)
-#define bfin_write_USB_EP5_FIFO(val)	bfin_write16(USB_EP5_FIFO, val)
-#define bfin_read_USB_EP6_FIFO()	bfin_read16(USB_EP6_FIFO)
-#define bfin_write_USB_EP6_FIFO(val)	bfin_write16(USB_EP6_FIFO, val)
-#define bfin_read_USB_EP7_FIFO()	bfin_read16(USB_EP7_FIFO)
-#define bfin_write_USB_EP7_FIFO(val)	bfin_write16(USB_EP7_FIFO, val)
-
-/* USB OTG Control Registers */
-
-#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
-#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
-#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
-#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
-#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
-#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
-
-/* USB Phy Control Registers */
-
-#define bfin_read_USB_LINKINFO()	bfin_read16(USB_LINKINFO)
-#define bfin_write_USB_LINKINFO(val)	bfin_write16(USB_LINKINFO, val)
-#define bfin_read_USB_VPLEN()		bfin_read16(USB_VPLEN)
-#define bfin_write_USB_VPLEN(val)	bfin_write16(USB_VPLEN, val)
-#define bfin_read_USB_HS_EOF1()		bfin_read16(USB_HS_EOF1)
-#define bfin_write_USB_HS_EOF1(val)	bfin_write16(USB_HS_EOF1, val)
-#define bfin_read_USB_FS_EOF1()		bfin_read16(USB_FS_EOF1)
-#define bfin_write_USB_FS_EOF1(val)	bfin_write16(USB_FS_EOF1, val)
-#define bfin_read_USB_LS_EOF1()		bfin_read16(USB_LS_EOF1)
-#define bfin_write_USB_LS_EOF1(val)	bfin_write16(USB_LS_EOF1, val)
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
-#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
-#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
-#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
-#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
-#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
-#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
-#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
-#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
-
-/* USB Endbfin_read_()oint 0 Control Registers */
-
-#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
-#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
-#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
-#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
-#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
-#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
-#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
-#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
-#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
-#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
-#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
-#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
-#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
-#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
-#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
-#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
-#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 1 Control Registers */
-
-#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
-#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
-#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
-#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
-#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
-#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
-#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
-#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
-#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
-#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
-#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
-#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
-#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
-#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
-#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
-#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
-#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
-#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
-#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 2 Control Registers */
-
-#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
-#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
-#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
-#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
-#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
-#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
-#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
-#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
-#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
-#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
-#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
-#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
-#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
-#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
-#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
-#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
-#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
-#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
-#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 3 Control Registers */
-
-#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
-#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
-#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
-#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
-#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
-#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
-#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
-#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
-#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
-#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
-#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
-#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
-#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
-#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
-#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
-#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
-#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
-#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
-#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 4 Control Registers */
-
-#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
-#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
-#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
-#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
-#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
-#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
-#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
-#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
-#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
-#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
-#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
-#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
-#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
-#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
-#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
-#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
-#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
-#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
-#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 5 Control Registers */
-
-#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
-#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
-#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
-#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
-#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
-#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
-#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
-#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
-#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
-#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
-#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
-#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
-#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
-#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
-#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
-#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
-#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
-#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
-#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 6 Control Registers */
-
-#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
-#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
-#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
-#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
-#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
-#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
-#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
-#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
-#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
-#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
-#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
-#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
-#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
-#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
-#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
-#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
-#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
-#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
-#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 7 Control Registers */
-
-#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
-#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
-#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
-#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
-#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
-#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
-#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
-#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
-#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
-#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
-#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
-#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
-#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
-#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
-#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
-#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
-#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
-#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
-#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
-#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
-#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
-#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
-
-/* USB Channel 0 Config Registers */
-
-#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
-#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
-#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
-#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
-#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
-#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
-#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
-#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
-#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
-#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
-
-/* USB Channel 1 Config Registers */
-
-#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
-#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
-#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
-#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
-#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
-#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
-#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
-#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
-#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
-#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
-
-/* USB Channel 2 Config Registers */
-
-#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
-#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
-#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
-#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
-#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
-#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
-#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
-#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
-#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
-#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
-
-/* USB Channel 3 Config Registers */
-
-#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
-#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
-#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
-#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
-#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
-#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
-#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
-#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
-#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
-#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
-
-/* USB Channel 4 Config Registers */
-
-#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
-#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
-#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
-#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
-#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
-#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
-#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
-#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
-#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
-#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
-
-/* USB Channel 5 Config Registers */
-
-#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
-#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
-#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
-#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
-#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
-#define bfin_write_USB_DMA5ADDRHIGH(val)	bfin_write16(USB_DMA5ADDRHIGH, val)
-#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
-#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
-#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
-#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
-
-/* USB Channel 6 Config Registers */
-
-#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
-#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
-#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
-#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
-#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
-#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
-#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
-#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
-#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
-#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
-
-/* USB Channel 7 Config Registers */
-
-#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
-#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
-#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
-#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
-#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
-#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
-#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
-#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
-#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
-#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
-
-/* Keybfin_read_()ad Registers */
-
-#define bfin_read_KPAD_CTL()		bfin_read16(KPAD_CTL)
-#define bfin_write_KPAD_CTL(val)	bfin_write16(KPAD_CTL, val)
-#define bfin_read_KPAD_PRESCALE()	bfin_read16(KPAD_PRESCALE)
-#define bfin_write_KPAD_PRESCALE(val)	bfin_write16(KPAD_PRESCALE, val)
-#define bfin_read_KPAD_MSEL()		bfin_read16(KPAD_MSEL)
-#define bfin_write_KPAD_MSEL(val)	bfin_write16(KPAD_MSEL, val)
-#define bfin_read_KPAD_ROWCOL()		bfin_read16(KPAD_ROWCOL)
-#define bfin_write_KPAD_ROWCOL(val)	bfin_write16(KPAD_ROWCOL, val)
-#define bfin_read_KPAD_STAT()		bfin_read16(KPAD_STAT)
-#define bfin_write_KPAD_STAT(val)	bfin_write16(KPAD_STAT, val)
-#define bfin_read_KPAD_SOFTEVAL()	bfin_read16(KPAD_SOFTEVAL)
-#define bfin_write_KPAD_SOFTEVAL(val)	bfin_write16(KPAD_SOFTEVAL, val)
-
-/* Pixel Combfin_read_()ositor (PIXC) Registers */
-
-#define bfin_read_PIXC_CTL()		bfin_read16(PIXC_CTL)
-#define bfin_write_PIXC_CTL(val)	bfin_write16(PIXC_CTL, val)
-#define bfin_read_PIXC_PPL()		bfin_read16(PIXC_PPL)
-#define bfin_write_PIXC_PPL(val)	bfin_write16(PIXC_PPL, val)
-#define bfin_read_PIXC_LPF()		bfin_read16(PIXC_LPF)
-#define bfin_write_PIXC_LPF(val)	bfin_write16(PIXC_LPF, val)
-#define bfin_read_PIXC_AHSTART()	bfin_read16(PIXC_AHSTART)
-#define bfin_write_PIXC_AHSTART(val)	bfin_write16(PIXC_AHSTART, val)
-#define bfin_read_PIXC_AHEND()		bfin_read16(PIXC_AHEND)
-#define bfin_write_PIXC_AHEND(val)	bfin_write16(PIXC_AHEND, val)
-#define bfin_read_PIXC_AVSTART()	bfin_read16(PIXC_AVSTART)
-#define bfin_write_PIXC_AVSTART(val)	bfin_write16(PIXC_AVSTART, val)
-#define bfin_read_PIXC_AVEND()		bfin_read16(PIXC_AVEND)
-#define bfin_write_PIXC_AVEND(val)	bfin_write16(PIXC_AVEND, val)
-#define bfin_read_PIXC_ATRANSP()	bfin_read16(PIXC_ATRANSP)
-#define bfin_write_PIXC_ATRANSP(val)	bfin_write16(PIXC_ATRANSP, val)
-#define bfin_read_PIXC_BHSTART()	bfin_read16(PIXC_BHSTART)
-#define bfin_write_PIXC_BHSTART(val)	bfin_write16(PIXC_BHSTART, val)
-#define bfin_read_PIXC_BHEND()		bfin_read16(PIXC_BHEND)
-#define bfin_write_PIXC_BHEND(val)	bfin_write16(PIXC_BHEND, val)
-#define bfin_read_PIXC_BVSTART()	bfin_read16(PIXC_BVSTART)
-#define bfin_write_PIXC_BVSTART(val)	bfin_write16(PIXC_BVSTART, val)
-#define bfin_read_PIXC_BVEND()		bfin_read16(PIXC_BVEND)
-#define bfin_write_PIXC_BVEND(val)	bfin_write16(PIXC_BVEND, val)
-#define bfin_read_PIXC_BTRANSP()	bfin_read16(PIXC_BTRANSP)
-#define bfin_write_PIXC_BTRANSP(val)	bfin_write16(PIXC_BTRANSP, val)
-#define bfin_read_PIXC_INTRSTAT()	bfin_read16(PIXC_INTRSTAT)
-#define bfin_write_PIXC_INTRSTAT(val)	bfin_write16(PIXC_INTRSTAT, val)
-#define bfin_read_PIXC_RYCON()		bfin_read32(PIXC_RYCON)
-#define bfin_write_PIXC_RYCON(val)	bfin_write32(PIXC_RYCON, val)
-#define bfin_read_PIXC_GUCON()		bfin_read32(PIXC_GUCON)
-#define bfin_write_PIXC_GUCON(val)	bfin_write32(PIXC_GUCON, val)
-#define bfin_read_PIXC_BVCON()		bfin_read32(PIXC_BVCON)
-#define bfin_write_PIXC_BVCON(val)	bfin_write32(PIXC_BVCON, val)
-#define bfin_read_PIXC_CCBIAS()		bfin_read32(PIXC_CCBIAS)
-#define bfin_write_PIXC_CCBIAS(val)	bfin_write32(PIXC_CCBIAS, val)
-#define bfin_read_PIXC_TC()		bfin_read32(PIXC_TC)
-#define bfin_write_PIXC_TC(val)		bfin_write32(PIXC_TC, val)
-
-/* Handshake MDMA 0 Registers */
-
-#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
-#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
-#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
-#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
-#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
-#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
-#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
-#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
-#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
-#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
-#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
-#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
-#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
-#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
-
-/* Handshake MDMA 1 Registers */
-
-#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
-#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
-#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
-#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
-#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
-#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
-#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
-#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
-#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
-#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
-#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
-#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
-#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
-#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
-
 #endif /* _CDEF_BF548_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF549.h b/arch/blackfin/mach-bf548/include/mach/cdefBF549.h
index 34c84c7..80201ed 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF549.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF549.h
@@ -18,165 +18,8 @@
 /* include cdefBF54x_base.h for the set of #defines that are common to all ADSP-BF54x bfin_read_()rocessors */
 #include "cdefBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF549 that are not in the common header */
-
-/* Timer Registers */
-
-#define bfin_read_TIMER8_CONFIG()		bfin_read16(TIMER8_CONFIG)
-#define bfin_write_TIMER8_CONFIG(val)		bfin_write16(TIMER8_CONFIG, val)
-#define bfin_read_TIMER8_COUNTER()		bfin_read32(TIMER8_COUNTER)
-#define bfin_write_TIMER8_COUNTER(val)		bfin_write32(TIMER8_COUNTER, val)
-#define bfin_read_TIMER8_PERIOD()		bfin_read32(TIMER8_PERIOD)
-#define bfin_write_TIMER8_PERIOD(val)		bfin_write32(TIMER8_PERIOD, val)
-#define bfin_read_TIMER8_WIDTH()		bfin_read32(TIMER8_WIDTH)
-#define bfin_write_TIMER8_WIDTH(val)		bfin_write32(TIMER8_WIDTH, val)
-#define bfin_read_TIMER9_CONFIG()		bfin_read16(TIMER9_CONFIG)
-#define bfin_write_TIMER9_CONFIG(val)		bfin_write16(TIMER9_CONFIG, val)
-#define bfin_read_TIMER9_COUNTER()		bfin_read32(TIMER9_COUNTER)
-#define bfin_write_TIMER9_COUNTER(val)		bfin_write32(TIMER9_COUNTER, val)
-#define bfin_read_TIMER9_PERIOD()		bfin_read32(TIMER9_PERIOD)
-#define bfin_write_TIMER9_PERIOD(val)		bfin_write32(TIMER9_PERIOD, val)
-#define bfin_read_TIMER9_WIDTH()		bfin_read32(TIMER9_WIDTH)
-#define bfin_write_TIMER9_WIDTH(val)		bfin_write32(TIMER9_WIDTH, val)
-#define bfin_read_TIMER10_CONFIG()		bfin_read16(TIMER10_CONFIG)
-#define bfin_write_TIMER10_CONFIG(val)		bfin_write16(TIMER10_CONFIG, val)
-#define bfin_read_TIMER10_COUNTER()		bfin_read32(TIMER10_COUNTER)
-#define bfin_write_TIMER10_COUNTER(val)		bfin_write32(TIMER10_COUNTER, val)
-#define bfin_read_TIMER10_PERIOD()		bfin_read32(TIMER10_PERIOD)
-#define bfin_write_TIMER10_PERIOD(val)		bfin_write32(TIMER10_PERIOD, val)
-#define bfin_read_TIMER10_WIDTH()		bfin_read32(TIMER10_WIDTH)
-#define bfin_write_TIMER10_WIDTH(val)		bfin_write32(TIMER10_WIDTH, val)
-
-/* Timer Groubfin_read_() of 3 */
-
-#define bfin_read_TIMER_ENABLE1()		bfin_read16(TIMER_ENABLE1)
-#define bfin_write_TIMER_ENABLE1(val)		bfin_write16(TIMER_ENABLE1, val)
-#define bfin_read_TIMER_DISABLE1()		bfin_read16(TIMER_DISABLE1)
-#define bfin_write_TIMER_DISABLE1(val)		bfin_write16(TIMER_DISABLE1, val)
-#define bfin_read_TIMER_STATUS1()		bfin_read32(TIMER_STATUS1)
-#define bfin_write_TIMER_STATUS1(val)		bfin_write32(TIMER_STATUS1, val)
-
-/* SPORT0 Registers */
-
-#define bfin_read_SPORT0_TCR1()			bfin_read16(SPORT0_TCR1)
-#define bfin_write_SPORT0_TCR1(val)		bfin_write16(SPORT0_TCR1, val)
-#define bfin_read_SPORT0_TCR2()			bfin_read16(SPORT0_TCR2)
-#define bfin_write_SPORT0_TCR2(val)		bfin_write16(SPORT0_TCR2, val)
-#define bfin_read_SPORT0_TCLKDIV()		bfin_read16(SPORT0_TCLKDIV)
-#define bfin_write_SPORT0_TCLKDIV(val)		bfin_write16(SPORT0_TCLKDIV, val)
-#define bfin_read_SPORT0_TFSDIV()		bfin_read16(SPORT0_TFSDIV)
-#define bfin_write_SPORT0_TFSDIV(val)		bfin_write16(SPORT0_TFSDIV, val)
-#define bfin_read_SPORT0_TX()			bfin_read32(SPORT0_TX)
-#define bfin_write_SPORT0_TX(val)		bfin_write32(SPORT0_TX, val)
-#define bfin_read_SPORT0_RX()			bfin_read32(SPORT0_RX)
-#define bfin_write_SPORT0_RX(val)		bfin_write32(SPORT0_RX, val)
-#define bfin_read_SPORT0_RCR1()			bfin_read16(SPORT0_RCR1)
-#define bfin_write_SPORT0_RCR1(val)		bfin_write16(SPORT0_RCR1, val)
-#define bfin_read_SPORT0_RCR2()			bfin_read16(SPORT0_RCR2)
-#define bfin_write_SPORT0_RCR2(val)		bfin_write16(SPORT0_RCR2, val)
-#define bfin_read_SPORT0_RCLKDIV()		bfin_read16(SPORT0_RCLKDIV)
-#define bfin_write_SPORT0_RCLKDIV(val)		bfin_write16(SPORT0_RCLKDIV, val)
-#define bfin_read_SPORT0_RFSDIV()		bfin_read16(SPORT0_RFSDIV)
-#define bfin_write_SPORT0_RFSDIV(val)		bfin_write16(SPORT0_RFSDIV, val)
-#define bfin_read_SPORT0_STAT()			bfin_read16(SPORT0_STAT)
-#define bfin_write_SPORT0_STAT(val)		bfin_write16(SPORT0_STAT, val)
-#define bfin_read_SPORT0_CHNL()			bfin_read16(SPORT0_CHNL)
-#define bfin_write_SPORT0_CHNL(val)		bfin_write16(SPORT0_CHNL, val)
-#define bfin_read_SPORT0_MCMC1()		bfin_read16(SPORT0_MCMC1)
-#define bfin_write_SPORT0_MCMC1(val)		bfin_write16(SPORT0_MCMC1, val)
-#define bfin_read_SPORT0_MCMC2()		bfin_read16(SPORT0_MCMC2)
-#define bfin_write_SPORT0_MCMC2(val)		bfin_write16(SPORT0_MCMC2, val)
-#define bfin_read_SPORT0_MTCS0()		bfin_read32(SPORT0_MTCS0)
-#define bfin_write_SPORT0_MTCS0(val)		bfin_write32(SPORT0_MTCS0, val)
-#define bfin_read_SPORT0_MTCS1()		bfin_read32(SPORT0_MTCS1)
-#define bfin_write_SPORT0_MTCS1(val)		bfin_write32(SPORT0_MTCS1, val)
-#define bfin_read_SPORT0_MTCS2()		bfin_read32(SPORT0_MTCS2)
-#define bfin_write_SPORT0_MTCS2(val)		bfin_write32(SPORT0_MTCS2, val)
-#define bfin_read_SPORT0_MTCS3()		bfin_read32(SPORT0_MTCS3)
-#define bfin_write_SPORT0_MTCS3(val)		bfin_write32(SPORT0_MTCS3, val)
-#define bfin_read_SPORT0_MRCS0()		bfin_read32(SPORT0_MRCS0)
-#define bfin_write_SPORT0_MRCS0(val)		bfin_write32(SPORT0_MRCS0, val)
-#define bfin_read_SPORT0_MRCS1()		bfin_read32(SPORT0_MRCS1)
-#define bfin_write_SPORT0_MRCS1(val)		bfin_write32(SPORT0_MRCS1, val)
-#define bfin_read_SPORT0_MRCS2()		bfin_read32(SPORT0_MRCS2)
-#define bfin_write_SPORT0_MRCS2(val)		bfin_write32(SPORT0_MRCS2, val)
-#define bfin_read_SPORT0_MRCS3()		bfin_read32(SPORT0_MRCS3)
-#define bfin_write_SPORT0_MRCS3(val)		bfin_write32(SPORT0_MRCS3, val)
-
-/* EPPI0 Registers */
-
-#define bfin_read_EPPI0_STATUS()		bfin_read16(EPPI0_STATUS)
-#define bfin_write_EPPI0_STATUS(val)		bfin_write16(EPPI0_STATUS, val)
-#define bfin_read_EPPI0_HCOUNT()		bfin_read16(EPPI0_HCOUNT)
-#define bfin_write_EPPI0_HCOUNT(val)		bfin_write16(EPPI0_HCOUNT, val)
-#define bfin_read_EPPI0_HDELAY()		bfin_read16(EPPI0_HDELAY)
-#define bfin_write_EPPI0_HDELAY(val)		bfin_write16(EPPI0_HDELAY, val)
-#define bfin_read_EPPI0_VCOUNT()		bfin_read16(EPPI0_VCOUNT)
-#define bfin_write_EPPI0_VCOUNT(val)		bfin_write16(EPPI0_VCOUNT, val)
-#define bfin_read_EPPI0_VDELAY()		bfin_read16(EPPI0_VDELAY)
-#define bfin_write_EPPI0_VDELAY(val)		bfin_write16(EPPI0_VDELAY, val)
-#define bfin_read_EPPI0_FRAME()			bfin_read16(EPPI0_FRAME)
-#define bfin_write_EPPI0_FRAME(val)		bfin_write16(EPPI0_FRAME, val)
-#define bfin_read_EPPI0_LINE()			bfin_read16(EPPI0_LINE)
-#define bfin_write_EPPI0_LINE(val)		bfin_write16(EPPI0_LINE, val)
-#define bfin_read_EPPI0_CLKDIV()		bfin_read16(EPPI0_CLKDIV)
-#define bfin_write_EPPI0_CLKDIV(val)		bfin_write16(EPPI0_CLKDIV, val)
-#define bfin_read_EPPI0_CONTROL()		bfin_read32(EPPI0_CONTROL)
-#define bfin_write_EPPI0_CONTROL(val)		bfin_write32(EPPI0_CONTROL, val)
-#define bfin_read_EPPI0_FS1W_HBL()		bfin_read32(EPPI0_FS1W_HBL)
-#define bfin_write_EPPI0_FS1W_HBL(val)		bfin_write32(EPPI0_FS1W_HBL, val)
-#define bfin_read_EPPI0_FS1P_AVPL()		bfin_read32(EPPI0_FS1P_AVPL)
-#define bfin_write_EPPI0_FS1P_AVPL(val)		bfin_write32(EPPI0_FS1P_AVPL, val)
-#define bfin_read_EPPI0_FS2W_LVB()		bfin_read32(EPPI0_FS2W_LVB)
-#define bfin_write_EPPI0_FS2W_LVB(val)		bfin_write32(EPPI0_FS2W_LVB, val)
-#define bfin_read_EPPI0_FS2P_LAVF()		bfin_read32(EPPI0_FS2P_LAVF)
-#define bfin_write_EPPI0_FS2P_LAVF(val)		bfin_write32(EPPI0_FS2P_LAVF, val)
-#define bfin_read_EPPI0_CLIP()			bfin_read32(EPPI0_CLIP)
-#define bfin_write_EPPI0_CLIP(val)		bfin_write32(EPPI0_CLIP, val)
-
-/* UART2 Registers */
-
-#define bfin_read_UART2_DLL()			bfin_read16(UART2_DLL)
-#define bfin_write_UART2_DLL(val)		bfin_write16(UART2_DLL, val)
-#define bfin_read_UART2_DLH()			bfin_read16(UART2_DLH)
-#define bfin_write_UART2_DLH(val)		bfin_write16(UART2_DLH, val)
-#define bfin_read_UART2_GCTL()			bfin_read16(UART2_GCTL)
-#define bfin_write_UART2_GCTL(val)		bfin_write16(UART2_GCTL, val)
-#define bfin_read_UART2_LCR()			bfin_read16(UART2_LCR)
-#define bfin_write_UART2_LCR(val)		bfin_write16(UART2_LCR, val)
-#define bfin_read_UART2_MCR()			bfin_read16(UART2_MCR)
-#define bfin_write_UART2_MCR(val)		bfin_write16(UART2_MCR, val)
-#define bfin_read_UART2_LSR()			bfin_read16(UART2_LSR)
-#define bfin_write_UART2_LSR(val)		bfin_write16(UART2_LSR, val)
-#define bfin_read_UART2_MSR()			bfin_read16(UART2_MSR)
-#define bfin_write_UART2_MSR(val)		bfin_write16(UART2_MSR, val)
-#define bfin_read_UART2_SCR()			bfin_read16(UART2_SCR)
-#define bfin_write_UART2_SCR(val)		bfin_write16(UART2_SCR, val)
-#define bfin_read_UART2_IER_SET()		bfin_read16(UART2_IER_SET)
-#define bfin_write_UART2_IER_SET(val)		bfin_write16(UART2_IER_SET, val)
-#define bfin_read_UART2_IER_CLEAR()		bfin_read16(UART2_IER_CLEAR)
-#define bfin_write_UART2_IER_CLEAR(val)		bfin_write16(UART2_IER_CLEAR, val)
-#define bfin_read_UART2_RBR()			bfin_read16(UART2_RBR)
-#define bfin_write_UART2_RBR(val)		bfin_write16(UART2_RBR, val)
-
-/* Two Wire Interface Registers (TWI1) */
-
-/* SPI2 Registers */
-
-#define bfin_read_SPI2_CTL()		bfin_read16(SPI2_CTL)
-#define bfin_write_SPI2_CTL(val)	bfin_write16(SPI2_CTL, val)
-#define bfin_read_SPI2_FLG()		bfin_read16(SPI2_FLG)
-#define bfin_write_SPI2_FLG(val)	bfin_write16(SPI2_FLG, val)
-#define bfin_read_SPI2_STAT()		bfin_read16(SPI2_STAT)
-#define bfin_write_SPI2_STAT(val)	bfin_write16(SPI2_STAT, val)
-#define bfin_read_SPI2_TDBR()		bfin_read16(SPI2_TDBR)
-#define bfin_write_SPI2_TDBR(val)	bfin_write16(SPI2_TDBR, val)
-#define bfin_read_SPI2_RDBR()		bfin_read16(SPI2_RDBR)
-#define bfin_write_SPI2_RDBR(val)	bfin_write16(SPI2_RDBR, val)
-#define bfin_read_SPI2_BAUD()		bfin_read16(SPI2_BAUD)
-#define bfin_write_SPI2_BAUD(val)	bfin_write16(SPI2_BAUD, val)
-#define bfin_read_SPI2_SHADOW()		bfin_read16(SPI2_SHADOW)
-#define bfin_write_SPI2_SHADOW(val)	bfin_write16(SPI2_SHADOW, val)
+/* The BF549 is like the BF544, but has MXVR */
+#include "cdefBF547.h"
 
 /* MXVR Registers */
 
@@ -464,1376 +307,4 @@
 #define bfin_read_MXVR_SCLK_CNT()		bfin_read16(MXVR_SCLK_CNT)
 #define bfin_write_MXVR_SCLK_CNT(val)		bfin_write16(MXVR_SCLK_CNT, val)
 
-/* CAN Controller 1 Config 1 Registers */
-
-#define bfin_read_CAN1_MC1()		bfin_read16(CAN1_MC1)
-#define bfin_write_CAN1_MC1(val)	bfin_write16(CAN1_MC1, val)
-#define bfin_read_CAN1_MD1()		bfin_read16(CAN1_MD1)
-#define bfin_write_CAN1_MD1(val)	bfin_write16(CAN1_MD1, val)
-#define bfin_read_CAN1_TRS1()		bfin_read16(CAN1_TRS1)
-#define bfin_write_CAN1_TRS1(val)	bfin_write16(CAN1_TRS1, val)
-#define bfin_read_CAN1_TRR1()		bfin_read16(CAN1_TRR1)
-#define bfin_write_CAN1_TRR1(val)	bfin_write16(CAN1_TRR1, val)
-#define bfin_read_CAN1_TA1()		bfin_read16(CAN1_TA1)
-#define bfin_write_CAN1_TA1(val)	bfin_write16(CAN1_TA1, val)
-#define bfin_read_CAN1_AA1()		bfin_read16(CAN1_AA1)
-#define bfin_write_CAN1_AA1(val)	bfin_write16(CAN1_AA1, val)
-#define bfin_read_CAN1_RMP1()		bfin_read16(CAN1_RMP1)
-#define bfin_write_CAN1_RMP1(val)	bfin_write16(CAN1_RMP1, val)
-#define bfin_read_CAN1_RML1()		bfin_read16(CAN1_RML1)
-#define bfin_write_CAN1_RML1(val)	bfin_write16(CAN1_RML1, val)
-#define bfin_read_CAN1_MBTIF1()		bfin_read16(CAN1_MBTIF1)
-#define bfin_write_CAN1_MBTIF1(val)	bfin_write16(CAN1_MBTIF1, val)
-#define bfin_read_CAN1_MBRIF1()		bfin_read16(CAN1_MBRIF1)
-#define bfin_write_CAN1_MBRIF1(val)	bfin_write16(CAN1_MBRIF1, val)
-#define bfin_read_CAN1_MBIM1()		bfin_read16(CAN1_MBIM1)
-#define bfin_write_CAN1_MBIM1(val)	bfin_write16(CAN1_MBIM1, val)
-#define bfin_read_CAN1_RFH1()		bfin_read16(CAN1_RFH1)
-#define bfin_write_CAN1_RFH1(val)	bfin_write16(CAN1_RFH1, val)
-#define bfin_read_CAN1_OPSS1()		bfin_read16(CAN1_OPSS1)
-#define bfin_write_CAN1_OPSS1(val)	bfin_write16(CAN1_OPSS1, val)
-
-/* CAN Controller 1 Config 2 Registers */
-
-#define bfin_read_CAN1_MC2()		bfin_read16(CAN1_MC2)
-#define bfin_write_CAN1_MC2(val)	bfin_write16(CAN1_MC2, val)
-#define bfin_read_CAN1_MD2()		bfin_read16(CAN1_MD2)
-#define bfin_write_CAN1_MD2(val)	bfin_write16(CAN1_MD2, val)
-#define bfin_read_CAN1_TRS2()		bfin_read16(CAN1_TRS2)
-#define bfin_write_CAN1_TRS2(val)	bfin_write16(CAN1_TRS2, val)
-#define bfin_read_CAN1_TRR2()		bfin_read16(CAN1_TRR2)
-#define bfin_write_CAN1_TRR2(val)	bfin_write16(CAN1_TRR2, val)
-#define bfin_read_CAN1_TA2()		bfin_read16(CAN1_TA2)
-#define bfin_write_CAN1_TA2(val)	bfin_write16(CAN1_TA2, val)
-#define bfin_read_CAN1_AA2()		bfin_read16(CAN1_AA2)
-#define bfin_write_CAN1_AA2(val)	bfin_write16(CAN1_AA2, val)
-#define bfin_read_CAN1_RMP2()		bfin_read16(CAN1_RMP2)
-#define bfin_write_CAN1_RMP2(val)	bfin_write16(CAN1_RMP2, val)
-#define bfin_read_CAN1_RML2()		bfin_read16(CAN1_RML2)
-#define bfin_write_CAN1_RML2(val)	bfin_write16(CAN1_RML2, val)
-#define bfin_read_CAN1_MBTIF2()		bfin_read16(CAN1_MBTIF2)
-#define bfin_write_CAN1_MBTIF2(val)	bfin_write16(CAN1_MBTIF2, val)
-#define bfin_read_CAN1_MBRIF2()		bfin_read16(CAN1_MBRIF2)
-#define bfin_write_CAN1_MBRIF2(val)	bfin_write16(CAN1_MBRIF2, val)
-#define bfin_read_CAN1_MBIM2()		bfin_read16(CAN1_MBIM2)
-#define bfin_write_CAN1_MBIM2(val)	bfin_write16(CAN1_MBIM2, val)
-#define bfin_read_CAN1_RFH2()		bfin_read16(CAN1_RFH2)
-#define bfin_write_CAN1_RFH2(val)	bfin_write16(CAN1_RFH2, val)
-#define bfin_read_CAN1_OPSS2()		bfin_read16(CAN1_OPSS2)
-#define bfin_write_CAN1_OPSS2(val)	bfin_write16(CAN1_OPSS2, val)
-
-/* CAN Controller 1 Clock/Interrubfin_read_()t/Counter Registers */
-
-#define bfin_read_CAN1_CLOCK()		bfin_read16(CAN1_CLOCK)
-#define bfin_write_CAN1_CLOCK(val)	bfin_write16(CAN1_CLOCK, val)
-#define bfin_read_CAN1_TIMING()		bfin_read16(CAN1_TIMING)
-#define bfin_write_CAN1_TIMING(val)	bfin_write16(CAN1_TIMING, val)
-#define bfin_read_CAN1_DEBUG()		bfin_read16(CAN1_DEBUG)
-#define bfin_write_CAN1_DEBUG(val)	bfin_write16(CAN1_DEBUG, val)
-#define bfin_read_CAN1_STATUS()		bfin_read16(CAN1_STATUS)
-#define bfin_write_CAN1_STATUS(val)	bfin_write16(CAN1_STATUS, val)
-#define bfin_read_CAN1_CEC()		bfin_read16(CAN1_CEC)
-#define bfin_write_CAN1_CEC(val)	bfin_write16(CAN1_CEC, val)
-#define bfin_read_CAN1_GIS()		bfin_read16(CAN1_GIS)
-#define bfin_write_CAN1_GIS(val)	bfin_write16(CAN1_GIS, val)
-#define bfin_read_CAN1_GIM()		bfin_read16(CAN1_GIM)
-#define bfin_write_CAN1_GIM(val)	bfin_write16(CAN1_GIM, val)
-#define bfin_read_CAN1_GIF()		bfin_read16(CAN1_GIF)
-#define bfin_write_CAN1_GIF(val)	bfin_write16(CAN1_GIF, val)
-#define bfin_read_CAN1_CONTROL()	bfin_read16(CAN1_CONTROL)
-#define bfin_write_CAN1_CONTROL(val)	bfin_write16(CAN1_CONTROL, val)
-#define bfin_read_CAN1_INTR()		bfin_read16(CAN1_INTR)
-#define bfin_write_CAN1_INTR(val)	bfin_write16(CAN1_INTR, val)
-#define bfin_read_CAN1_MBTD()		bfin_read16(CAN1_MBTD)
-#define bfin_write_CAN1_MBTD(val)	bfin_write16(CAN1_MBTD, val)
-#define bfin_read_CAN1_EWR()		bfin_read16(CAN1_EWR)
-#define bfin_write_CAN1_EWR(val)	bfin_write16(CAN1_EWR, val)
-#define bfin_read_CAN1_ESR()		bfin_read16(CAN1_ESR)
-#define bfin_write_CAN1_ESR(val)	bfin_write16(CAN1_ESR, val)
-#define bfin_read_CAN1_UCCNT()		bfin_read16(CAN1_UCCNT)
-#define bfin_write_CAN1_UCCNT(val)	bfin_write16(CAN1_UCCNT, val)
-#define bfin_read_CAN1_UCRC()		bfin_read16(CAN1_UCRC)
-#define bfin_write_CAN1_UCRC(val)	bfin_write16(CAN1_UCRC, val)
-#define bfin_read_CAN1_UCCNF()		bfin_read16(CAN1_UCCNF)
-#define bfin_write_CAN1_UCCNF(val)	bfin_write16(CAN1_UCCNF, val)
-
-/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
-
-#define bfin_read_CAN1_AM00L()		bfin_read16(CAN1_AM00L)
-#define bfin_write_CAN1_AM00L(val)	bfin_write16(CAN1_AM00L, val)
-#define bfin_read_CAN1_AM00H()		bfin_read16(CAN1_AM00H)
-#define bfin_write_CAN1_AM00H(val)	bfin_write16(CAN1_AM00H, val)
-#define bfin_read_CAN1_AM01L()		bfin_read16(CAN1_AM01L)
-#define bfin_write_CAN1_AM01L(val)	bfin_write16(CAN1_AM01L, val)
-#define bfin_read_CAN1_AM01H()		bfin_read16(CAN1_AM01H)
-#define bfin_write_CAN1_AM01H(val)	bfin_write16(CAN1_AM01H, val)
-#define bfin_read_CAN1_AM02L()		bfin_read16(CAN1_AM02L)
-#define bfin_write_CAN1_AM02L(val)	bfin_write16(CAN1_AM02L, val)
-#define bfin_read_CAN1_AM02H()		bfin_read16(CAN1_AM02H)
-#define bfin_write_CAN1_AM02H(val)	bfin_write16(CAN1_AM02H, val)
-#define bfin_read_CAN1_AM03L()		bfin_read16(CAN1_AM03L)
-#define bfin_write_CAN1_AM03L(val)	bfin_write16(CAN1_AM03L, val)
-#define bfin_read_CAN1_AM03H()		bfin_read16(CAN1_AM03H)
-#define bfin_write_CAN1_AM03H(val)	bfin_write16(CAN1_AM03H, val)
-#define bfin_read_CAN1_AM04L()		bfin_read16(CAN1_AM04L)
-#define bfin_write_CAN1_AM04L(val)	bfin_write16(CAN1_AM04L, val)
-#define bfin_read_CAN1_AM04H()		bfin_read16(CAN1_AM04H)
-#define bfin_write_CAN1_AM04H(val)	bfin_write16(CAN1_AM04H, val)
-#define bfin_read_CAN1_AM05L()		bfin_read16(CAN1_AM05L)
-#define bfin_write_CAN1_AM05L(val)	bfin_write16(CAN1_AM05L, val)
-#define bfin_read_CAN1_AM05H()		bfin_read16(CAN1_AM05H)
-#define bfin_write_CAN1_AM05H(val)	bfin_write16(CAN1_AM05H, val)
-#define bfin_read_CAN1_AM06L()		bfin_read16(CAN1_AM06L)
-#define bfin_write_CAN1_AM06L(val)	bfin_write16(CAN1_AM06L, val)
-#define bfin_read_CAN1_AM06H()		bfin_read16(CAN1_AM06H)
-#define bfin_write_CAN1_AM06H(val)	bfin_write16(CAN1_AM06H, val)
-#define bfin_read_CAN1_AM07L()		bfin_read16(CAN1_AM07L)
-#define bfin_write_CAN1_AM07L(val)	bfin_write16(CAN1_AM07L, val)
-#define bfin_read_CAN1_AM07H()		bfin_read16(CAN1_AM07H)
-#define bfin_write_CAN1_AM07H(val)	bfin_write16(CAN1_AM07H, val)
-#define bfin_read_CAN1_AM08L()		bfin_read16(CAN1_AM08L)
-#define bfin_write_CAN1_AM08L(val)	bfin_write16(CAN1_AM08L, val)
-#define bfin_read_CAN1_AM08H()		bfin_read16(CAN1_AM08H)
-#define bfin_write_CAN1_AM08H(val)	bfin_write16(CAN1_AM08H, val)
-#define bfin_read_CAN1_AM09L()		bfin_read16(CAN1_AM09L)
-#define bfin_write_CAN1_AM09L(val)	bfin_write16(CAN1_AM09L, val)
-#define bfin_read_CAN1_AM09H()		bfin_read16(CAN1_AM09H)
-#define bfin_write_CAN1_AM09H(val)	bfin_write16(CAN1_AM09H, val)
-#define bfin_read_CAN1_AM10L()		bfin_read16(CAN1_AM10L)
-#define bfin_write_CAN1_AM10L(val)	bfin_write16(CAN1_AM10L, val)
-#define bfin_read_CAN1_AM10H()		bfin_read16(CAN1_AM10H)
-#define bfin_write_CAN1_AM10H(val)	bfin_write16(CAN1_AM10H, val)
-#define bfin_read_CAN1_AM11L()		bfin_read16(CAN1_AM11L)
-#define bfin_write_CAN1_AM11L(val)	bfin_write16(CAN1_AM11L, val)
-#define bfin_read_CAN1_AM11H()		bfin_read16(CAN1_AM11H)
-#define bfin_write_CAN1_AM11H(val)	bfin_write16(CAN1_AM11H, val)
-#define bfin_read_CAN1_AM12L()		bfin_read16(CAN1_AM12L)
-#define bfin_write_CAN1_AM12L(val)	bfin_write16(CAN1_AM12L, val)
-#define bfin_read_CAN1_AM12H()		bfin_read16(CAN1_AM12H)
-#define bfin_write_CAN1_AM12H(val)	bfin_write16(CAN1_AM12H, val)
-#define bfin_read_CAN1_AM13L()		bfin_read16(CAN1_AM13L)
-#define bfin_write_CAN1_AM13L(val)	bfin_write16(CAN1_AM13L, val)
-#define bfin_read_CAN1_AM13H()		bfin_read16(CAN1_AM13H)
-#define bfin_write_CAN1_AM13H(val)	bfin_write16(CAN1_AM13H, val)
-#define bfin_read_CAN1_AM14L()		bfin_read16(CAN1_AM14L)
-#define bfin_write_CAN1_AM14L(val)	bfin_write16(CAN1_AM14L, val)
-#define bfin_read_CAN1_AM14H()		bfin_read16(CAN1_AM14H)
-#define bfin_write_CAN1_AM14H(val)	bfin_write16(CAN1_AM14H, val)
-#define bfin_read_CAN1_AM15L()		bfin_read16(CAN1_AM15L)
-#define bfin_write_CAN1_AM15L(val)	bfin_write16(CAN1_AM15L, val)
-#define bfin_read_CAN1_AM15H()		bfin_read16(CAN1_AM15H)
-#define bfin_write_CAN1_AM15H(val)	bfin_write16(CAN1_AM15H, val)
-
-/* CAN Controller 1 Mailbox Accebfin_read_()tance Registers */
-
-#define bfin_read_CAN1_AM16L()		bfin_read16(CAN1_AM16L)
-#define bfin_write_CAN1_AM16L(val)	bfin_write16(CAN1_AM16L, val)
-#define bfin_read_CAN1_AM16H()		bfin_read16(CAN1_AM16H)
-#define bfin_write_CAN1_AM16H(val)	bfin_write16(CAN1_AM16H, val)
-#define bfin_read_CAN1_AM17L()		bfin_read16(CAN1_AM17L)
-#define bfin_write_CAN1_AM17L(val)	bfin_write16(CAN1_AM17L, val)
-#define bfin_read_CAN1_AM17H()		bfin_read16(CAN1_AM17H)
-#define bfin_write_CAN1_AM17H(val)	bfin_write16(CAN1_AM17H, val)
-#define bfin_read_CAN1_AM18L()		bfin_read16(CAN1_AM18L)
-#define bfin_write_CAN1_AM18L(val)	bfin_write16(CAN1_AM18L, val)
-#define bfin_read_CAN1_AM18H()		bfin_read16(CAN1_AM18H)
-#define bfin_write_CAN1_AM18H(val)	bfin_write16(CAN1_AM18H, val)
-#define bfin_read_CAN1_AM19L()		bfin_read16(CAN1_AM19L)
-#define bfin_write_CAN1_AM19L(val)	bfin_write16(CAN1_AM19L, val)
-#define bfin_read_CAN1_AM19H()		bfin_read16(CAN1_AM19H)
-#define bfin_write_CAN1_AM19H(val)	bfin_write16(CAN1_AM19H, val)
-#define bfin_read_CAN1_AM20L()		bfin_read16(CAN1_AM20L)
-#define bfin_write_CAN1_AM20L(val)	bfin_write16(CAN1_AM20L, val)
-#define bfin_read_CAN1_AM20H()		bfin_read16(CAN1_AM20H)
-#define bfin_write_CAN1_AM20H(val)	bfin_write16(CAN1_AM20H, val)
-#define bfin_read_CAN1_AM21L()		bfin_read16(CAN1_AM21L)
-#define bfin_write_CAN1_AM21L(val)	bfin_write16(CAN1_AM21L, val)
-#define bfin_read_CAN1_AM21H()		bfin_read16(CAN1_AM21H)
-#define bfin_write_CAN1_AM21H(val)	bfin_write16(CAN1_AM21H, val)
-#define bfin_read_CAN1_AM22L()		bfin_read16(CAN1_AM22L)
-#define bfin_write_CAN1_AM22L(val)	bfin_write16(CAN1_AM22L, val)
-#define bfin_read_CAN1_AM22H()		bfin_read16(CAN1_AM22H)
-#define bfin_write_CAN1_AM22H(val)	bfin_write16(CAN1_AM22H, val)
-#define bfin_read_CAN1_AM23L()		bfin_read16(CAN1_AM23L)
-#define bfin_write_CAN1_AM23L(val)	bfin_write16(CAN1_AM23L, val)
-#define bfin_read_CAN1_AM23H()		bfin_read16(CAN1_AM23H)
-#define bfin_write_CAN1_AM23H(val)	bfin_write16(CAN1_AM23H, val)
-#define bfin_read_CAN1_AM24L()		bfin_read16(CAN1_AM24L)
-#define bfin_write_CAN1_AM24L(val)	bfin_write16(CAN1_AM24L, val)
-#define bfin_read_CAN1_AM24H()		bfin_read16(CAN1_AM24H)
-#define bfin_write_CAN1_AM24H(val)	bfin_write16(CAN1_AM24H, val)
-#define bfin_read_CAN1_AM25L()		bfin_read16(CAN1_AM25L)
-#define bfin_write_CAN1_AM25L(val)	bfin_write16(CAN1_AM25L, val)
-#define bfin_read_CAN1_AM25H()		bfin_read16(CAN1_AM25H)
-#define bfin_write_CAN1_AM25H(val)	bfin_write16(CAN1_AM25H, val)
-#define bfin_read_CAN1_AM26L()		bfin_read16(CAN1_AM26L)
-#define bfin_write_CAN1_AM26L(val)	bfin_write16(CAN1_AM26L, val)
-#define bfin_read_CAN1_AM26H()		bfin_read16(CAN1_AM26H)
-#define bfin_write_CAN1_AM26H(val)	bfin_write16(CAN1_AM26H, val)
-#define bfin_read_CAN1_AM27L()		bfin_read16(CAN1_AM27L)
-#define bfin_write_CAN1_AM27L(val)	bfin_write16(CAN1_AM27L, val)
-#define bfin_read_CAN1_AM27H()		bfin_read16(CAN1_AM27H)
-#define bfin_write_CAN1_AM27H(val)	bfin_write16(CAN1_AM27H, val)
-#define bfin_read_CAN1_AM28L()		bfin_read16(CAN1_AM28L)
-#define bfin_write_CAN1_AM28L(val)	bfin_write16(CAN1_AM28L, val)
-#define bfin_read_CAN1_AM28H()		bfin_read16(CAN1_AM28H)
-#define bfin_write_CAN1_AM28H(val)	bfin_write16(CAN1_AM28H, val)
-#define bfin_read_CAN1_AM29L()		bfin_read16(CAN1_AM29L)
-#define bfin_write_CAN1_AM29L(val)	bfin_write16(CAN1_AM29L, val)
-#define bfin_read_CAN1_AM29H()		bfin_read16(CAN1_AM29H)
-#define bfin_write_CAN1_AM29H(val)	bfin_write16(CAN1_AM29H, val)
-#define bfin_read_CAN1_AM30L()		bfin_read16(CAN1_AM30L)
-#define bfin_write_CAN1_AM30L(val)	bfin_write16(CAN1_AM30L, val)
-#define bfin_read_CAN1_AM30H()		bfin_read16(CAN1_AM30H)
-#define bfin_write_CAN1_AM30H(val)	bfin_write16(CAN1_AM30H, val)
-#define bfin_read_CAN1_AM31L()		bfin_read16(CAN1_AM31L)
-#define bfin_write_CAN1_AM31L(val)	bfin_write16(CAN1_AM31L, val)
-#define bfin_read_CAN1_AM31H()		bfin_read16(CAN1_AM31H)
-#define bfin_write_CAN1_AM31H(val)	bfin_write16(CAN1_AM31H, val)
-
-/* CAN Controller 1 Mailbox Data Registers */
-
-#define bfin_read_CAN1_MB00_DATA0()		bfin_read16(CAN1_MB00_DATA0)
-#define bfin_write_CAN1_MB00_DATA0(val)		bfin_write16(CAN1_MB00_DATA0, val)
-#define bfin_read_CAN1_MB00_DATA1()		bfin_read16(CAN1_MB00_DATA1)
-#define bfin_write_CAN1_MB00_DATA1(val)		bfin_write16(CAN1_MB00_DATA1, val)
-#define bfin_read_CAN1_MB00_DATA2()		bfin_read16(CAN1_MB00_DATA2)
-#define bfin_write_CAN1_MB00_DATA2(val)		bfin_write16(CAN1_MB00_DATA2, val)
-#define bfin_read_CAN1_MB00_DATA3()		bfin_read16(CAN1_MB00_DATA3)
-#define bfin_write_CAN1_MB00_DATA3(val)		bfin_write16(CAN1_MB00_DATA3, val)
-#define bfin_read_CAN1_MB00_LENGTH()		bfin_read16(CAN1_MB00_LENGTH)
-#define bfin_write_CAN1_MB00_LENGTH(val)	bfin_write16(CAN1_MB00_LENGTH, val)
-#define bfin_read_CAN1_MB00_TIMESTAMP()		bfin_read16(CAN1_MB00_TIMESTAMP)
-#define bfin_write_CAN1_MB00_TIMESTAMP(val)	bfin_write16(CAN1_MB00_TIMESTAMP, val)
-#define bfin_read_CAN1_MB00_ID0()		bfin_read16(CAN1_MB00_ID0)
-#define bfin_write_CAN1_MB00_ID0(val)		bfin_write16(CAN1_MB00_ID0, val)
-#define bfin_read_CAN1_MB00_ID1()		bfin_read16(CAN1_MB00_ID1)
-#define bfin_write_CAN1_MB00_ID1(val)		bfin_write16(CAN1_MB00_ID1, val)
-#define bfin_read_CAN1_MB01_DATA0()		bfin_read16(CAN1_MB01_DATA0)
-#define bfin_write_CAN1_MB01_DATA0(val)		bfin_write16(CAN1_MB01_DATA0, val)
-#define bfin_read_CAN1_MB01_DATA1()		bfin_read16(CAN1_MB01_DATA1)
-#define bfin_write_CAN1_MB01_DATA1(val)		bfin_write16(CAN1_MB01_DATA1, val)
-#define bfin_read_CAN1_MB01_DATA2()		bfin_read16(CAN1_MB01_DATA2)
-#define bfin_write_CAN1_MB01_DATA2(val)		bfin_write16(CAN1_MB01_DATA2, val)
-#define bfin_read_CAN1_MB01_DATA3()		bfin_read16(CAN1_MB01_DATA3)
-#define bfin_write_CAN1_MB01_DATA3(val)		bfin_write16(CAN1_MB01_DATA3, val)
-#define bfin_read_CAN1_MB01_LENGTH()		bfin_read16(CAN1_MB01_LENGTH)
-#define bfin_write_CAN1_MB01_LENGTH(val)	bfin_write16(CAN1_MB01_LENGTH, val)
-#define bfin_read_CAN1_MB01_TIMESTAMP()		bfin_read16(CAN1_MB01_TIMESTAMP)
-#define bfin_write_CAN1_MB01_TIMESTAMP(val)	bfin_write16(CAN1_MB01_TIMESTAMP, val)
-#define bfin_read_CAN1_MB01_ID0()		bfin_read16(CAN1_MB01_ID0)
-#define bfin_write_CAN1_MB01_ID0(val)		bfin_write16(CAN1_MB01_ID0, val)
-#define bfin_read_CAN1_MB01_ID1()		bfin_read16(CAN1_MB01_ID1)
-#define bfin_write_CAN1_MB01_ID1(val)		bfin_write16(CAN1_MB01_ID1, val)
-#define bfin_read_CAN1_MB02_DATA0()		bfin_read16(CAN1_MB02_DATA0)
-#define bfin_write_CAN1_MB02_DATA0(val)		bfin_write16(CAN1_MB02_DATA0, val)
-#define bfin_read_CAN1_MB02_DATA1()		bfin_read16(CAN1_MB02_DATA1)
-#define bfin_write_CAN1_MB02_DATA1(val)		bfin_write16(CAN1_MB02_DATA1, val)
-#define bfin_read_CAN1_MB02_DATA2()		bfin_read16(CAN1_MB02_DATA2)
-#define bfin_write_CAN1_MB02_DATA2(val)		bfin_write16(CAN1_MB02_DATA2, val)
-#define bfin_read_CAN1_MB02_DATA3()		bfin_read16(CAN1_MB02_DATA3)
-#define bfin_write_CAN1_MB02_DATA3(val)		bfin_write16(CAN1_MB02_DATA3, val)
-#define bfin_read_CAN1_MB02_LENGTH()		bfin_read16(CAN1_MB02_LENGTH)
-#define bfin_write_CAN1_MB02_LENGTH(val)	bfin_write16(CAN1_MB02_LENGTH, val)
-#define bfin_read_CAN1_MB02_TIMESTAMP()		bfin_read16(CAN1_MB02_TIMESTAMP)
-#define bfin_write_CAN1_MB02_TIMESTAMP(val)	bfin_write16(CAN1_MB02_TIMESTAMP, val)
-#define bfin_read_CAN1_MB02_ID0()		bfin_read16(CAN1_MB02_ID0)
-#define bfin_write_CAN1_MB02_ID0(val)		bfin_write16(CAN1_MB02_ID0, val)
-#define bfin_read_CAN1_MB02_ID1()		bfin_read16(CAN1_MB02_ID1)
-#define bfin_write_CAN1_MB02_ID1(val)		bfin_write16(CAN1_MB02_ID1, val)
-#define bfin_read_CAN1_MB03_DATA0()		bfin_read16(CAN1_MB03_DATA0)
-#define bfin_write_CAN1_MB03_DATA0(val)		bfin_write16(CAN1_MB03_DATA0, val)
-#define bfin_read_CAN1_MB03_DATA1()		bfin_read16(CAN1_MB03_DATA1)
-#define bfin_write_CAN1_MB03_DATA1(val)		bfin_write16(CAN1_MB03_DATA1, val)
-#define bfin_read_CAN1_MB03_DATA2()		bfin_read16(CAN1_MB03_DATA2)
-#define bfin_write_CAN1_MB03_DATA2(val)		bfin_write16(CAN1_MB03_DATA2, val)
-#define bfin_read_CAN1_MB03_DATA3()		bfin_read16(CAN1_MB03_DATA3)
-#define bfin_write_CAN1_MB03_DATA3(val)		bfin_write16(CAN1_MB03_DATA3, val)
-#define bfin_read_CAN1_MB03_LENGTH()		bfin_read16(CAN1_MB03_LENGTH)
-#define bfin_write_CAN1_MB03_LENGTH(val)	bfin_write16(CAN1_MB03_LENGTH, val)
-#define bfin_read_CAN1_MB03_TIMESTAMP()		bfin_read16(CAN1_MB03_TIMESTAMP)
-#define bfin_write_CAN1_MB03_TIMESTAMP(val)	bfin_write16(CAN1_MB03_TIMESTAMP, val)
-#define bfin_read_CAN1_MB03_ID0()		bfin_read16(CAN1_MB03_ID0)
-#define bfin_write_CAN1_MB03_ID0(val)		bfin_write16(CAN1_MB03_ID0, val)
-#define bfin_read_CAN1_MB03_ID1()		bfin_read16(CAN1_MB03_ID1)
-#define bfin_write_CAN1_MB03_ID1(val)		bfin_write16(CAN1_MB03_ID1, val)
-#define bfin_read_CAN1_MB04_DATA0()		bfin_read16(CAN1_MB04_DATA0)
-#define bfin_write_CAN1_MB04_DATA0(val)		bfin_write16(CAN1_MB04_DATA0, val)
-#define bfin_read_CAN1_MB04_DATA1()		bfin_read16(CAN1_MB04_DATA1)
-#define bfin_write_CAN1_MB04_DATA1(val)		bfin_write16(CAN1_MB04_DATA1, val)
-#define bfin_read_CAN1_MB04_DATA2()		bfin_read16(CAN1_MB04_DATA2)
-#define bfin_write_CAN1_MB04_DATA2(val)		bfin_write16(CAN1_MB04_DATA2, val)
-#define bfin_read_CAN1_MB04_DATA3()		bfin_read16(CAN1_MB04_DATA3)
-#define bfin_write_CAN1_MB04_DATA3(val)		bfin_write16(CAN1_MB04_DATA3, val)
-#define bfin_read_CAN1_MB04_LENGTH()		bfin_read16(CAN1_MB04_LENGTH)
-#define bfin_write_CAN1_MB04_LENGTH(val)	bfin_write16(CAN1_MB04_LENGTH, val)
-#define bfin_read_CAN1_MB04_TIMESTAMP()		bfin_read16(CAN1_MB04_TIMESTAMP)
-#define bfin_write_CAN1_MB04_TIMESTAMP(val)	bfin_write16(CAN1_MB04_TIMESTAMP, val)
-#define bfin_read_CAN1_MB04_ID0()		bfin_read16(CAN1_MB04_ID0)
-#define bfin_write_CAN1_MB04_ID0(val)		bfin_write16(CAN1_MB04_ID0, val)
-#define bfin_read_CAN1_MB04_ID1()		bfin_read16(CAN1_MB04_ID1)
-#define bfin_write_CAN1_MB04_ID1(val)		bfin_write16(CAN1_MB04_ID1, val)
-#define bfin_read_CAN1_MB05_DATA0()		bfin_read16(CAN1_MB05_DATA0)
-#define bfin_write_CAN1_MB05_DATA0(val)		bfin_write16(CAN1_MB05_DATA0, val)
-#define bfin_read_CAN1_MB05_DATA1()		bfin_read16(CAN1_MB05_DATA1)
-#define bfin_write_CAN1_MB05_DATA1(val)		bfin_write16(CAN1_MB05_DATA1, val)
-#define bfin_read_CAN1_MB05_DATA2()		bfin_read16(CAN1_MB05_DATA2)
-#define bfin_write_CAN1_MB05_DATA2(val)		bfin_write16(CAN1_MB05_DATA2, val)
-#define bfin_read_CAN1_MB05_DATA3()		bfin_read16(CAN1_MB05_DATA3)
-#define bfin_write_CAN1_MB05_DATA3(val)		bfin_write16(CAN1_MB05_DATA3, val)
-#define bfin_read_CAN1_MB05_LENGTH()		bfin_read16(CAN1_MB05_LENGTH)
-#define bfin_write_CAN1_MB05_LENGTH(val)	bfin_write16(CAN1_MB05_LENGTH, val)
-#define bfin_read_CAN1_MB05_TIMESTAMP()		bfin_read16(CAN1_MB05_TIMESTAMP)
-#define bfin_write_CAN1_MB05_TIMESTAMP(val)	bfin_write16(CAN1_MB05_TIMESTAMP, val)
-#define bfin_read_CAN1_MB05_ID0()		bfin_read16(CAN1_MB05_ID0)
-#define bfin_write_CAN1_MB05_ID0(val)		bfin_write16(CAN1_MB05_ID0, val)
-#define bfin_read_CAN1_MB05_ID1()		bfin_read16(CAN1_MB05_ID1)
-#define bfin_write_CAN1_MB05_ID1(val)		bfin_write16(CAN1_MB05_ID1, val)
-#define bfin_read_CAN1_MB06_DATA0()		bfin_read16(CAN1_MB06_DATA0)
-#define bfin_write_CAN1_MB06_DATA0(val)		bfin_write16(CAN1_MB06_DATA0, val)
-#define bfin_read_CAN1_MB06_DATA1()		bfin_read16(CAN1_MB06_DATA1)
-#define bfin_write_CAN1_MB06_DATA1(val)		bfin_write16(CAN1_MB06_DATA1, val)
-#define bfin_read_CAN1_MB06_DATA2()		bfin_read16(CAN1_MB06_DATA2)
-#define bfin_write_CAN1_MB06_DATA2(val)		bfin_write16(CAN1_MB06_DATA2, val)
-#define bfin_read_CAN1_MB06_DATA3()		bfin_read16(CAN1_MB06_DATA3)
-#define bfin_write_CAN1_MB06_DATA3(val)		bfin_write16(CAN1_MB06_DATA3, val)
-#define bfin_read_CAN1_MB06_LENGTH()		bfin_read16(CAN1_MB06_LENGTH)
-#define bfin_write_CAN1_MB06_LENGTH(val)	bfin_write16(CAN1_MB06_LENGTH, val)
-#define bfin_read_CAN1_MB06_TIMESTAMP()		bfin_read16(CAN1_MB06_TIMESTAMP)
-#define bfin_write_CAN1_MB06_TIMESTAMP(val)	bfin_write16(CAN1_MB06_TIMESTAMP, val)
-#define bfin_read_CAN1_MB06_ID0()		bfin_read16(CAN1_MB06_ID0)
-#define bfin_write_CAN1_MB06_ID0(val)		bfin_write16(CAN1_MB06_ID0, val)
-#define bfin_read_CAN1_MB06_ID1()		bfin_read16(CAN1_MB06_ID1)
-#define bfin_write_CAN1_MB06_ID1(val)		bfin_write16(CAN1_MB06_ID1, val)
-#define bfin_read_CAN1_MB07_DATA0()		bfin_read16(CAN1_MB07_DATA0)
-#define bfin_write_CAN1_MB07_DATA0(val)		bfin_write16(CAN1_MB07_DATA0, val)
-#define bfin_read_CAN1_MB07_DATA1()		bfin_read16(CAN1_MB07_DATA1)
-#define bfin_write_CAN1_MB07_DATA1(val)		bfin_write16(CAN1_MB07_DATA1, val)
-#define bfin_read_CAN1_MB07_DATA2()		bfin_read16(CAN1_MB07_DATA2)
-#define bfin_write_CAN1_MB07_DATA2(val)		bfin_write16(CAN1_MB07_DATA2, val)
-#define bfin_read_CAN1_MB07_DATA3()		bfin_read16(CAN1_MB07_DATA3)
-#define bfin_write_CAN1_MB07_DATA3(val)		bfin_write16(CAN1_MB07_DATA3, val)
-#define bfin_read_CAN1_MB07_LENGTH()		bfin_read16(CAN1_MB07_LENGTH)
-#define bfin_write_CAN1_MB07_LENGTH(val)	bfin_write16(CAN1_MB07_LENGTH, val)
-#define bfin_read_CAN1_MB07_TIMESTAMP()		bfin_read16(CAN1_MB07_TIMESTAMP)
-#define bfin_write_CAN1_MB07_TIMESTAMP(val)	bfin_write16(CAN1_MB07_TIMESTAMP, val)
-#define bfin_read_CAN1_MB07_ID0()		bfin_read16(CAN1_MB07_ID0)
-#define bfin_write_CAN1_MB07_ID0(val)		bfin_write16(CAN1_MB07_ID0, val)
-#define bfin_read_CAN1_MB07_ID1()		bfin_read16(CAN1_MB07_ID1)
-#define bfin_write_CAN1_MB07_ID1(val)		bfin_write16(CAN1_MB07_ID1, val)
-#define bfin_read_CAN1_MB08_DATA0()		bfin_read16(CAN1_MB08_DATA0)
-#define bfin_write_CAN1_MB08_DATA0(val)		bfin_write16(CAN1_MB08_DATA0, val)
-#define bfin_read_CAN1_MB08_DATA1()		bfin_read16(CAN1_MB08_DATA1)
-#define bfin_write_CAN1_MB08_DATA1(val)		bfin_write16(CAN1_MB08_DATA1, val)
-#define bfin_read_CAN1_MB08_DATA2()		bfin_read16(CAN1_MB08_DATA2)
-#define bfin_write_CAN1_MB08_DATA2(val)		bfin_write16(CAN1_MB08_DATA2, val)
-#define bfin_read_CAN1_MB08_DATA3()		bfin_read16(CAN1_MB08_DATA3)
-#define bfin_write_CAN1_MB08_DATA3(val)		bfin_write16(CAN1_MB08_DATA3, val)
-#define bfin_read_CAN1_MB08_LENGTH()		bfin_read16(CAN1_MB08_LENGTH)
-#define bfin_write_CAN1_MB08_LENGTH(val)	bfin_write16(CAN1_MB08_LENGTH, val)
-#define bfin_read_CAN1_MB08_TIMESTAMP()		bfin_read16(CAN1_MB08_TIMESTAMP)
-#define bfin_write_CAN1_MB08_TIMESTAMP(val)	bfin_write16(CAN1_MB08_TIMESTAMP, val)
-#define bfin_read_CAN1_MB08_ID0()		bfin_read16(CAN1_MB08_ID0)
-#define bfin_write_CAN1_MB08_ID0(val)		bfin_write16(CAN1_MB08_ID0, val)
-#define bfin_read_CAN1_MB08_ID1()		bfin_read16(CAN1_MB08_ID1)
-#define bfin_write_CAN1_MB08_ID1(val)		bfin_write16(CAN1_MB08_ID1, val)
-#define bfin_read_CAN1_MB09_DATA0()		bfin_read16(CAN1_MB09_DATA0)
-#define bfin_write_CAN1_MB09_DATA0(val)		bfin_write16(CAN1_MB09_DATA0, val)
-#define bfin_read_CAN1_MB09_DATA1()		bfin_read16(CAN1_MB09_DATA1)
-#define bfin_write_CAN1_MB09_DATA1(val)		bfin_write16(CAN1_MB09_DATA1, val)
-#define bfin_read_CAN1_MB09_DATA2()		bfin_read16(CAN1_MB09_DATA2)
-#define bfin_write_CAN1_MB09_DATA2(val)		bfin_write16(CAN1_MB09_DATA2, val)
-#define bfin_read_CAN1_MB09_DATA3()		bfin_read16(CAN1_MB09_DATA3)
-#define bfin_write_CAN1_MB09_DATA3(val)		bfin_write16(CAN1_MB09_DATA3, val)
-#define bfin_read_CAN1_MB09_LENGTH()		bfin_read16(CAN1_MB09_LENGTH)
-#define bfin_write_CAN1_MB09_LENGTH(val)	bfin_write16(CAN1_MB09_LENGTH, val)
-#define bfin_read_CAN1_MB09_TIMESTAMP()		bfin_read16(CAN1_MB09_TIMESTAMP)
-#define bfin_write_CAN1_MB09_TIMESTAMP(val)	bfin_write16(CAN1_MB09_TIMESTAMP, val)
-#define bfin_read_CAN1_MB09_ID0()		bfin_read16(CAN1_MB09_ID0)
-#define bfin_write_CAN1_MB09_ID0(val)		bfin_write16(CAN1_MB09_ID0, val)
-#define bfin_read_CAN1_MB09_ID1()		bfin_read16(CAN1_MB09_ID1)
-#define bfin_write_CAN1_MB09_ID1(val)		bfin_write16(CAN1_MB09_ID1, val)
-#define bfin_read_CAN1_MB10_DATA0()		bfin_read16(CAN1_MB10_DATA0)
-#define bfin_write_CAN1_MB10_DATA0(val)		bfin_write16(CAN1_MB10_DATA0, val)
-#define bfin_read_CAN1_MB10_DATA1()		bfin_read16(CAN1_MB10_DATA1)
-#define bfin_write_CAN1_MB10_DATA1(val)		bfin_write16(CAN1_MB10_DATA1, val)
-#define bfin_read_CAN1_MB10_DATA2()		bfin_read16(CAN1_MB10_DATA2)
-#define bfin_write_CAN1_MB10_DATA2(val)		bfin_write16(CAN1_MB10_DATA2, val)
-#define bfin_read_CAN1_MB10_DATA3()		bfin_read16(CAN1_MB10_DATA3)
-#define bfin_write_CAN1_MB10_DATA3(val)		bfin_write16(CAN1_MB10_DATA3, val)
-#define bfin_read_CAN1_MB10_LENGTH()		bfin_read16(CAN1_MB10_LENGTH)
-#define bfin_write_CAN1_MB10_LENGTH(val)	bfin_write16(CAN1_MB10_LENGTH, val)
-#define bfin_read_CAN1_MB10_TIMESTAMP()		bfin_read16(CAN1_MB10_TIMESTAMP)
-#define bfin_write_CAN1_MB10_TIMESTAMP(val)	bfin_write16(CAN1_MB10_TIMESTAMP, val)
-#define bfin_read_CAN1_MB10_ID0()		bfin_read16(CAN1_MB10_ID0)
-#define bfin_write_CAN1_MB10_ID0(val)		bfin_write16(CAN1_MB10_ID0, val)
-#define bfin_read_CAN1_MB10_ID1()		bfin_read16(CAN1_MB10_ID1)
-#define bfin_write_CAN1_MB10_ID1(val)		bfin_write16(CAN1_MB10_ID1, val)
-#define bfin_read_CAN1_MB11_DATA0()		bfin_read16(CAN1_MB11_DATA0)
-#define bfin_write_CAN1_MB11_DATA0(val)		bfin_write16(CAN1_MB11_DATA0, val)
-#define bfin_read_CAN1_MB11_DATA1()		bfin_read16(CAN1_MB11_DATA1)
-#define bfin_write_CAN1_MB11_DATA1(val)		bfin_write16(CAN1_MB11_DATA1, val)
-#define bfin_read_CAN1_MB11_DATA2()		bfin_read16(CAN1_MB11_DATA2)
-#define bfin_write_CAN1_MB11_DATA2(val)		bfin_write16(CAN1_MB11_DATA2, val)
-#define bfin_read_CAN1_MB11_DATA3()		bfin_read16(CAN1_MB11_DATA3)
-#define bfin_write_CAN1_MB11_DATA3(val)		bfin_write16(CAN1_MB11_DATA3, val)
-#define bfin_read_CAN1_MB11_LENGTH()		bfin_read16(CAN1_MB11_LENGTH)
-#define bfin_write_CAN1_MB11_LENGTH(val)	bfin_write16(CAN1_MB11_LENGTH, val)
-#define bfin_read_CAN1_MB11_TIMESTAMP()		bfin_read16(CAN1_MB11_TIMESTAMP)
-#define bfin_write_CAN1_MB11_TIMESTAMP(val)	bfin_write16(CAN1_MB11_TIMESTAMP, val)
-#define bfin_read_CAN1_MB11_ID0()		bfin_read16(CAN1_MB11_ID0)
-#define bfin_write_CAN1_MB11_ID0(val)		bfin_write16(CAN1_MB11_ID0, val)
-#define bfin_read_CAN1_MB11_ID1()		bfin_read16(CAN1_MB11_ID1)
-#define bfin_write_CAN1_MB11_ID1(val)		bfin_write16(CAN1_MB11_ID1, val)
-#define bfin_read_CAN1_MB12_DATA0()		bfin_read16(CAN1_MB12_DATA0)
-#define bfin_write_CAN1_MB12_DATA0(val)		bfin_write16(CAN1_MB12_DATA0, val)
-#define bfin_read_CAN1_MB12_DATA1()		bfin_read16(CAN1_MB12_DATA1)
-#define bfin_write_CAN1_MB12_DATA1(val)		bfin_write16(CAN1_MB12_DATA1, val)
-#define bfin_read_CAN1_MB12_DATA2()		bfin_read16(CAN1_MB12_DATA2)
-#define bfin_write_CAN1_MB12_DATA2(val)		bfin_write16(CAN1_MB12_DATA2, val)
-#define bfin_read_CAN1_MB12_DATA3()		bfin_read16(CAN1_MB12_DATA3)
-#define bfin_write_CAN1_MB12_DATA3(val)		bfin_write16(CAN1_MB12_DATA3, val)
-#define bfin_read_CAN1_MB12_LENGTH()		bfin_read16(CAN1_MB12_LENGTH)
-#define bfin_write_CAN1_MB12_LENGTH(val)	bfin_write16(CAN1_MB12_LENGTH, val)
-#define bfin_read_CAN1_MB12_TIMESTAMP()		bfin_read16(CAN1_MB12_TIMESTAMP)
-#define bfin_write_CAN1_MB12_TIMESTAMP(val)	bfin_write16(CAN1_MB12_TIMESTAMP, val)
-#define bfin_read_CAN1_MB12_ID0()		bfin_read16(CAN1_MB12_ID0)
-#define bfin_write_CAN1_MB12_ID0(val)		bfin_write16(CAN1_MB12_ID0, val)
-#define bfin_read_CAN1_MB12_ID1()		bfin_read16(CAN1_MB12_ID1)
-#define bfin_write_CAN1_MB12_ID1(val)		bfin_write16(CAN1_MB12_ID1, val)
-#define bfin_read_CAN1_MB13_DATA0()		bfin_read16(CAN1_MB13_DATA0)
-#define bfin_write_CAN1_MB13_DATA0(val)		bfin_write16(CAN1_MB13_DATA0, val)
-#define bfin_read_CAN1_MB13_DATA1()		bfin_read16(CAN1_MB13_DATA1)
-#define bfin_write_CAN1_MB13_DATA1(val)		bfin_write16(CAN1_MB13_DATA1, val)
-#define bfin_read_CAN1_MB13_DATA2()		bfin_read16(CAN1_MB13_DATA2)
-#define bfin_write_CAN1_MB13_DATA2(val)		bfin_write16(CAN1_MB13_DATA2, val)
-#define bfin_read_CAN1_MB13_DATA3()		bfin_read16(CAN1_MB13_DATA3)
-#define bfin_write_CAN1_MB13_DATA3(val)		bfin_write16(CAN1_MB13_DATA3, val)
-#define bfin_read_CAN1_MB13_LENGTH()		bfin_read16(CAN1_MB13_LENGTH)
-#define bfin_write_CAN1_MB13_LENGTH(val)	bfin_write16(CAN1_MB13_LENGTH, val)
-#define bfin_read_CAN1_MB13_TIMESTAMP()		bfin_read16(CAN1_MB13_TIMESTAMP)
-#define bfin_write_CAN1_MB13_TIMESTAMP(val)	bfin_write16(CAN1_MB13_TIMESTAMP, val)
-#define bfin_read_CAN1_MB13_ID0()		bfin_read16(CAN1_MB13_ID0)
-#define bfin_write_CAN1_MB13_ID0(val)		bfin_write16(CAN1_MB13_ID0, val)
-#define bfin_read_CAN1_MB13_ID1()		bfin_read16(CAN1_MB13_ID1)
-#define bfin_write_CAN1_MB13_ID1(val)		bfin_write16(CAN1_MB13_ID1, val)
-#define bfin_read_CAN1_MB14_DATA0()		bfin_read16(CAN1_MB14_DATA0)
-#define bfin_write_CAN1_MB14_DATA0(val)		bfin_write16(CAN1_MB14_DATA0, val)
-#define bfin_read_CAN1_MB14_DATA1()		bfin_read16(CAN1_MB14_DATA1)
-#define bfin_write_CAN1_MB14_DATA1(val)		bfin_write16(CAN1_MB14_DATA1, val)
-#define bfin_read_CAN1_MB14_DATA2()		bfin_read16(CAN1_MB14_DATA2)
-#define bfin_write_CAN1_MB14_DATA2(val)		bfin_write16(CAN1_MB14_DATA2, val)
-#define bfin_read_CAN1_MB14_DATA3()		bfin_read16(CAN1_MB14_DATA3)
-#define bfin_write_CAN1_MB14_DATA3(val)		bfin_write16(CAN1_MB14_DATA3, val)
-#define bfin_read_CAN1_MB14_LENGTH()		bfin_read16(CAN1_MB14_LENGTH)
-#define bfin_write_CAN1_MB14_LENGTH(val)	bfin_write16(CAN1_MB14_LENGTH, val)
-#define bfin_read_CAN1_MB14_TIMESTAMP()		bfin_read16(CAN1_MB14_TIMESTAMP)
-#define bfin_write_CAN1_MB14_TIMESTAMP(val)	bfin_write16(CAN1_MB14_TIMESTAMP, val)
-#define bfin_read_CAN1_MB14_ID0()		bfin_read16(CAN1_MB14_ID0)
-#define bfin_write_CAN1_MB14_ID0(val)		bfin_write16(CAN1_MB14_ID0, val)
-#define bfin_read_CAN1_MB14_ID1()		bfin_read16(CAN1_MB14_ID1)
-#define bfin_write_CAN1_MB14_ID1(val)		bfin_write16(CAN1_MB14_ID1, val)
-#define bfin_read_CAN1_MB15_DATA0()		bfin_read16(CAN1_MB15_DATA0)
-#define bfin_write_CAN1_MB15_DATA0(val)		bfin_write16(CAN1_MB15_DATA0, val)
-#define bfin_read_CAN1_MB15_DATA1()		bfin_read16(CAN1_MB15_DATA1)
-#define bfin_write_CAN1_MB15_DATA1(val)		bfin_write16(CAN1_MB15_DATA1, val)
-#define bfin_read_CAN1_MB15_DATA2()		bfin_read16(CAN1_MB15_DATA2)
-#define bfin_write_CAN1_MB15_DATA2(val)		bfin_write16(CAN1_MB15_DATA2, val)
-#define bfin_read_CAN1_MB15_DATA3()		bfin_read16(CAN1_MB15_DATA3)
-#define bfin_write_CAN1_MB15_DATA3(val)		bfin_write16(CAN1_MB15_DATA3, val)
-#define bfin_read_CAN1_MB15_LENGTH()		bfin_read16(CAN1_MB15_LENGTH)
-#define bfin_write_CAN1_MB15_LENGTH(val)	bfin_write16(CAN1_MB15_LENGTH, val)
-#define bfin_read_CAN1_MB15_TIMESTAMP()		bfin_read16(CAN1_MB15_TIMESTAMP)
-#define bfin_write_CAN1_MB15_TIMESTAMP(val)	bfin_write16(CAN1_MB15_TIMESTAMP, val)
-#define bfin_read_CAN1_MB15_ID0()		bfin_read16(CAN1_MB15_ID0)
-#define bfin_write_CAN1_MB15_ID0(val)		bfin_write16(CAN1_MB15_ID0, val)
-#define bfin_read_CAN1_MB15_ID1()		bfin_read16(CAN1_MB15_ID1)
-#define bfin_write_CAN1_MB15_ID1(val)		bfin_write16(CAN1_MB15_ID1, val)
-
-/* CAN Controller 1 Mailbox Data Registers */
-
-#define bfin_read_CAN1_MB16_DATA0()		bfin_read16(CAN1_MB16_DATA0)
-#define bfin_write_CAN1_MB16_DATA0(val)		bfin_write16(CAN1_MB16_DATA0, val)
-#define bfin_read_CAN1_MB16_DATA1()		bfin_read16(CAN1_MB16_DATA1)
-#define bfin_write_CAN1_MB16_DATA1(val)		bfin_write16(CAN1_MB16_DATA1, val)
-#define bfin_read_CAN1_MB16_DATA2()		bfin_read16(CAN1_MB16_DATA2)
-#define bfin_write_CAN1_MB16_DATA2(val)		bfin_write16(CAN1_MB16_DATA2, val)
-#define bfin_read_CAN1_MB16_DATA3()		bfin_read16(CAN1_MB16_DATA3)
-#define bfin_write_CAN1_MB16_DATA3(val)		bfin_write16(CAN1_MB16_DATA3, val)
-#define bfin_read_CAN1_MB16_LENGTH()		bfin_read16(CAN1_MB16_LENGTH)
-#define bfin_write_CAN1_MB16_LENGTH(val)	bfin_write16(CAN1_MB16_LENGTH, val)
-#define bfin_read_CAN1_MB16_TIMESTAMP()		bfin_read16(CAN1_MB16_TIMESTAMP)
-#define bfin_write_CAN1_MB16_TIMESTAMP(val)	bfin_write16(CAN1_MB16_TIMESTAMP, val)
-#define bfin_read_CAN1_MB16_ID0()		bfin_read16(CAN1_MB16_ID0)
-#define bfin_write_CAN1_MB16_ID0(val)		bfin_write16(CAN1_MB16_ID0, val)
-#define bfin_read_CAN1_MB16_ID1()		bfin_read16(CAN1_MB16_ID1)
-#define bfin_write_CAN1_MB16_ID1(val)		bfin_write16(CAN1_MB16_ID1, val)
-#define bfin_read_CAN1_MB17_DATA0()		bfin_read16(CAN1_MB17_DATA0)
-#define bfin_write_CAN1_MB17_DATA0(val)		bfin_write16(CAN1_MB17_DATA0, val)
-#define bfin_read_CAN1_MB17_DATA1()		bfin_read16(CAN1_MB17_DATA1)
-#define bfin_write_CAN1_MB17_DATA1(val)		bfin_write16(CAN1_MB17_DATA1, val)
-#define bfin_read_CAN1_MB17_DATA2()		bfin_read16(CAN1_MB17_DATA2)
-#define bfin_write_CAN1_MB17_DATA2(val)		bfin_write16(CAN1_MB17_DATA2, val)
-#define bfin_read_CAN1_MB17_DATA3()		bfin_read16(CAN1_MB17_DATA3)
-#define bfin_write_CAN1_MB17_DATA3(val)		bfin_write16(CAN1_MB17_DATA3, val)
-#define bfin_read_CAN1_MB17_LENGTH()		bfin_read16(CAN1_MB17_LENGTH)
-#define bfin_write_CAN1_MB17_LENGTH(val)	bfin_write16(CAN1_MB17_LENGTH, val)
-#define bfin_read_CAN1_MB17_TIMESTAMP()		bfin_read16(CAN1_MB17_TIMESTAMP)
-#define bfin_write_CAN1_MB17_TIMESTAMP(val)	bfin_write16(CAN1_MB17_TIMESTAMP, val)
-#define bfin_read_CAN1_MB17_ID0()		bfin_read16(CAN1_MB17_ID0)
-#define bfin_write_CAN1_MB17_ID0(val)		bfin_write16(CAN1_MB17_ID0, val)
-#define bfin_read_CAN1_MB17_ID1()		bfin_read16(CAN1_MB17_ID1)
-#define bfin_write_CAN1_MB17_ID1(val)		bfin_write16(CAN1_MB17_ID1, val)
-#define bfin_read_CAN1_MB18_DATA0()		bfin_read16(CAN1_MB18_DATA0)
-#define bfin_write_CAN1_MB18_DATA0(val)		bfin_write16(CAN1_MB18_DATA0, val)
-#define bfin_read_CAN1_MB18_DATA1()		bfin_read16(CAN1_MB18_DATA1)
-#define bfin_write_CAN1_MB18_DATA1(val)		bfin_write16(CAN1_MB18_DATA1, val)
-#define bfin_read_CAN1_MB18_DATA2()		bfin_read16(CAN1_MB18_DATA2)
-#define bfin_write_CAN1_MB18_DATA2(val)		bfin_write16(CAN1_MB18_DATA2, val)
-#define bfin_read_CAN1_MB18_DATA3()		bfin_read16(CAN1_MB18_DATA3)
-#define bfin_write_CAN1_MB18_DATA3(val)		bfin_write16(CAN1_MB18_DATA3, val)
-#define bfin_read_CAN1_MB18_LENGTH()		bfin_read16(CAN1_MB18_LENGTH)
-#define bfin_write_CAN1_MB18_LENGTH(val)	bfin_write16(CAN1_MB18_LENGTH, val)
-#define bfin_read_CAN1_MB18_TIMESTAMP()		bfin_read16(CAN1_MB18_TIMESTAMP)
-#define bfin_write_CAN1_MB18_TIMESTAMP(val)	bfin_write16(CAN1_MB18_TIMESTAMP, val)
-#define bfin_read_CAN1_MB18_ID0()		bfin_read16(CAN1_MB18_ID0)
-#define bfin_write_CAN1_MB18_ID0(val)		bfin_write16(CAN1_MB18_ID0, val)
-#define bfin_read_CAN1_MB18_ID1()		bfin_read16(CAN1_MB18_ID1)
-#define bfin_write_CAN1_MB18_ID1(val)		bfin_write16(CAN1_MB18_ID1, val)
-#define bfin_read_CAN1_MB19_DATA0()		bfin_read16(CAN1_MB19_DATA0)
-#define bfin_write_CAN1_MB19_DATA0(val)		bfin_write16(CAN1_MB19_DATA0, val)
-#define bfin_read_CAN1_MB19_DATA1()		bfin_read16(CAN1_MB19_DATA1)
-#define bfin_write_CAN1_MB19_DATA1(val)		bfin_write16(CAN1_MB19_DATA1, val)
-#define bfin_read_CAN1_MB19_DATA2()		bfin_read16(CAN1_MB19_DATA2)
-#define bfin_write_CAN1_MB19_DATA2(val)		bfin_write16(CAN1_MB19_DATA2, val)
-#define bfin_read_CAN1_MB19_DATA3()		bfin_read16(CAN1_MB19_DATA3)
-#define bfin_write_CAN1_MB19_DATA3(val)		bfin_write16(CAN1_MB19_DATA3, val)
-#define bfin_read_CAN1_MB19_LENGTH()		bfin_read16(CAN1_MB19_LENGTH)
-#define bfin_write_CAN1_MB19_LENGTH(val)	bfin_write16(CAN1_MB19_LENGTH, val)
-#define bfin_read_CAN1_MB19_TIMESTAMP()		bfin_read16(CAN1_MB19_TIMESTAMP)
-#define bfin_write_CAN1_MB19_TIMESTAMP(val)	bfin_write16(CAN1_MB19_TIMESTAMP, val)
-#define bfin_read_CAN1_MB19_ID0()		bfin_read16(CAN1_MB19_ID0)
-#define bfin_write_CAN1_MB19_ID0(val)		bfin_write16(CAN1_MB19_ID0, val)
-#define bfin_read_CAN1_MB19_ID1()		bfin_read16(CAN1_MB19_ID1)
-#define bfin_write_CAN1_MB19_ID1(val)		bfin_write16(CAN1_MB19_ID1, val)
-#define bfin_read_CAN1_MB20_DATA0()		bfin_read16(CAN1_MB20_DATA0)
-#define bfin_write_CAN1_MB20_DATA0(val)		bfin_write16(CAN1_MB20_DATA0, val)
-#define bfin_read_CAN1_MB20_DATA1()		bfin_read16(CAN1_MB20_DATA1)
-#define bfin_write_CAN1_MB20_DATA1(val)		bfin_write16(CAN1_MB20_DATA1, val)
-#define bfin_read_CAN1_MB20_DATA2()		bfin_read16(CAN1_MB20_DATA2)
-#define bfin_write_CAN1_MB20_DATA2(val)		bfin_write16(CAN1_MB20_DATA2, val)
-#define bfin_read_CAN1_MB20_DATA3()		bfin_read16(CAN1_MB20_DATA3)
-#define bfin_write_CAN1_MB20_DATA3(val)		bfin_write16(CAN1_MB20_DATA3, val)
-#define bfin_read_CAN1_MB20_LENGTH()		bfin_read16(CAN1_MB20_LENGTH)
-#define bfin_write_CAN1_MB20_LENGTH(val)	bfin_write16(CAN1_MB20_LENGTH, val)
-#define bfin_read_CAN1_MB20_TIMESTAMP()		bfin_read16(CAN1_MB20_TIMESTAMP)
-#define bfin_write_CAN1_MB20_TIMESTAMP(val)	bfin_write16(CAN1_MB20_TIMESTAMP, val)
-#define bfin_read_CAN1_MB20_ID0()		bfin_read16(CAN1_MB20_ID0)
-#define bfin_write_CAN1_MB20_ID0(val)		bfin_write16(CAN1_MB20_ID0, val)
-#define bfin_read_CAN1_MB20_ID1()		bfin_read16(CAN1_MB20_ID1)
-#define bfin_write_CAN1_MB20_ID1(val)		bfin_write16(CAN1_MB20_ID1, val)
-#define bfin_read_CAN1_MB21_DATA0()		bfin_read16(CAN1_MB21_DATA0)
-#define bfin_write_CAN1_MB21_DATA0(val)		bfin_write16(CAN1_MB21_DATA0, val)
-#define bfin_read_CAN1_MB21_DATA1()		bfin_read16(CAN1_MB21_DATA1)
-#define bfin_write_CAN1_MB21_DATA1(val)		bfin_write16(CAN1_MB21_DATA1, val)
-#define bfin_read_CAN1_MB21_DATA2()		bfin_read16(CAN1_MB21_DATA2)
-#define bfin_write_CAN1_MB21_DATA2(val)		bfin_write16(CAN1_MB21_DATA2, val)
-#define bfin_read_CAN1_MB21_DATA3()		bfin_read16(CAN1_MB21_DATA3)
-#define bfin_write_CAN1_MB21_DATA3(val)		bfin_write16(CAN1_MB21_DATA3, val)
-#define bfin_read_CAN1_MB21_LENGTH()		bfin_read16(CAN1_MB21_LENGTH)
-#define bfin_write_CAN1_MB21_LENGTH(val)	bfin_write16(CAN1_MB21_LENGTH, val)
-#define bfin_read_CAN1_MB21_TIMESTAMP()		bfin_read16(CAN1_MB21_TIMESTAMP)
-#define bfin_write_CAN1_MB21_TIMESTAMP(val)	bfin_write16(CAN1_MB21_TIMESTAMP, val)
-#define bfin_read_CAN1_MB21_ID0()		bfin_read16(CAN1_MB21_ID0)
-#define bfin_write_CAN1_MB21_ID0(val)		bfin_write16(CAN1_MB21_ID0, val)
-#define bfin_read_CAN1_MB21_ID1()		bfin_read16(CAN1_MB21_ID1)
-#define bfin_write_CAN1_MB21_ID1(val)		bfin_write16(CAN1_MB21_ID1, val)
-#define bfin_read_CAN1_MB22_DATA0()		bfin_read16(CAN1_MB22_DATA0)
-#define bfin_write_CAN1_MB22_DATA0(val)		bfin_write16(CAN1_MB22_DATA0, val)
-#define bfin_read_CAN1_MB22_DATA1()		bfin_read16(CAN1_MB22_DATA1)
-#define bfin_write_CAN1_MB22_DATA1(val)		bfin_write16(CAN1_MB22_DATA1, val)
-#define bfin_read_CAN1_MB22_DATA2()		bfin_read16(CAN1_MB22_DATA2)
-#define bfin_write_CAN1_MB22_DATA2(val)		bfin_write16(CAN1_MB22_DATA2, val)
-#define bfin_read_CAN1_MB22_DATA3()		bfin_read16(CAN1_MB22_DATA3)
-#define bfin_write_CAN1_MB22_DATA3(val)		bfin_write16(CAN1_MB22_DATA3, val)
-#define bfin_read_CAN1_MB22_LENGTH()		bfin_read16(CAN1_MB22_LENGTH)
-#define bfin_write_CAN1_MB22_LENGTH(val)	bfin_write16(CAN1_MB22_LENGTH, val)
-#define bfin_read_CAN1_MB22_TIMESTAMP()		bfin_read16(CAN1_MB22_TIMESTAMP)
-#define bfin_write_CAN1_MB22_TIMESTAMP(val)	bfin_write16(CAN1_MB22_TIMESTAMP, val)
-#define bfin_read_CAN1_MB22_ID0()		bfin_read16(CAN1_MB22_ID0)
-#define bfin_write_CAN1_MB22_ID0(val)		bfin_write16(CAN1_MB22_ID0, val)
-#define bfin_read_CAN1_MB22_ID1()		bfin_read16(CAN1_MB22_ID1)
-#define bfin_write_CAN1_MB22_ID1(val)		bfin_write16(CAN1_MB22_ID1, val)
-#define bfin_read_CAN1_MB23_DATA0()		bfin_read16(CAN1_MB23_DATA0)
-#define bfin_write_CAN1_MB23_DATA0(val)		bfin_write16(CAN1_MB23_DATA0, val)
-#define bfin_read_CAN1_MB23_DATA1()		bfin_read16(CAN1_MB23_DATA1)
-#define bfin_write_CAN1_MB23_DATA1(val)		bfin_write16(CAN1_MB23_DATA1, val)
-#define bfin_read_CAN1_MB23_DATA2()		bfin_read16(CAN1_MB23_DATA2)
-#define bfin_write_CAN1_MB23_DATA2(val)		bfin_write16(CAN1_MB23_DATA2, val)
-#define bfin_read_CAN1_MB23_DATA3()		bfin_read16(CAN1_MB23_DATA3)
-#define bfin_write_CAN1_MB23_DATA3(val)		bfin_write16(CAN1_MB23_DATA3, val)
-#define bfin_read_CAN1_MB23_LENGTH()		bfin_read16(CAN1_MB23_LENGTH)
-#define bfin_write_CAN1_MB23_LENGTH(val)	bfin_write16(CAN1_MB23_LENGTH, val)
-#define bfin_read_CAN1_MB23_TIMESTAMP()		bfin_read16(CAN1_MB23_TIMESTAMP)
-#define bfin_write_CAN1_MB23_TIMESTAMP(val)	bfin_write16(CAN1_MB23_TIMESTAMP, val)
-#define bfin_read_CAN1_MB23_ID0()		bfin_read16(CAN1_MB23_ID0)
-#define bfin_write_CAN1_MB23_ID0(val)		bfin_write16(CAN1_MB23_ID0, val)
-#define bfin_read_CAN1_MB23_ID1()		bfin_read16(CAN1_MB23_ID1)
-#define bfin_write_CAN1_MB23_ID1(val)		bfin_write16(CAN1_MB23_ID1, val)
-#define bfin_read_CAN1_MB24_DATA0()		bfin_read16(CAN1_MB24_DATA0)
-#define bfin_write_CAN1_MB24_DATA0(val)		bfin_write16(CAN1_MB24_DATA0, val)
-#define bfin_read_CAN1_MB24_DATA1()		bfin_read16(CAN1_MB24_DATA1)
-#define bfin_write_CAN1_MB24_DATA1(val)		bfin_write16(CAN1_MB24_DATA1, val)
-#define bfin_read_CAN1_MB24_DATA2()		bfin_read16(CAN1_MB24_DATA2)
-#define bfin_write_CAN1_MB24_DATA2(val)		bfin_write16(CAN1_MB24_DATA2, val)
-#define bfin_read_CAN1_MB24_DATA3()		bfin_read16(CAN1_MB24_DATA3)
-#define bfin_write_CAN1_MB24_DATA3(val)		bfin_write16(CAN1_MB24_DATA3, val)
-#define bfin_read_CAN1_MB24_LENGTH()		bfin_read16(CAN1_MB24_LENGTH)
-#define bfin_write_CAN1_MB24_LENGTH(val)	bfin_write16(CAN1_MB24_LENGTH, val)
-#define bfin_read_CAN1_MB24_TIMESTAMP()		bfin_read16(CAN1_MB24_TIMESTAMP)
-#define bfin_write_CAN1_MB24_TIMESTAMP(val)	bfin_write16(CAN1_MB24_TIMESTAMP, val)
-#define bfin_read_CAN1_MB24_ID0()		bfin_read16(CAN1_MB24_ID0)
-#define bfin_write_CAN1_MB24_ID0(val)		bfin_write16(CAN1_MB24_ID0, val)
-#define bfin_read_CAN1_MB24_ID1()		bfin_read16(CAN1_MB24_ID1)
-#define bfin_write_CAN1_MB24_ID1(val)		bfin_write16(CAN1_MB24_ID1, val)
-#define bfin_read_CAN1_MB25_DATA0()		bfin_read16(CAN1_MB25_DATA0)
-#define bfin_write_CAN1_MB25_DATA0(val)		bfin_write16(CAN1_MB25_DATA0, val)
-#define bfin_read_CAN1_MB25_DATA1()		bfin_read16(CAN1_MB25_DATA1)
-#define bfin_write_CAN1_MB25_DATA1(val)		bfin_write16(CAN1_MB25_DATA1, val)
-#define bfin_read_CAN1_MB25_DATA2()		bfin_read16(CAN1_MB25_DATA2)
-#define bfin_write_CAN1_MB25_DATA2(val)		bfin_write16(CAN1_MB25_DATA2, val)
-#define bfin_read_CAN1_MB25_DATA3()		bfin_read16(CAN1_MB25_DATA3)
-#define bfin_write_CAN1_MB25_DATA3(val)		bfin_write16(CAN1_MB25_DATA3, val)
-#define bfin_read_CAN1_MB25_LENGTH()		bfin_read16(CAN1_MB25_LENGTH)
-#define bfin_write_CAN1_MB25_LENGTH(val)	bfin_write16(CAN1_MB25_LENGTH, val)
-#define bfin_read_CAN1_MB25_TIMESTAMP()		bfin_read16(CAN1_MB25_TIMESTAMP)
-#define bfin_write_CAN1_MB25_TIMESTAMP(val)	bfin_write16(CAN1_MB25_TIMESTAMP, val)
-#define bfin_read_CAN1_MB25_ID0()		bfin_read16(CAN1_MB25_ID0)
-#define bfin_write_CAN1_MB25_ID0(val)		bfin_write16(CAN1_MB25_ID0, val)
-#define bfin_read_CAN1_MB25_ID1()		bfin_read16(CAN1_MB25_ID1)
-#define bfin_write_CAN1_MB25_ID1(val)		bfin_write16(CAN1_MB25_ID1, val)
-#define bfin_read_CAN1_MB26_DATA0()		bfin_read16(CAN1_MB26_DATA0)
-#define bfin_write_CAN1_MB26_DATA0(val)		bfin_write16(CAN1_MB26_DATA0, val)
-#define bfin_read_CAN1_MB26_DATA1()		bfin_read16(CAN1_MB26_DATA1)
-#define bfin_write_CAN1_MB26_DATA1(val)		bfin_write16(CAN1_MB26_DATA1, val)
-#define bfin_read_CAN1_MB26_DATA2()		bfin_read16(CAN1_MB26_DATA2)
-#define bfin_write_CAN1_MB26_DATA2(val)		bfin_write16(CAN1_MB26_DATA2, val)
-#define bfin_read_CAN1_MB26_DATA3()		bfin_read16(CAN1_MB26_DATA3)
-#define bfin_write_CAN1_MB26_DATA3(val)		bfin_write16(CAN1_MB26_DATA3, val)
-#define bfin_read_CAN1_MB26_LENGTH()		bfin_read16(CAN1_MB26_LENGTH)
-#define bfin_write_CAN1_MB26_LENGTH(val)	bfin_write16(CAN1_MB26_LENGTH, val)
-#define bfin_read_CAN1_MB26_TIMESTAMP()		bfin_read16(CAN1_MB26_TIMESTAMP)
-#define bfin_write_CAN1_MB26_TIMESTAMP(val)	bfin_write16(CAN1_MB26_TIMESTAMP, val)
-#define bfin_read_CAN1_MB26_ID0()		bfin_read16(CAN1_MB26_ID0)
-#define bfin_write_CAN1_MB26_ID0(val)		bfin_write16(CAN1_MB26_ID0, val)
-#define bfin_read_CAN1_MB26_ID1()		bfin_read16(CAN1_MB26_ID1)
-#define bfin_write_CAN1_MB26_ID1(val)		bfin_write16(CAN1_MB26_ID1, val)
-#define bfin_read_CAN1_MB27_DATA0()		bfin_read16(CAN1_MB27_DATA0)
-#define bfin_write_CAN1_MB27_DATA0(val)		bfin_write16(CAN1_MB27_DATA0, val)
-#define bfin_read_CAN1_MB27_DATA1()		bfin_read16(CAN1_MB27_DATA1)
-#define bfin_write_CAN1_MB27_DATA1(val)		bfin_write16(CAN1_MB27_DATA1, val)
-#define bfin_read_CAN1_MB27_DATA2()		bfin_read16(CAN1_MB27_DATA2)
-#define bfin_write_CAN1_MB27_DATA2(val)		bfin_write16(CAN1_MB27_DATA2, val)
-#define bfin_read_CAN1_MB27_DATA3()		bfin_read16(CAN1_MB27_DATA3)
-#define bfin_write_CAN1_MB27_DATA3(val)		bfin_write16(CAN1_MB27_DATA3, val)
-#define bfin_read_CAN1_MB27_LENGTH()		bfin_read16(CAN1_MB27_LENGTH)
-#define bfin_write_CAN1_MB27_LENGTH(val)	bfin_write16(CAN1_MB27_LENGTH, val)
-#define bfin_read_CAN1_MB27_TIMESTAMP()		bfin_read16(CAN1_MB27_TIMESTAMP)
-#define bfin_write_CAN1_MB27_TIMESTAMP(val)	bfin_write16(CAN1_MB27_TIMESTAMP, val)
-#define bfin_read_CAN1_MB27_ID0()		bfin_read16(CAN1_MB27_ID0)
-#define bfin_write_CAN1_MB27_ID0(val)		bfin_write16(CAN1_MB27_ID0, val)
-#define bfin_read_CAN1_MB27_ID1()		bfin_read16(CAN1_MB27_ID1)
-#define bfin_write_CAN1_MB27_ID1(val)		bfin_write16(CAN1_MB27_ID1, val)
-#define bfin_read_CAN1_MB28_DATA0()		bfin_read16(CAN1_MB28_DATA0)
-#define bfin_write_CAN1_MB28_DATA0(val)		bfin_write16(CAN1_MB28_DATA0, val)
-#define bfin_read_CAN1_MB28_DATA1()		bfin_read16(CAN1_MB28_DATA1)
-#define bfin_write_CAN1_MB28_DATA1(val)		bfin_write16(CAN1_MB28_DATA1, val)
-#define bfin_read_CAN1_MB28_DATA2()		bfin_read16(CAN1_MB28_DATA2)
-#define bfin_write_CAN1_MB28_DATA2(val)		bfin_write16(CAN1_MB28_DATA2, val)
-#define bfin_read_CAN1_MB28_DATA3()		bfin_read16(CAN1_MB28_DATA3)
-#define bfin_write_CAN1_MB28_DATA3(val)		bfin_write16(CAN1_MB28_DATA3, val)
-#define bfin_read_CAN1_MB28_LENGTH()		bfin_read16(CAN1_MB28_LENGTH)
-#define bfin_write_CAN1_MB28_LENGTH(val)	bfin_write16(CAN1_MB28_LENGTH, val)
-#define bfin_read_CAN1_MB28_TIMESTAMP()		bfin_read16(CAN1_MB28_TIMESTAMP)
-#define bfin_write_CAN1_MB28_TIMESTAMP(val)	bfin_write16(CAN1_MB28_TIMESTAMP, val)
-#define bfin_read_CAN1_MB28_ID0()		bfin_read16(CAN1_MB28_ID0)
-#define bfin_write_CAN1_MB28_ID0(val)		bfin_write16(CAN1_MB28_ID0, val)
-#define bfin_read_CAN1_MB28_ID1()		bfin_read16(CAN1_MB28_ID1)
-#define bfin_write_CAN1_MB28_ID1(val)		bfin_write16(CAN1_MB28_ID1, val)
-#define bfin_read_CAN1_MB29_DATA0()		bfin_read16(CAN1_MB29_DATA0)
-#define bfin_write_CAN1_MB29_DATA0(val)		bfin_write16(CAN1_MB29_DATA0, val)
-#define bfin_read_CAN1_MB29_DATA1()		bfin_read16(CAN1_MB29_DATA1)
-#define bfin_write_CAN1_MB29_DATA1(val)		bfin_write16(CAN1_MB29_DATA1, val)
-#define bfin_read_CAN1_MB29_DATA2()		bfin_read16(CAN1_MB29_DATA2)
-#define bfin_write_CAN1_MB29_DATA2(val)		bfin_write16(CAN1_MB29_DATA2, val)
-#define bfin_read_CAN1_MB29_DATA3()		bfin_read16(CAN1_MB29_DATA3)
-#define bfin_write_CAN1_MB29_DATA3(val)		bfin_write16(CAN1_MB29_DATA3, val)
-#define bfin_read_CAN1_MB29_LENGTH()		bfin_read16(CAN1_MB29_LENGTH)
-#define bfin_write_CAN1_MB29_LENGTH(val)	bfin_write16(CAN1_MB29_LENGTH, val)
-#define bfin_read_CAN1_MB29_TIMESTAMP()		bfin_read16(CAN1_MB29_TIMESTAMP)
-#define bfin_write_CAN1_MB29_TIMESTAMP(val)	bfin_write16(CAN1_MB29_TIMESTAMP, val)
-#define bfin_read_CAN1_MB29_ID0()		bfin_read16(CAN1_MB29_ID0)
-#define bfin_write_CAN1_MB29_ID0(val)		bfin_write16(CAN1_MB29_ID0, val)
-#define bfin_read_CAN1_MB29_ID1()		bfin_read16(CAN1_MB29_ID1)
-#define bfin_write_CAN1_MB29_ID1(val)		bfin_write16(CAN1_MB29_ID1, val)
-#define bfin_read_CAN1_MB30_DATA0()		bfin_read16(CAN1_MB30_DATA0)
-#define bfin_write_CAN1_MB30_DATA0(val)		bfin_write16(CAN1_MB30_DATA0, val)
-#define bfin_read_CAN1_MB30_DATA1()		bfin_read16(CAN1_MB30_DATA1)
-#define bfin_write_CAN1_MB30_DATA1(val)		bfin_write16(CAN1_MB30_DATA1, val)
-#define bfin_read_CAN1_MB30_DATA2()		bfin_read16(CAN1_MB30_DATA2)
-#define bfin_write_CAN1_MB30_DATA2(val)		bfin_write16(CAN1_MB30_DATA2, val)
-#define bfin_read_CAN1_MB30_DATA3()		bfin_read16(CAN1_MB30_DATA3)
-#define bfin_write_CAN1_MB30_DATA3(val)		bfin_write16(CAN1_MB30_DATA3, val)
-#define bfin_read_CAN1_MB30_LENGTH()		bfin_read16(CAN1_MB30_LENGTH)
-#define bfin_write_CAN1_MB30_LENGTH(val)	bfin_write16(CAN1_MB30_LENGTH, val)
-#define bfin_read_CAN1_MB30_TIMESTAMP()		bfin_read16(CAN1_MB30_TIMESTAMP)
-#define bfin_write_CAN1_MB30_TIMESTAMP(val)	bfin_write16(CAN1_MB30_TIMESTAMP, val)
-#define bfin_read_CAN1_MB30_ID0()		bfin_read16(CAN1_MB30_ID0)
-#define bfin_write_CAN1_MB30_ID0(val)		bfin_write16(CAN1_MB30_ID0, val)
-#define bfin_read_CAN1_MB30_ID1()		bfin_read16(CAN1_MB30_ID1)
-#define bfin_write_CAN1_MB30_ID1(val)		bfin_write16(CAN1_MB30_ID1, val)
-#define bfin_read_CAN1_MB31_DATA0()		bfin_read16(CAN1_MB31_DATA0)
-#define bfin_write_CAN1_MB31_DATA0(val)		bfin_write16(CAN1_MB31_DATA0, val)
-#define bfin_read_CAN1_MB31_DATA1()		bfin_read16(CAN1_MB31_DATA1)
-#define bfin_write_CAN1_MB31_DATA1(val)		bfin_write16(CAN1_MB31_DATA1, val)
-#define bfin_read_CAN1_MB31_DATA2()		bfin_read16(CAN1_MB31_DATA2)
-#define bfin_write_CAN1_MB31_DATA2(val)		bfin_write16(CAN1_MB31_DATA2, val)
-#define bfin_read_CAN1_MB31_DATA3()		bfin_read16(CAN1_MB31_DATA3)
-#define bfin_write_CAN1_MB31_DATA3(val)		bfin_write16(CAN1_MB31_DATA3, val)
-#define bfin_read_CAN1_MB31_LENGTH()		bfin_read16(CAN1_MB31_LENGTH)
-#define bfin_write_CAN1_MB31_LENGTH(val)	bfin_write16(CAN1_MB31_LENGTH, val)
-#define bfin_read_CAN1_MB31_TIMESTAMP()		bfin_read16(CAN1_MB31_TIMESTAMP)
-#define bfin_write_CAN1_MB31_TIMESTAMP(val)	bfin_write16(CAN1_MB31_TIMESTAMP, val)
-#define bfin_read_CAN1_MB31_ID0()		bfin_read16(CAN1_MB31_ID0)
-#define bfin_write_CAN1_MB31_ID0(val)		bfin_write16(CAN1_MB31_ID0, val)
-#define bfin_read_CAN1_MB31_ID1()		bfin_read16(CAN1_MB31_ID1)
-#define bfin_write_CAN1_MB31_ID1(val)		bfin_write16(CAN1_MB31_ID1, val)
-
-/* ATAPI Registers */
-
-#define bfin_read_ATAPI_CONTROL()		bfin_read16(ATAPI_CONTROL)
-#define bfin_write_ATAPI_CONTROL(val)		bfin_write16(ATAPI_CONTROL, val)
-#define bfin_read_ATAPI_STATUS()		bfin_read16(ATAPI_STATUS)
-#define bfin_write_ATAPI_STATUS(val)		bfin_write16(ATAPI_STATUS, val)
-#define bfin_read_ATAPI_DEV_ADDR()		bfin_read16(ATAPI_DEV_ADDR)
-#define bfin_write_ATAPI_DEV_ADDR(val)		bfin_write16(ATAPI_DEV_ADDR, val)
-#define bfin_read_ATAPI_DEV_TXBUF()		bfin_read16(ATAPI_DEV_TXBUF)
-#define bfin_write_ATAPI_DEV_TXBUF(val)		bfin_write16(ATAPI_DEV_TXBUF, val)
-#define bfin_read_ATAPI_DEV_RXBUF()		bfin_read16(ATAPI_DEV_RXBUF)
-#define bfin_write_ATAPI_DEV_RXBUF(val)		bfin_write16(ATAPI_DEV_RXBUF, val)
-#define bfin_read_ATAPI_INT_MASK()		bfin_read16(ATAPI_INT_MASK)
-#define bfin_write_ATAPI_INT_MASK(val)		bfin_write16(ATAPI_INT_MASK, val)
-#define bfin_read_ATAPI_INT_STATUS()		bfin_read16(ATAPI_INT_STATUS)
-#define bfin_write_ATAPI_INT_STATUS(val)	bfin_write16(ATAPI_INT_STATUS, val)
-#define bfin_read_ATAPI_XFER_LEN()		bfin_read16(ATAPI_XFER_LEN)
-#define bfin_write_ATAPI_XFER_LEN(val)		bfin_write16(ATAPI_XFER_LEN, val)
-#define bfin_read_ATAPI_LINE_STATUS()		bfin_read16(ATAPI_LINE_STATUS)
-#define bfin_write_ATAPI_LINE_STATUS(val)	bfin_write16(ATAPI_LINE_STATUS, val)
-#define bfin_read_ATAPI_SM_STATE()		bfin_read16(ATAPI_SM_STATE)
-#define bfin_write_ATAPI_SM_STATE(val)		bfin_write16(ATAPI_SM_STATE, val)
-#define bfin_read_ATAPI_TERMINATE()		bfin_read16(ATAPI_TERMINATE)
-#define bfin_write_ATAPI_TERMINATE(val)		bfin_write16(ATAPI_TERMINATE, val)
-#define bfin_read_ATAPI_PIO_TFRCNT()		bfin_read16(ATAPI_PIO_TFRCNT)
-#define bfin_write_ATAPI_PIO_TFRCNT(val)	bfin_write16(ATAPI_PIO_TFRCNT, val)
-#define bfin_read_ATAPI_DMA_TFRCNT()		bfin_read16(ATAPI_DMA_TFRCNT)
-#define bfin_write_ATAPI_DMA_TFRCNT(val)	bfin_write16(ATAPI_DMA_TFRCNT, val)
-#define bfin_read_ATAPI_UMAIN_TFRCNT()		bfin_read16(ATAPI_UMAIN_TFRCNT)
-#define bfin_write_ATAPI_UMAIN_TFRCNT(val)	bfin_write16(ATAPI_UMAIN_TFRCNT, val)
-#define bfin_read_ATAPI_UDMAOUT_TFRCNT()	bfin_read16(ATAPI_UDMAOUT_TFRCNT)
-#define bfin_write_ATAPI_UDMAOUT_TFRCNT(val)	bfin_write16(ATAPI_UDMAOUT_TFRCNT, val)
-#define bfin_read_ATAPI_REG_TIM_0()		bfin_read16(ATAPI_REG_TIM_0)
-#define bfin_write_ATAPI_REG_TIM_0(val)		bfin_write16(ATAPI_REG_TIM_0, val)
-#define bfin_read_ATAPI_PIO_TIM_0()		bfin_read16(ATAPI_PIO_TIM_0)
-#define bfin_write_ATAPI_PIO_TIM_0(val)		bfin_write16(ATAPI_PIO_TIM_0, val)
-#define bfin_read_ATAPI_PIO_TIM_1()		bfin_read16(ATAPI_PIO_TIM_1)
-#define bfin_write_ATAPI_PIO_TIM_1(val)		bfin_write16(ATAPI_PIO_TIM_1, val)
-#define bfin_read_ATAPI_MULTI_TIM_0()		bfin_read16(ATAPI_MULTI_TIM_0)
-#define bfin_write_ATAPI_MULTI_TIM_0(val)	bfin_write16(ATAPI_MULTI_TIM_0, val)
-#define bfin_read_ATAPI_MULTI_TIM_1()		bfin_read16(ATAPI_MULTI_TIM_1)
-#define bfin_write_ATAPI_MULTI_TIM_1(val)	bfin_write16(ATAPI_MULTI_TIM_1, val)
-#define bfin_read_ATAPI_MULTI_TIM_2()		bfin_read16(ATAPI_MULTI_TIM_2)
-#define bfin_write_ATAPI_MULTI_TIM_2(val)	bfin_write16(ATAPI_MULTI_TIM_2, val)
-#define bfin_read_ATAPI_ULTRA_TIM_0()		bfin_read16(ATAPI_ULTRA_TIM_0)
-#define bfin_write_ATAPI_ULTRA_TIM_0(val)	bfin_write16(ATAPI_ULTRA_TIM_0, val)
-#define bfin_read_ATAPI_ULTRA_TIM_1()		bfin_read16(ATAPI_ULTRA_TIM_1)
-#define bfin_write_ATAPI_ULTRA_TIM_1(val)	bfin_write16(ATAPI_ULTRA_TIM_1, val)
-#define bfin_read_ATAPI_ULTRA_TIM_2()		bfin_read16(ATAPI_ULTRA_TIM_2)
-#define bfin_write_ATAPI_ULTRA_TIM_2(val)	bfin_write16(ATAPI_ULTRA_TIM_2, val)
-#define bfin_read_ATAPI_ULTRA_TIM_3()		bfin_read16(ATAPI_ULTRA_TIM_3)
-#define bfin_write_ATAPI_ULTRA_TIM_3(val)	bfin_write16(ATAPI_ULTRA_TIM_3, val)
-
-/* SDH Registers */
-
-#define bfin_read_SDH_PWR_CTL()		bfin_read16(SDH_PWR_CTL)
-#define bfin_write_SDH_PWR_CTL(val)	bfin_write16(SDH_PWR_CTL, val)
-#define bfin_read_SDH_CLK_CTL()		bfin_read16(SDH_CLK_CTL)
-#define bfin_write_SDH_CLK_CTL(val)	bfin_write16(SDH_CLK_CTL, val)
-#define bfin_read_SDH_ARGUMENT()	bfin_read32(SDH_ARGUMENT)
-#define bfin_write_SDH_ARGUMENT(val)	bfin_write32(SDH_ARGUMENT, val)
-#define bfin_read_SDH_COMMAND()		bfin_read16(SDH_COMMAND)
-#define bfin_write_SDH_COMMAND(val)	bfin_write16(SDH_COMMAND, val)
-#define bfin_read_SDH_RESP_CMD()	bfin_read16(SDH_RESP_CMD)
-#define bfin_write_SDH_RESP_CMD(val)	bfin_write16(SDH_RESP_CMD, val)
-#define bfin_read_SDH_RESPONSE0()	bfin_read32(SDH_RESPONSE0)
-#define bfin_write_SDH_RESPONSE0(val)	bfin_write32(SDH_RESPONSE0, val)
-#define bfin_read_SDH_RESPONSE1()	bfin_read32(SDH_RESPONSE1)
-#define bfin_write_SDH_RESPONSE1(val)	bfin_write32(SDH_RESPONSE1, val)
-#define bfin_read_SDH_RESPONSE2()	bfin_read32(SDH_RESPONSE2)
-#define bfin_write_SDH_RESPONSE2(val)	bfin_write32(SDH_RESPONSE2, val)
-#define bfin_read_SDH_RESPONSE3()	bfin_read32(SDH_RESPONSE3)
-#define bfin_write_SDH_RESPONSE3(val)	bfin_write32(SDH_RESPONSE3, val)
-#define bfin_read_SDH_DATA_TIMER()	bfin_read32(SDH_DATA_TIMER)
-#define bfin_write_SDH_DATA_TIMER(val)	bfin_write32(SDH_DATA_TIMER, val)
-#define bfin_read_SDH_DATA_LGTH()	bfin_read16(SDH_DATA_LGTH)
-#define bfin_write_SDH_DATA_LGTH(val)	bfin_write16(SDH_DATA_LGTH, val)
-#define bfin_read_SDH_DATA_CTL()	bfin_read16(SDH_DATA_CTL)
-#define bfin_write_SDH_DATA_CTL(val)	bfin_write16(SDH_DATA_CTL, val)
-#define bfin_read_SDH_DATA_CNT()	bfin_read16(SDH_DATA_CNT)
-#define bfin_write_SDH_DATA_CNT(val)	bfin_write16(SDH_DATA_CNT, val)
-#define bfin_read_SDH_STATUS()		bfin_read32(SDH_STATUS)
-#define bfin_write_SDH_STATUS(val)	bfin_write32(SDH_STATUS, val)
-#define bfin_read_SDH_STATUS_CLR()	bfin_read16(SDH_STATUS_CLR)
-#define bfin_write_SDH_STATUS_CLR(val)	bfin_write16(SDH_STATUS_CLR, val)
-#define bfin_read_SDH_MASK0()		bfin_read32(SDH_MASK0)
-#define bfin_write_SDH_MASK0(val)	bfin_write32(SDH_MASK0, val)
-#define bfin_read_SDH_MASK1()		bfin_read32(SDH_MASK1)
-#define bfin_write_SDH_MASK1(val)	bfin_write32(SDH_MASK1, val)
-#define bfin_read_SDH_FIFO_CNT()	bfin_read16(SDH_FIFO_CNT)
-#define bfin_write_SDH_FIFO_CNT(val)	bfin_write16(SDH_FIFO_CNT, val)
-#define bfin_read_SDH_FIFO()		bfin_read32(SDH_FIFO)
-#define bfin_write_SDH_FIFO(val)	bfin_write32(SDH_FIFO, val)
-#define bfin_read_SDH_E_STATUS()	bfin_read16(SDH_E_STATUS)
-#define bfin_write_SDH_E_STATUS(val)	bfin_write16(SDH_E_STATUS, val)
-#define bfin_read_SDH_E_MASK()		bfin_read16(SDH_E_MASK)
-#define bfin_write_SDH_E_MASK(val)	bfin_write16(SDH_E_MASK, val)
-#define bfin_read_SDH_CFG()		bfin_read16(SDH_CFG)
-#define bfin_write_SDH_CFG(val)		bfin_write16(SDH_CFG, val)
-#define bfin_read_SDH_RD_WAIT_EN()	bfin_read16(SDH_RD_WAIT_EN)
-#define bfin_write_SDH_RD_WAIT_EN(val)	bfin_write16(SDH_RD_WAIT_EN, val)
-#define bfin_read_SDH_PID0()		bfin_read16(SDH_PID0)
-#define bfin_write_SDH_PID0(val)	bfin_write16(SDH_PID0, val)
-#define bfin_read_SDH_PID1()		bfin_read16(SDH_PID1)
-#define bfin_write_SDH_PID1(val)	bfin_write16(SDH_PID1, val)
-#define bfin_read_SDH_PID2()		bfin_read16(SDH_PID2)
-#define bfin_write_SDH_PID2(val)	bfin_write16(SDH_PID2, val)
-#define bfin_read_SDH_PID3()		bfin_read16(SDH_PID3)
-#define bfin_write_SDH_PID3(val)	bfin_write16(SDH_PID3, val)
-#define bfin_read_SDH_PID4()		bfin_read16(SDH_PID4)
-#define bfin_write_SDH_PID4(val)	bfin_write16(SDH_PID4, val)
-#define bfin_read_SDH_PID5()		bfin_read16(SDH_PID5)
-#define bfin_write_SDH_PID5(val)	bfin_write16(SDH_PID5, val)
-#define bfin_read_SDH_PID6()		bfin_read16(SDH_PID6)
-#define bfin_write_SDH_PID6(val)	bfin_write16(SDH_PID6, val)
-#define bfin_read_SDH_PID7()		bfin_read16(SDH_PID7)
-#define bfin_write_SDH_PID7(val)	bfin_write16(SDH_PID7, val)
-
-/* HOST Port Registers */
-
-#define bfin_read_HOST_CONTROL()	bfin_read16(HOST_CONTROL)
-#define bfin_write_HOST_CONTROL(val)	bfin_write16(HOST_CONTROL, val)
-#define bfin_read_HOST_STATUS()		bfin_read16(HOST_STATUS)
-#define bfin_write_HOST_STATUS(val)	bfin_write16(HOST_STATUS, val)
-#define bfin_read_HOST_TIMEOUT()	bfin_read16(HOST_TIMEOUT)
-#define bfin_write_HOST_TIMEOUT(val)	bfin_write16(HOST_TIMEOUT, val)
-
-/* USB Control Registers */
-
-#define bfin_read_USB_FADDR()		bfin_read16(USB_FADDR)
-#define bfin_write_USB_FADDR(val)	bfin_write16(USB_FADDR, val)
-#define bfin_read_USB_POWER()		bfin_read16(USB_POWER)
-#define bfin_write_USB_POWER(val)	bfin_write16(USB_POWER, val)
-#define bfin_read_USB_INTRTX()		bfin_read16(USB_INTRTX)
-#define bfin_write_USB_INTRTX(val)	bfin_write16(USB_INTRTX, val)
-#define bfin_read_USB_INTRRX()		bfin_read16(USB_INTRRX)
-#define bfin_write_USB_INTRRX(val)	bfin_write16(USB_INTRRX, val)
-#define bfin_read_USB_INTRTXE()		bfin_read16(USB_INTRTXE)
-#define bfin_write_USB_INTRTXE(val)	bfin_write16(USB_INTRTXE, val)
-#define bfin_read_USB_INTRRXE()		bfin_read16(USB_INTRRXE)
-#define bfin_write_USB_INTRRXE(val)	bfin_write16(USB_INTRRXE, val)
-#define bfin_read_USB_INTRUSB()		bfin_read16(USB_INTRUSB)
-#define bfin_write_USB_INTRUSB(val)	bfin_write16(USB_INTRUSB, val)
-#define bfin_read_USB_INTRUSBE()	bfin_read16(USB_INTRUSBE)
-#define bfin_write_USB_INTRUSBE(val)	bfin_write16(USB_INTRUSBE, val)
-#define bfin_read_USB_FRAME()		bfin_read16(USB_FRAME)
-#define bfin_write_USB_FRAME(val)	bfin_write16(USB_FRAME, val)
-#define bfin_read_USB_INDEX()		bfin_read16(USB_INDEX)
-#define bfin_write_USB_INDEX(val)	bfin_write16(USB_INDEX, val)
-#define bfin_read_USB_TESTMODE()	bfin_read16(USB_TESTMODE)
-#define bfin_write_USB_TESTMODE(val)	bfin_write16(USB_TESTMODE, val)
-#define bfin_read_USB_GLOBINTR()	bfin_read16(USB_GLOBINTR)
-#define bfin_write_USB_GLOBINTR(val)	bfin_write16(USB_GLOBINTR, val)
-#define bfin_read_USB_GLOBAL_CTL()	bfin_read16(USB_GLOBAL_CTL)
-#define bfin_write_USB_GLOBAL_CTL(val)	bfin_write16(USB_GLOBAL_CTL, val)
-
-/* USB Packet Control Registers */
-
-#define bfin_read_USB_TX_MAX_PACKET()		bfin_read16(USB_TX_MAX_PACKET)
-#define bfin_write_USB_TX_MAX_PACKET(val)	bfin_write16(USB_TX_MAX_PACKET, val)
-#define bfin_read_USB_CSR0()			bfin_read16(USB_CSR0)
-#define bfin_write_USB_CSR0(val)		bfin_write16(USB_CSR0, val)
-#define bfin_read_USB_TXCSR()			bfin_read16(USB_TXCSR)
-#define bfin_write_USB_TXCSR(val)		bfin_write16(USB_TXCSR, val)
-#define bfin_read_USB_RX_MAX_PACKET()		bfin_read16(USB_RX_MAX_PACKET)
-#define bfin_write_USB_RX_MAX_PACKET(val)	bfin_write16(USB_RX_MAX_PACKET, val)
-#define bfin_read_USB_RXCSR()			bfin_read16(USB_RXCSR)
-#define bfin_write_USB_RXCSR(val)		bfin_write16(USB_RXCSR, val)
-#define bfin_read_USB_COUNT0()			bfin_read16(USB_COUNT0)
-#define bfin_write_USB_COUNT0(val)		bfin_write16(USB_COUNT0, val)
-#define bfin_read_USB_RXCOUNT()			bfin_read16(USB_RXCOUNT)
-#define bfin_write_USB_RXCOUNT(val)		bfin_write16(USB_RXCOUNT, val)
-#define bfin_read_USB_TXTYPE()			bfin_read16(USB_TXTYPE)
-#define bfin_write_USB_TXTYPE(val)		bfin_write16(USB_TXTYPE, val)
-#define bfin_read_USB_NAKLIMIT0()		bfin_read16(USB_NAKLIMIT0)
-#define bfin_write_USB_NAKLIMIT0(val)		bfin_write16(USB_NAKLIMIT0, val)
-#define bfin_read_USB_TXINTERVAL()		bfin_read16(USB_TXINTERVAL)
-#define bfin_write_USB_TXINTERVAL(val)		bfin_write16(USB_TXINTERVAL, val)
-#define bfin_read_USB_RXTYPE()			bfin_read16(USB_RXTYPE)
-#define bfin_write_USB_RXTYPE(val)		bfin_write16(USB_RXTYPE, val)
-#define bfin_read_USB_RXINTERVAL()		bfin_read16(USB_RXINTERVAL)
-#define bfin_write_USB_RXINTERVAL(val)		bfin_write16(USB_RXINTERVAL, val)
-#define bfin_read_USB_TXCOUNT()			bfin_read16(USB_TXCOUNT)
-#define bfin_write_USB_TXCOUNT(val)		bfin_write16(USB_TXCOUNT, val)
-
-/* USB Endbfin_read_()oint FIFO Registers */
-
-#define bfin_read_USB_EP0_FIFO()		bfin_read16(USB_EP0_FIFO)
-#define bfin_write_USB_EP0_FIFO(val)		bfin_write16(USB_EP0_FIFO, val)
-#define bfin_read_USB_EP1_FIFO()		bfin_read16(USB_EP1_FIFO)
-#define bfin_write_USB_EP1_FIFO(val)		bfin_write16(USB_EP1_FIFO, val)
-#define bfin_read_USB_EP2_FIFO()		bfin_read16(USB_EP2_FIFO)
-#define bfin_write_USB_EP2_FIFO(val)		bfin_write16(USB_EP2_FIFO, val)
-#define bfin_read_USB_EP3_FIFO()		bfin_read16(USB_EP3_FIFO)
-#define bfin_write_USB_EP3_FIFO(val)		bfin_write16(USB_EP3_FIFO, val)
-#define bfin_read_USB_EP4_FIFO()		bfin_read16(USB_EP4_FIFO)
-#define bfin_write_USB_EP4_FIFO(val)		bfin_write16(USB_EP4_FIFO, val)
-#define bfin_read_USB_EP5_FIFO()		bfin_read16(USB_EP5_FIFO)
-#define bfin_write_USB_EP5_FIFO(val)		bfin_write16(USB_EP5_FIFO, val)
-#define bfin_read_USB_EP6_FIFO()		bfin_read16(USB_EP6_FIFO)
-#define bfin_write_USB_EP6_FIFO(val)		bfin_write16(USB_EP6_FIFO, val)
-#define bfin_read_USB_EP7_FIFO()		bfin_read16(USB_EP7_FIFO)
-#define bfin_write_USB_EP7_FIFO(val)		bfin_write16(USB_EP7_FIFO, val)
-
-/* USB OTG Control Registers */
-
-#define bfin_read_USB_OTG_DEV_CTL()		bfin_read16(USB_OTG_DEV_CTL)
-#define bfin_write_USB_OTG_DEV_CTL(val)		bfin_write16(USB_OTG_DEV_CTL, val)
-#define bfin_read_USB_OTG_VBUS_IRQ()		bfin_read16(USB_OTG_VBUS_IRQ)
-#define bfin_write_USB_OTG_VBUS_IRQ(val)	bfin_write16(USB_OTG_VBUS_IRQ, val)
-#define bfin_read_USB_OTG_VBUS_MASK()		bfin_read16(USB_OTG_VBUS_MASK)
-#define bfin_write_USB_OTG_VBUS_MASK(val)	bfin_write16(USB_OTG_VBUS_MASK, val)
-
-/* USB Phy Control Registers */
-
-#define bfin_read_USB_LINKINFO()		bfin_read16(USB_LINKINFO)
-#define bfin_write_USB_LINKINFO(val)		bfin_write16(USB_LINKINFO, val)
-#define bfin_read_USB_VPLEN()			bfin_read16(USB_VPLEN)
-#define bfin_write_USB_VPLEN(val)		bfin_write16(USB_VPLEN, val)
-#define bfin_read_USB_HS_EOF1()			bfin_read16(USB_HS_EOF1)
-#define bfin_write_USB_HS_EOF1(val)		bfin_write16(USB_HS_EOF1, val)
-#define bfin_read_USB_FS_EOF1()			bfin_read16(USB_FS_EOF1)
-#define bfin_write_USB_FS_EOF1(val)		bfin_write16(USB_FS_EOF1, val)
-#define bfin_read_USB_LS_EOF1()			bfin_read16(USB_LS_EOF1)
-#define bfin_write_USB_LS_EOF1(val)		bfin_write16(USB_LS_EOF1, val)
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CNTRL()		bfin_read16(USB_APHY_CNTRL)
-#define bfin_write_USB_APHY_CNTRL(val)		bfin_write16(USB_APHY_CNTRL, val)
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define bfin_read_USB_APHY_CALIB()		bfin_read16(USB_APHY_CALIB)
-#define bfin_write_USB_APHY_CALIB(val)		bfin_write16(USB_APHY_CALIB, val)
-#define bfin_read_USB_APHY_CNTRL2()		bfin_read16(USB_APHY_CNTRL2)
-#define bfin_write_USB_APHY_CNTRL2(val)		bfin_write16(USB_APHY_CNTRL2, val)
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define bfin_read_USB_PHY_TEST()		bfin_read16(USB_PHY_TEST)
-#define bfin_write_USB_PHY_TEST(val)		bfin_write16(USB_PHY_TEST, val)
-#define bfin_read_USB_PLLOSC_CTRL()		bfin_read16(USB_PLLOSC_CTRL)
-#define bfin_write_USB_PLLOSC_CTRL(val)		bfin_write16(USB_PLLOSC_CTRL, val)
-#define bfin_read_USB_SRP_CLKDIV()		bfin_read16(USB_SRP_CLKDIV)
-#define bfin_write_USB_SRP_CLKDIV(val)		bfin_write16(USB_SRP_CLKDIV, val)
-
-/* USB Endbfin_read_()oint 0 Control Registers */
-
-#define bfin_read_USB_EP_NI0_TXMAXP()		bfin_read16(USB_EP_NI0_TXMAXP)
-#define bfin_write_USB_EP_NI0_TXMAXP(val)	bfin_write16(USB_EP_NI0_TXMAXP, val)
-#define bfin_read_USB_EP_NI0_TXCSR()		bfin_read16(USB_EP_NI0_TXCSR)
-#define bfin_write_USB_EP_NI0_TXCSR(val)	bfin_write16(USB_EP_NI0_TXCSR, val)
-#define bfin_read_USB_EP_NI0_RXMAXP()		bfin_read16(USB_EP_NI0_RXMAXP)
-#define bfin_write_USB_EP_NI0_RXMAXP(val)	bfin_write16(USB_EP_NI0_RXMAXP, val)
-#define bfin_read_USB_EP_NI0_RXCSR()		bfin_read16(USB_EP_NI0_RXCSR)
-#define bfin_write_USB_EP_NI0_RXCSR(val)	bfin_write16(USB_EP_NI0_RXCSR, val)
-#define bfin_read_USB_EP_NI0_RXCOUNT()		bfin_read16(USB_EP_NI0_RXCOUNT)
-#define bfin_write_USB_EP_NI0_RXCOUNT(val)	bfin_write16(USB_EP_NI0_RXCOUNT, val)
-#define bfin_read_USB_EP_NI0_TXTYPE()		bfin_read16(USB_EP_NI0_TXTYPE)
-#define bfin_write_USB_EP_NI0_TXTYPE(val)	bfin_write16(USB_EP_NI0_TXTYPE, val)
-#define bfin_read_USB_EP_NI0_TXINTERVAL()	bfin_read16(USB_EP_NI0_TXINTERVAL)
-#define bfin_write_USB_EP_NI0_TXINTERVAL(val)	bfin_write16(USB_EP_NI0_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI0_RXTYPE()		bfin_read16(USB_EP_NI0_RXTYPE)
-#define bfin_write_USB_EP_NI0_RXTYPE(val)	bfin_write16(USB_EP_NI0_RXTYPE, val)
-#define bfin_read_USB_EP_NI0_RXINTERVAL()	bfin_read16(USB_EP_NI0_RXINTERVAL)
-#define bfin_write_USB_EP_NI0_RXINTERVAL(val)	bfin_write16(USB_EP_NI0_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 1 Control Registers */
-
-#define bfin_read_USB_EP_NI0_TXCOUNT()		bfin_read16(USB_EP_NI0_TXCOUNT)
-#define bfin_write_USB_EP_NI0_TXCOUNT(val)	bfin_write16(USB_EP_NI0_TXCOUNT, val)
-#define bfin_read_USB_EP_NI1_TXMAXP()		bfin_read16(USB_EP_NI1_TXMAXP)
-#define bfin_write_USB_EP_NI1_TXMAXP(val)	bfin_write16(USB_EP_NI1_TXMAXP, val)
-#define bfin_read_USB_EP_NI1_TXCSR()		bfin_read16(USB_EP_NI1_TXCSR)
-#define bfin_write_USB_EP_NI1_TXCSR(val)	bfin_write16(USB_EP_NI1_TXCSR, val)
-#define bfin_read_USB_EP_NI1_RXMAXP()		bfin_read16(USB_EP_NI1_RXMAXP)
-#define bfin_write_USB_EP_NI1_RXMAXP(val)	bfin_write16(USB_EP_NI1_RXMAXP, val)
-#define bfin_read_USB_EP_NI1_RXCSR()		bfin_read16(USB_EP_NI1_RXCSR)
-#define bfin_write_USB_EP_NI1_RXCSR(val)	bfin_write16(USB_EP_NI1_RXCSR, val)
-#define bfin_read_USB_EP_NI1_RXCOUNT()		bfin_read16(USB_EP_NI1_RXCOUNT)
-#define bfin_write_USB_EP_NI1_RXCOUNT(val)	bfin_write16(USB_EP_NI1_RXCOUNT, val)
-#define bfin_read_USB_EP_NI1_TXTYPE()		bfin_read16(USB_EP_NI1_TXTYPE)
-#define bfin_write_USB_EP_NI1_TXTYPE(val)	bfin_write16(USB_EP_NI1_TXTYPE, val)
-#define bfin_read_USB_EP_NI1_TXINTERVAL()	bfin_read16(USB_EP_NI1_TXINTERVAL)
-#define bfin_write_USB_EP_NI1_TXINTERVAL(val)	bfin_write16(USB_EP_NI1_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI1_RXTYPE()		bfin_read16(USB_EP_NI1_RXTYPE)
-#define bfin_write_USB_EP_NI1_RXTYPE(val)	bfin_write16(USB_EP_NI1_RXTYPE, val)
-#define bfin_read_USB_EP_NI1_RXINTERVAL()	bfin_read16(USB_EP_NI1_RXINTERVAL)
-#define bfin_write_USB_EP_NI1_RXINTERVAL(val)	bfin_write16(USB_EP_NI1_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 2 Control Registers */
-
-#define bfin_read_USB_EP_NI1_TXCOUNT()		bfin_read16(USB_EP_NI1_TXCOUNT)
-#define bfin_write_USB_EP_NI1_TXCOUNT(val)	bfin_write16(USB_EP_NI1_TXCOUNT, val)
-#define bfin_read_USB_EP_NI2_TXMAXP()		bfin_read16(USB_EP_NI2_TXMAXP)
-#define bfin_write_USB_EP_NI2_TXMAXP(val)	bfin_write16(USB_EP_NI2_TXMAXP, val)
-#define bfin_read_USB_EP_NI2_TXCSR()		bfin_read16(USB_EP_NI2_TXCSR)
-#define bfin_write_USB_EP_NI2_TXCSR(val)	bfin_write16(USB_EP_NI2_TXCSR, val)
-#define bfin_read_USB_EP_NI2_RXMAXP()		bfin_read16(USB_EP_NI2_RXMAXP)
-#define bfin_write_USB_EP_NI2_RXMAXP(val)	bfin_write16(USB_EP_NI2_RXMAXP, val)
-#define bfin_read_USB_EP_NI2_RXCSR()		bfin_read16(USB_EP_NI2_RXCSR)
-#define bfin_write_USB_EP_NI2_RXCSR(val)	bfin_write16(USB_EP_NI2_RXCSR, val)
-#define bfin_read_USB_EP_NI2_RXCOUNT()		bfin_read16(USB_EP_NI2_RXCOUNT)
-#define bfin_write_USB_EP_NI2_RXCOUNT(val)	bfin_write16(USB_EP_NI2_RXCOUNT, val)
-#define bfin_read_USB_EP_NI2_TXTYPE()		bfin_read16(USB_EP_NI2_TXTYPE)
-#define bfin_write_USB_EP_NI2_TXTYPE(val)	bfin_write16(USB_EP_NI2_TXTYPE, val)
-#define bfin_read_USB_EP_NI2_TXINTERVAL()	bfin_read16(USB_EP_NI2_TXINTERVAL)
-#define bfin_write_USB_EP_NI2_TXINTERVAL(val)	bfin_write16(USB_EP_NI2_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI2_RXTYPE()		bfin_read16(USB_EP_NI2_RXTYPE)
-#define bfin_write_USB_EP_NI2_RXTYPE(val)	bfin_write16(USB_EP_NI2_RXTYPE, val)
-#define bfin_read_USB_EP_NI2_RXINTERVAL()	bfin_read16(USB_EP_NI2_RXINTERVAL)
-#define bfin_write_USB_EP_NI2_RXINTERVAL(val)	bfin_write16(USB_EP_NI2_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 3 Control Registers */
-
-#define bfin_read_USB_EP_NI2_TXCOUNT()		bfin_read16(USB_EP_NI2_TXCOUNT)
-#define bfin_write_USB_EP_NI2_TXCOUNT(val)	bfin_write16(USB_EP_NI2_TXCOUNT, val)
-#define bfin_read_USB_EP_NI3_TXMAXP()		bfin_read16(USB_EP_NI3_TXMAXP)
-#define bfin_write_USB_EP_NI3_TXMAXP(val)	bfin_write16(USB_EP_NI3_TXMAXP, val)
-#define bfin_read_USB_EP_NI3_TXCSR()		bfin_read16(USB_EP_NI3_TXCSR)
-#define bfin_write_USB_EP_NI3_TXCSR(val)	bfin_write16(USB_EP_NI3_TXCSR, val)
-#define bfin_read_USB_EP_NI3_RXMAXP()		bfin_read16(USB_EP_NI3_RXMAXP)
-#define bfin_write_USB_EP_NI3_RXMAXP(val)	bfin_write16(USB_EP_NI3_RXMAXP, val)
-#define bfin_read_USB_EP_NI3_RXCSR()		bfin_read16(USB_EP_NI3_RXCSR)
-#define bfin_write_USB_EP_NI3_RXCSR(val)	bfin_write16(USB_EP_NI3_RXCSR, val)
-#define bfin_read_USB_EP_NI3_RXCOUNT()		bfin_read16(USB_EP_NI3_RXCOUNT)
-#define bfin_write_USB_EP_NI3_RXCOUNT(val)	bfin_write16(USB_EP_NI3_RXCOUNT, val)
-#define bfin_read_USB_EP_NI3_TXTYPE()		bfin_read16(USB_EP_NI3_TXTYPE)
-#define bfin_write_USB_EP_NI3_TXTYPE(val)	bfin_write16(USB_EP_NI3_TXTYPE, val)
-#define bfin_read_USB_EP_NI3_TXINTERVAL()	bfin_read16(USB_EP_NI3_TXINTERVAL)
-#define bfin_write_USB_EP_NI3_TXINTERVAL(val)	bfin_write16(USB_EP_NI3_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI3_RXTYPE()		bfin_read16(USB_EP_NI3_RXTYPE)
-#define bfin_write_USB_EP_NI3_RXTYPE(val)	bfin_write16(USB_EP_NI3_RXTYPE, val)
-#define bfin_read_USB_EP_NI3_RXINTERVAL()	bfin_read16(USB_EP_NI3_RXINTERVAL)
-#define bfin_write_USB_EP_NI3_RXINTERVAL(val)	bfin_write16(USB_EP_NI3_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 4 Control Registers */
-
-#define bfin_read_USB_EP_NI3_TXCOUNT()		bfin_read16(USB_EP_NI3_TXCOUNT)
-#define bfin_write_USB_EP_NI3_TXCOUNT(val)	bfin_write16(USB_EP_NI3_TXCOUNT, val)
-#define bfin_read_USB_EP_NI4_TXMAXP()		bfin_read16(USB_EP_NI4_TXMAXP)
-#define bfin_write_USB_EP_NI4_TXMAXP(val)	bfin_write16(USB_EP_NI4_TXMAXP, val)
-#define bfin_read_USB_EP_NI4_TXCSR()		bfin_read16(USB_EP_NI4_TXCSR)
-#define bfin_write_USB_EP_NI4_TXCSR(val)	bfin_write16(USB_EP_NI4_TXCSR, val)
-#define bfin_read_USB_EP_NI4_RXMAXP()		bfin_read16(USB_EP_NI4_RXMAXP)
-#define bfin_write_USB_EP_NI4_RXMAXP(val)	bfin_write16(USB_EP_NI4_RXMAXP, val)
-#define bfin_read_USB_EP_NI4_RXCSR()		bfin_read16(USB_EP_NI4_RXCSR)
-#define bfin_write_USB_EP_NI4_RXCSR(val)	bfin_write16(USB_EP_NI4_RXCSR, val)
-#define bfin_read_USB_EP_NI4_RXCOUNT()		bfin_read16(USB_EP_NI4_RXCOUNT)
-#define bfin_write_USB_EP_NI4_RXCOUNT(val)	bfin_write16(USB_EP_NI4_RXCOUNT, val)
-#define bfin_read_USB_EP_NI4_TXTYPE()		bfin_read16(USB_EP_NI4_TXTYPE)
-#define bfin_write_USB_EP_NI4_TXTYPE(val)	bfin_write16(USB_EP_NI4_TXTYPE, val)
-#define bfin_read_USB_EP_NI4_TXINTERVAL()	bfin_read16(USB_EP_NI4_TXINTERVAL)
-#define bfin_write_USB_EP_NI4_TXINTERVAL(val)	bfin_write16(USB_EP_NI4_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI4_RXTYPE()		bfin_read16(USB_EP_NI4_RXTYPE)
-#define bfin_write_USB_EP_NI4_RXTYPE(val)	bfin_write16(USB_EP_NI4_RXTYPE, val)
-#define bfin_read_USB_EP_NI4_RXINTERVAL()	bfin_read16(USB_EP_NI4_RXINTERVAL)
-#define bfin_write_USB_EP_NI4_RXINTERVAL(val)	bfin_write16(USB_EP_NI4_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 5 Control Registers */
-
-#define bfin_read_USB_EP_NI4_TXCOUNT()		bfin_read16(USB_EP_NI4_TXCOUNT)
-#define bfin_write_USB_EP_NI4_TXCOUNT(val)	bfin_write16(USB_EP_NI4_TXCOUNT, val)
-#define bfin_read_USB_EP_NI5_TXMAXP()		bfin_read16(USB_EP_NI5_TXMAXP)
-#define bfin_write_USB_EP_NI5_TXMAXP(val)	bfin_write16(USB_EP_NI5_TXMAXP, val)
-#define bfin_read_USB_EP_NI5_TXCSR()		bfin_read16(USB_EP_NI5_TXCSR)
-#define bfin_write_USB_EP_NI5_TXCSR(val)	bfin_write16(USB_EP_NI5_TXCSR, val)
-#define bfin_read_USB_EP_NI5_RXMAXP()		bfin_read16(USB_EP_NI5_RXMAXP)
-#define bfin_write_USB_EP_NI5_RXMAXP(val)	bfin_write16(USB_EP_NI5_RXMAXP, val)
-#define bfin_read_USB_EP_NI5_RXCSR()		bfin_read16(USB_EP_NI5_RXCSR)
-#define bfin_write_USB_EP_NI5_RXCSR(val)	bfin_write16(USB_EP_NI5_RXCSR, val)
-#define bfin_read_USB_EP_NI5_RXCOUNT()		bfin_read16(USB_EP_NI5_RXCOUNT)
-#define bfin_write_USB_EP_NI5_RXCOUNT(val)	bfin_write16(USB_EP_NI5_RXCOUNT, val)
-#define bfin_read_USB_EP_NI5_TXTYPE()		bfin_read16(USB_EP_NI5_TXTYPE)
-#define bfin_write_USB_EP_NI5_TXTYPE(val)	bfin_write16(USB_EP_NI5_TXTYPE, val)
-#define bfin_read_USB_EP_NI5_TXINTERVAL()	bfin_read16(USB_EP_NI5_TXINTERVAL)
-#define bfin_write_USB_EP_NI5_TXINTERVAL(val)	bfin_write16(USB_EP_NI5_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI5_RXTYPE()		bfin_read16(USB_EP_NI5_RXTYPE)
-#define bfin_write_USB_EP_NI5_RXTYPE(val)	bfin_write16(USB_EP_NI5_RXTYPE, val)
-#define bfin_read_USB_EP_NI5_RXINTERVAL()	bfin_read16(USB_EP_NI5_RXINTERVAL)
-#define bfin_write_USB_EP_NI5_RXINTERVAL(val)	bfin_write16(USB_EP_NI5_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 6 Control Registers */
-
-#define bfin_read_USB_EP_NI5_TXCOUNT()		bfin_read16(USB_EP_NI5_TXCOUNT)
-#define bfin_write_USB_EP_NI5_TXCOUNT(val)	bfin_write16(USB_EP_NI5_TXCOUNT, val)
-#define bfin_read_USB_EP_NI6_TXMAXP()		bfin_read16(USB_EP_NI6_TXMAXP)
-#define bfin_write_USB_EP_NI6_TXMAXP(val)	bfin_write16(USB_EP_NI6_TXMAXP, val)
-#define bfin_read_USB_EP_NI6_TXCSR()		bfin_read16(USB_EP_NI6_TXCSR)
-#define bfin_write_USB_EP_NI6_TXCSR(val)	bfin_write16(USB_EP_NI6_TXCSR, val)
-#define bfin_read_USB_EP_NI6_RXMAXP()		bfin_read16(USB_EP_NI6_RXMAXP)
-#define bfin_write_USB_EP_NI6_RXMAXP(val)	bfin_write16(USB_EP_NI6_RXMAXP, val)
-#define bfin_read_USB_EP_NI6_RXCSR()		bfin_read16(USB_EP_NI6_RXCSR)
-#define bfin_write_USB_EP_NI6_RXCSR(val)	bfin_write16(USB_EP_NI6_RXCSR, val)
-#define bfin_read_USB_EP_NI6_RXCOUNT()		bfin_read16(USB_EP_NI6_RXCOUNT)
-#define bfin_write_USB_EP_NI6_RXCOUNT(val)	bfin_write16(USB_EP_NI6_RXCOUNT, val)
-#define bfin_read_USB_EP_NI6_TXTYPE()		bfin_read16(USB_EP_NI6_TXTYPE)
-#define bfin_write_USB_EP_NI6_TXTYPE(val)	bfin_write16(USB_EP_NI6_TXTYPE, val)
-#define bfin_read_USB_EP_NI6_TXINTERVAL()	bfin_read16(USB_EP_NI6_TXINTERVAL)
-#define bfin_write_USB_EP_NI6_TXINTERVAL(val)	bfin_write16(USB_EP_NI6_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI6_RXTYPE()		bfin_read16(USB_EP_NI6_RXTYPE)
-#define bfin_write_USB_EP_NI6_RXTYPE(val)	bfin_write16(USB_EP_NI6_RXTYPE, val)
-#define bfin_read_USB_EP_NI6_RXINTERVAL()	bfin_read16(USB_EP_NI6_RXINTERVAL)
-#define bfin_write_USB_EP_NI6_RXINTERVAL(val)	bfin_write16(USB_EP_NI6_RXINTERVAL, val)
-
-/* USB Endbfin_read_()oint 7 Control Registers */
-
-#define bfin_read_USB_EP_NI6_TXCOUNT()		bfin_read16(USB_EP_NI6_TXCOUNT)
-#define bfin_write_USB_EP_NI6_TXCOUNT(val)	bfin_write16(USB_EP_NI6_TXCOUNT, val)
-#define bfin_read_USB_EP_NI7_TXMAXP()		bfin_read16(USB_EP_NI7_TXMAXP)
-#define bfin_write_USB_EP_NI7_TXMAXP(val)	bfin_write16(USB_EP_NI7_TXMAXP, val)
-#define bfin_read_USB_EP_NI7_TXCSR()		bfin_read16(USB_EP_NI7_TXCSR)
-#define bfin_write_USB_EP_NI7_TXCSR(val)	bfin_write16(USB_EP_NI7_TXCSR, val)
-#define bfin_read_USB_EP_NI7_RXMAXP()		bfin_read16(USB_EP_NI7_RXMAXP)
-#define bfin_write_USB_EP_NI7_RXMAXP(val)	bfin_write16(USB_EP_NI7_RXMAXP, val)
-#define bfin_read_USB_EP_NI7_RXCSR()		bfin_read16(USB_EP_NI7_RXCSR)
-#define bfin_write_USB_EP_NI7_RXCSR(val)	bfin_write16(USB_EP_NI7_RXCSR, val)
-#define bfin_read_USB_EP_NI7_RXCOUNT()		bfin_read16(USB_EP_NI7_RXCOUNT)
-#define bfin_write_USB_EP_NI7_RXCOUNT(val)	bfin_write16(USB_EP_NI7_RXCOUNT, val)
-#define bfin_read_USB_EP_NI7_TXTYPE()		bfin_read16(USB_EP_NI7_TXTYPE)
-#define bfin_write_USB_EP_NI7_TXTYPE(val)	bfin_write16(USB_EP_NI7_TXTYPE, val)
-#define bfin_read_USB_EP_NI7_TXINTERVAL()	bfin_read16(USB_EP_NI7_TXINTERVAL)
-#define bfin_write_USB_EP_NI7_TXINTERVAL(val)	bfin_write16(USB_EP_NI7_TXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_RXTYPE()		bfin_read16(USB_EP_NI7_RXTYPE)
-#define bfin_write_USB_EP_NI7_RXTYPE(val)	bfin_write16(USB_EP_NI7_RXTYPE, val)
-#define bfin_read_USB_EP_NI7_RXINTERVAL()	bfin_read16(USB_EP_NI7_RXINTERVAL)
-#define bfin_write_USB_EP_NI7_RXINTERVAL(val)	bfin_write16(USB_EP_NI7_RXINTERVAL, val)
-#define bfin_read_USB_EP_NI7_TXCOUNT()		bfin_read16(USB_EP_NI7_TXCOUNT)
-#define bfin_write_USB_EP_NI7_TXCOUNT(val)	bfin_write16(USB_EP_NI7_TXCOUNT, val)
-#define bfin_read_USB_DMA_INTERRUPT()		bfin_read16(USB_DMA_INTERRUPT)
-#define bfin_write_USB_DMA_INTERRUPT(val)	bfin_write16(USB_DMA_INTERRUPT, val)
-
-/* USB Channel 0 Config Registers */
-
-#define bfin_read_USB_DMA0CONTROL()		bfin_read16(USB_DMA0CONTROL)
-#define bfin_write_USB_DMA0CONTROL(val)		bfin_write16(USB_DMA0CONTROL, val)
-#define bfin_read_USB_DMA0ADDRLOW()		bfin_read16(USB_DMA0ADDRLOW)
-#define bfin_write_USB_DMA0ADDRLOW(val)		bfin_write16(USB_DMA0ADDRLOW, val)
-#define bfin_read_USB_DMA0ADDRHIGH()		bfin_read16(USB_DMA0ADDRHIGH)
-#define bfin_write_USB_DMA0ADDRHIGH(val)	bfin_write16(USB_DMA0ADDRHIGH, val)
-#define bfin_read_USB_DMA0COUNTLOW()		bfin_read16(USB_DMA0COUNTLOW)
-#define bfin_write_USB_DMA0COUNTLOW(val)	bfin_write16(USB_DMA0COUNTLOW, val)
-#define bfin_read_USB_DMA0COUNTHIGH()		bfin_read16(USB_DMA0COUNTHIGH)
-#define bfin_write_USB_DMA0COUNTHIGH(val)	bfin_write16(USB_DMA0COUNTHIGH, val)
-
-/* USB Channel 1 Config Registers */
-
-#define bfin_read_USB_DMA1CONTROL()		bfin_read16(USB_DMA1CONTROL)
-#define bfin_write_USB_DMA1CONTROL(val)		bfin_write16(USB_DMA1CONTROL, val)
-#define bfin_read_USB_DMA1ADDRLOW()		bfin_read16(USB_DMA1ADDRLOW)
-#define bfin_write_USB_DMA1ADDRLOW(val)		bfin_write16(USB_DMA1ADDRLOW, val)
-#define bfin_read_USB_DMA1ADDRHIGH()		bfin_read16(USB_DMA1ADDRHIGH)
-#define bfin_write_USB_DMA1ADDRHIGH(val)	bfin_write16(USB_DMA1ADDRHIGH, val)
-#define bfin_read_USB_DMA1COUNTLOW()		bfin_read16(USB_DMA1COUNTLOW)
-#define bfin_write_USB_DMA1COUNTLOW(val)	bfin_write16(USB_DMA1COUNTLOW, val)
-#define bfin_read_USB_DMA1COUNTHIGH()		bfin_read16(USB_DMA1COUNTHIGH)
-#define bfin_write_USB_DMA1COUNTHIGH(val)	bfin_write16(USB_DMA1COUNTHIGH, val)
-
-/* USB Channel 2 Config Registers */
-
-#define bfin_read_USB_DMA2CONTROL()		bfin_read16(USB_DMA2CONTROL)
-#define bfin_write_USB_DMA2CONTROL(val)		bfin_write16(USB_DMA2CONTROL, val)
-#define bfin_read_USB_DMA2ADDRLOW()		bfin_read16(USB_DMA2ADDRLOW)
-#define bfin_write_USB_DMA2ADDRLOW(val)		bfin_write16(USB_DMA2ADDRLOW, val)
-#define bfin_read_USB_DMA2ADDRHIGH()		bfin_read16(USB_DMA2ADDRHIGH)
-#define bfin_write_USB_DMA2ADDRHIGH(val)	bfin_write16(USB_DMA2ADDRHIGH, val)
-#define bfin_read_USB_DMA2COUNTLOW()		bfin_read16(USB_DMA2COUNTLOW)
-#define bfin_write_USB_DMA2COUNTLOW(val)	bfin_write16(USB_DMA2COUNTLOW, val)
-#define bfin_read_USB_DMA2COUNTHIGH()		bfin_read16(USB_DMA2COUNTHIGH)
-#define bfin_write_USB_DMA2COUNTHIGH(val)	bfin_write16(USB_DMA2COUNTHIGH, val)
-
-/* USB Channel 3 Config Registers */
-
-#define bfin_read_USB_DMA3CONTROL()		bfin_read16(USB_DMA3CONTROL)
-#define bfin_write_USB_DMA3CONTROL(val)		bfin_write16(USB_DMA3CONTROL, val)
-#define bfin_read_USB_DMA3ADDRLOW()		bfin_read16(USB_DMA3ADDRLOW)
-#define bfin_write_USB_DMA3ADDRLOW(val)		bfin_write16(USB_DMA3ADDRLOW, val)
-#define bfin_read_USB_DMA3ADDRHIGH()		bfin_read16(USB_DMA3ADDRHIGH)
-#define bfin_write_USB_DMA3ADDRHIGH(val)	bfin_write16(USB_DMA3ADDRHIGH, val)
-#define bfin_read_USB_DMA3COUNTLOW()		bfin_read16(USB_DMA3COUNTLOW)
-#define bfin_write_USB_DMA3COUNTLOW(val)	bfin_write16(USB_DMA3COUNTLOW, val)
-#define bfin_read_USB_DMA3COUNTHIGH()		bfin_read16(USB_DMA3COUNTHIGH)
-#define bfin_write_USB_DMA3COUNTHIGH(val)	bfin_write16(USB_DMA3COUNTHIGH, val)
-
-/* USB Channel 4 Config Registers */
-
-#define bfin_read_USB_DMA4CONTROL()		bfin_read16(USB_DMA4CONTROL)
-#define bfin_write_USB_DMA4CONTROL(val)		bfin_write16(USB_DMA4CONTROL, val)
-#define bfin_read_USB_DMA4ADDRLOW()		bfin_read16(USB_DMA4ADDRLOW)
-#define bfin_write_USB_DMA4ADDRLOW(val)		bfin_write16(USB_DMA4ADDRLOW, val)
-#define bfin_read_USB_DMA4ADDRHIGH()		bfin_read16(USB_DMA4ADDRHIGH)
-#define bfin_write_USB_DMA4ADDRHIGH(val)	bfin_write16(USB_DMA4ADDRHIGH, val)
-#define bfin_read_USB_DMA4COUNTLOW()		bfin_read16(USB_DMA4COUNTLOW)
-#define bfin_write_USB_DMA4COUNTLOW(val)	bfin_write16(USB_DMA4COUNTLOW, val)
-#define bfin_read_USB_DMA4COUNTHIGH()		bfin_read16(USB_DMA4COUNTHIGH)
-#define bfin_write_USB_DMA4COUNTHIGH(val)	bfin_write16(USB_DMA4COUNTHIGH, val)
-
-/* USB Channel 5 Config Registers */
-
-#define bfin_read_USB_DMA5CONTROL()		bfin_read16(USB_DMA5CONTROL)
-#define bfin_write_USB_DMA5CONTROL(val)		bfin_write16(USB_DMA5CONTROL, val)
-#define bfin_read_USB_DMA5ADDRLOW()		bfin_read16(USB_DMA5ADDRLOW)
-#define bfin_write_USB_DMA5ADDRLOW(val)		bfin_write16(USB_DMA5ADDRLOW, val)
-#define bfin_read_USB_DMA5ADDRHIGH()		bfin_read16(USB_DMA5ADDRHIGH)
-#define bfin_write_USB_DMA5ADDRHIGH(val)		bfin_write16(USB_DMA5ADDRHIGH, val)
-#define bfin_read_USB_DMA5COUNTLOW()		bfin_read16(USB_DMA5COUNTLOW)
-#define bfin_write_USB_DMA5COUNTLOW(val)	bfin_write16(USB_DMA5COUNTLOW, val)
-#define bfin_read_USB_DMA5COUNTHIGH()		bfin_read16(USB_DMA5COUNTHIGH)
-#define bfin_write_USB_DMA5COUNTHIGH(val)	bfin_write16(USB_DMA5COUNTHIGH, val)
-
-/* USB Channel 6 Config Registers */
-
-#define bfin_read_USB_DMA6CONTROL()		bfin_read16(USB_DMA6CONTROL)
-#define bfin_write_USB_DMA6CONTROL(val)		bfin_write16(USB_DMA6CONTROL, val)
-#define bfin_read_USB_DMA6ADDRLOW()		bfin_read16(USB_DMA6ADDRLOW)
-#define bfin_write_USB_DMA6ADDRLOW(val)		bfin_write16(USB_DMA6ADDRLOW, val)
-#define bfin_read_USB_DMA6ADDRHIGH()		bfin_read16(USB_DMA6ADDRHIGH)
-#define bfin_write_USB_DMA6ADDRHIGH(val)	bfin_write16(USB_DMA6ADDRHIGH, val)
-#define bfin_read_USB_DMA6COUNTLOW()		bfin_read16(USB_DMA6COUNTLOW)
-#define bfin_write_USB_DMA6COUNTLOW(val)	bfin_write16(USB_DMA6COUNTLOW, val)
-#define bfin_read_USB_DMA6COUNTHIGH()		bfin_read16(USB_DMA6COUNTHIGH)
-#define bfin_write_USB_DMA6COUNTHIGH(val)	bfin_write16(USB_DMA6COUNTHIGH, val)
-
-/* USB Channel 7 Config Registers */
-
-#define bfin_read_USB_DMA7CONTROL()		bfin_read16(USB_DMA7CONTROL)
-#define bfin_write_USB_DMA7CONTROL(val)		bfin_write16(USB_DMA7CONTROL, val)
-#define bfin_read_USB_DMA7ADDRLOW()		bfin_read16(USB_DMA7ADDRLOW)
-#define bfin_write_USB_DMA7ADDRLOW(val)		bfin_write16(USB_DMA7ADDRLOW, val)
-#define bfin_read_USB_DMA7ADDRHIGH()		bfin_read16(USB_DMA7ADDRHIGH)
-#define bfin_write_USB_DMA7ADDRHIGH(val)	bfin_write16(USB_DMA7ADDRHIGH, val)
-#define bfin_read_USB_DMA7COUNTLOW()		bfin_read16(USB_DMA7COUNTLOW)
-#define bfin_write_USB_DMA7COUNTLOW(val)	bfin_write16(USB_DMA7COUNTLOW, val)
-#define bfin_read_USB_DMA7COUNTHIGH()		bfin_read16(USB_DMA7COUNTHIGH)
-#define bfin_write_USB_DMA7COUNTHIGH(val)	bfin_write16(USB_DMA7COUNTHIGH, val)
-
-/* Keybfin_read_()ad Registers */
-
-#define bfin_read_KPAD_CTL()		bfin_read16(KPAD_CTL)
-#define bfin_write_KPAD_CTL(val)	bfin_write16(KPAD_CTL, val)
-#define bfin_read_KPAD_PRESCALE()	bfin_read16(KPAD_PRESCALE)
-#define bfin_write_KPAD_PRESCALE(val)	bfin_write16(KPAD_PRESCALE, val)
-#define bfin_read_KPAD_MSEL()		bfin_read16(KPAD_MSEL)
-#define bfin_write_KPAD_MSEL(val)	bfin_write16(KPAD_MSEL, val)
-#define bfin_read_KPAD_ROWCOL()		bfin_read16(KPAD_ROWCOL)
-#define bfin_write_KPAD_ROWCOL(val)	bfin_write16(KPAD_ROWCOL, val)
-#define bfin_read_KPAD_STAT()		bfin_read16(KPAD_STAT)
-#define bfin_write_KPAD_STAT(val)	bfin_write16(KPAD_STAT, val)
-#define bfin_read_KPAD_SOFTEVAL()	bfin_read16(KPAD_SOFTEVAL)
-#define bfin_write_KPAD_SOFTEVAL(val)	bfin_write16(KPAD_SOFTEVAL, val)
-
-/* Pixel Combfin_read_()ositor (PIXC) Registers */
-
-#define bfin_read_PIXC_CTL()		bfin_read16(PIXC_CTL)
-#define bfin_write_PIXC_CTL(val)	bfin_write16(PIXC_CTL, val)
-#define bfin_read_PIXC_PPL()		bfin_read16(PIXC_PPL)
-#define bfin_write_PIXC_PPL(val)	bfin_write16(PIXC_PPL, val)
-#define bfin_read_PIXC_LPF()		bfin_read16(PIXC_LPF)
-#define bfin_write_PIXC_LPF(val)	bfin_write16(PIXC_LPF, val)
-#define bfin_read_PIXC_AHSTART()	bfin_read16(PIXC_AHSTART)
-#define bfin_write_PIXC_AHSTART(val)	bfin_write16(PIXC_AHSTART, val)
-#define bfin_read_PIXC_AHEND()		bfin_read16(PIXC_AHEND)
-#define bfin_write_PIXC_AHEND(val)	bfin_write16(PIXC_AHEND, val)
-#define bfin_read_PIXC_AVSTART()	bfin_read16(PIXC_AVSTART)
-#define bfin_write_PIXC_AVSTART(val)	bfin_write16(PIXC_AVSTART, val)
-#define bfin_read_PIXC_AVEND()		bfin_read16(PIXC_AVEND)
-#define bfin_write_PIXC_AVEND(val)	bfin_write16(PIXC_AVEND, val)
-#define bfin_read_PIXC_ATRANSP()	bfin_read16(PIXC_ATRANSP)
-#define bfin_write_PIXC_ATRANSP(val)	bfin_write16(PIXC_ATRANSP, val)
-#define bfin_read_PIXC_BHSTART()	bfin_read16(PIXC_BHSTART)
-#define bfin_write_PIXC_BHSTART(val)	bfin_write16(PIXC_BHSTART, val)
-#define bfin_read_PIXC_BHEND()		bfin_read16(PIXC_BHEND)
-#define bfin_write_PIXC_BHEND(val)	bfin_write16(PIXC_BHEND, val)
-#define bfin_read_PIXC_BVSTART()	bfin_read16(PIXC_BVSTART)
-#define bfin_write_PIXC_BVSTART(val)	bfin_write16(PIXC_BVSTART, val)
-#define bfin_read_PIXC_BVEND()		bfin_read16(PIXC_BVEND)
-#define bfin_write_PIXC_BVEND(val)	bfin_write16(PIXC_BVEND, val)
-#define bfin_read_PIXC_BTRANSP()	bfin_read16(PIXC_BTRANSP)
-#define bfin_write_PIXC_BTRANSP(val)	bfin_write16(PIXC_BTRANSP, val)
-#define bfin_read_PIXC_INTRSTAT()	bfin_read16(PIXC_INTRSTAT)
-#define bfin_write_PIXC_INTRSTAT(val)	bfin_write16(PIXC_INTRSTAT, val)
-#define bfin_read_PIXC_RYCON()		bfin_read32(PIXC_RYCON)
-#define bfin_write_PIXC_RYCON(val)	bfin_write32(PIXC_RYCON, val)
-#define bfin_read_PIXC_GUCON()		bfin_read32(PIXC_GUCON)
-#define bfin_write_PIXC_GUCON(val)	bfin_write32(PIXC_GUCON, val)
-#define bfin_read_PIXC_BVCON()		bfin_read32(PIXC_BVCON)
-#define bfin_write_PIXC_BVCON(val)	bfin_write32(PIXC_BVCON, val)
-#define bfin_read_PIXC_CCBIAS()		bfin_read32(PIXC_CCBIAS)
-#define bfin_write_PIXC_CCBIAS(val)	bfin_write32(PIXC_CCBIAS, val)
-#define bfin_read_PIXC_TC()		bfin_read32(PIXC_TC)
-#define bfin_write_PIXC_TC(val)		bfin_write32(PIXC_TC, val)
-
-/* Handshake MDMA 0 Registers */
-
-#define bfin_read_HMDMA0_CONTROL()		bfin_read16(HMDMA0_CONTROL)
-#define bfin_write_HMDMA0_CONTROL(val)		bfin_write16(HMDMA0_CONTROL, val)
-#define bfin_read_HMDMA0_ECINIT()		bfin_read16(HMDMA0_ECINIT)
-#define bfin_write_HMDMA0_ECINIT(val)		bfin_write16(HMDMA0_ECINIT, val)
-#define bfin_read_HMDMA0_BCINIT()		bfin_read16(HMDMA0_BCINIT)
-#define bfin_write_HMDMA0_BCINIT(val)		bfin_write16(HMDMA0_BCINIT, val)
-#define bfin_read_HMDMA0_ECURGENT()		bfin_read16(HMDMA0_ECURGENT)
-#define bfin_write_HMDMA0_ECURGENT(val)		bfin_write16(HMDMA0_ECURGENT, val)
-#define bfin_read_HMDMA0_ECOVERFLOW()		bfin_read16(HMDMA0_ECOVERFLOW)
-#define bfin_write_HMDMA0_ECOVERFLOW(val)	bfin_write16(HMDMA0_ECOVERFLOW, val)
-#define bfin_read_HMDMA0_ECOUNT()		bfin_read16(HMDMA0_ECOUNT)
-#define bfin_write_HMDMA0_ECOUNT(val)		bfin_write16(HMDMA0_ECOUNT, val)
-#define bfin_read_HMDMA0_BCOUNT()		bfin_read16(HMDMA0_BCOUNT)
-#define bfin_write_HMDMA0_BCOUNT(val)		bfin_write16(HMDMA0_BCOUNT, val)
-
-/* Handshake MDMA 1 Registers */
-
-#define bfin_read_HMDMA1_CONTROL()		bfin_read16(HMDMA1_CONTROL)
-#define bfin_write_HMDMA1_CONTROL(val)		bfin_write16(HMDMA1_CONTROL, val)
-#define bfin_read_HMDMA1_ECINIT()		bfin_read16(HMDMA1_ECINIT)
-#define bfin_write_HMDMA1_ECINIT(val)		bfin_write16(HMDMA1_ECINIT, val)
-#define bfin_read_HMDMA1_BCINIT()		bfin_read16(HMDMA1_BCINIT)
-#define bfin_write_HMDMA1_BCINIT(val)		bfin_write16(HMDMA1_BCINIT, val)
-#define bfin_read_HMDMA1_ECURGENT()		bfin_read16(HMDMA1_ECURGENT)
-#define bfin_write_HMDMA1_ECURGENT(val)		bfin_write16(HMDMA1_ECURGENT, val)
-#define bfin_read_HMDMA1_ECOVERFLOW()		bfin_read16(HMDMA1_ECOVERFLOW)
-#define bfin_write_HMDMA1_ECOVERFLOW(val)	bfin_write16(HMDMA1_ECOVERFLOW, val)
-#define bfin_read_HMDMA1_ECOUNT()		bfin_read16(HMDMA1_ECOUNT)
-#define bfin_write_HMDMA1_ECOUNT(val)		bfin_write16(HMDMA1_ECOUNT, val)
-#define bfin_read_HMDMA1_BCOUNT()		bfin_read16(HMDMA1_BCOUNT)
-#define bfin_write_HMDMA1_BCOUNT(val)		bfin_write16(HMDMA1_BCOUNT, val)
-
 #endif /* _CDEF_BF549_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
index a2e9d98..32f71e6 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
@@ -2615,17 +2615,6 @@
 #define bfin_read_CNT_MIN()		bfin_read32(CNT_MIN)
 #define bfin_write_CNT_MIN(val)		bfin_write32(CNT_MIN, val)
 
-/* OTP/FUSE Registers */
-
-#define bfin_read_OTP_CONTROL()		bfin_read16(OTP_CONTROL)
-#define bfin_write_OTP_CONTROL(val)	bfin_write16(OTP_CONTROL, val)
-#define bfin_read_OTP_BEN()		bfin_read16(OTP_BEN)
-#define bfin_write_OTP_BEN(val)		bfin_write16(OTP_BEN, val)
-#define bfin_read_OTP_STATUS()		bfin_read16(OTP_STATUS)
-#define bfin_write_OTP_STATUS(val)	bfin_write16(OTP_STATUS, val)
-#define bfin_read_OTP_TIMING()		bfin_read32(OTP_TIMING)
-#define bfin_write_OTP_TIMING(val)	bfin_write32(OTP_TIMING, val)
-
 /* Security Registers */
 
 #define bfin_read_SECURE_SYSSWT()	bfin_read32(SECURE_SYSSWT)
@@ -2640,17 +2629,6 @@
 #define bfin_read_DMAC1_PERIMUX()	bfin_read16(DMAC1_PERIMUX)
 #define bfin_write_DMAC1_PERIMUX(val)	bfin_write16(DMAC1_PERIMUX, val)
 
-/* OTP Read/Write Data Buffer Registers */
-
-#define bfin_read_OTP_DATA0()		bfin_read32(OTP_DATA0)
-#define bfin_write_OTP_DATA0(val)	bfin_write32(OTP_DATA0, val)
-#define bfin_read_OTP_DATA1()		bfin_read32(OTP_DATA1)
-#define bfin_write_OTP_DATA1(val)	bfin_write32(OTP_DATA1, val)
-#define bfin_read_OTP_DATA2()		bfin_read32(OTP_DATA2)
-#define bfin_write_OTP_DATA2(val)	bfin_write32(OTP_DATA2, val)
-#define bfin_read_OTP_DATA3()		bfin_read32(OTP_DATA3)
-#define bfin_write_OTP_DATA3(val)	bfin_write32(OTP_DATA3, val)
-
 /* Handshake MDMA is not defined in the shared file because it is not available on the ADSP-BF542 bfin_read_()rocessor */
 
 /* legacy definitions */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF544.h b/arch/blackfin/mach-bf548/include/mach/defBF544.h
index 39f588d..f916c52 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF544.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF544.h
@@ -624,9 +624,9 @@
 #define                 DMA_READY  0x1        /* DMA Ready */
 #define                  FIFOFULL  0x2        /* FIFO Full */
 #define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define                  COMPLETE  0x8        /* DMA Complete */
+#define              DMA_COMPLETE  0x8        /* DMA Complete */
 #define                      HSHK  0x10       /* Host Handshake */
-#define                   TIMEOUT  0x20       /* Host Timeout */
+#define                 HSTIMEOUT  0x20       /* Host Timeout */
 #define                      HIRQ  0x40       /* Host Interrupt Request */
 #define                ALLOW_CNFG  0x80       /* Allow New Configuration */
 #define                   DMA_DIR  0x100      /* DMA Direction */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF547.h b/arch/blackfin/mach-bf548/include/mach/defBF547.h
index c4dcf30..72c3436 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF547.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF547.h
@@ -4,18 +4,18 @@
  * Licensed under the ADI BSD license or the GPL-2 (or later)
  */
 
-#ifndef _DEF_BF548_H
-#define _DEF_BF548_H
+#ifndef _DEF_BF547_H
+#define _DEF_BF547_H
 
 /* Include all Core registers and bit definitions */
 #include <asm/def_LPBlackfin.h>
 
-/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF548 */
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF547 */
 
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
+/* The following are the #defines needed by ADSP-BF547 that are not in the common header */
 
 /* Timer Registers */
 
@@ -1217,4 +1217,4 @@
 /* ******************************************* */
 
 
-#endif /* _DEF_BF548_H */
+#endif /* _DEF_BF547_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF548.h b/arch/blackfin/mach-bf548/include/mach/defBF548.h
index a507998..3fb33b0 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF548.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF548.h
@@ -15,115 +15,8 @@
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF548 that are not in the common header */
-
-/* Timer Registers */
-
-#define                    TIMER8_CONFIG  0xffc00600   /* Timer 8 Configuration Register */
-#define                   TIMER8_COUNTER  0xffc00604   /* Timer 8 Counter Register */
-#define                    TIMER8_PERIOD  0xffc00608   /* Timer 8 Period Register */
-#define                     TIMER8_WIDTH  0xffc0060c   /* Timer 8 Width Register */
-#define                    TIMER9_CONFIG  0xffc00610   /* Timer 9 Configuration Register */
-#define                   TIMER9_COUNTER  0xffc00614   /* Timer 9 Counter Register */
-#define                    TIMER9_PERIOD  0xffc00618   /* Timer 9 Period Register */
-#define                     TIMER9_WIDTH  0xffc0061c   /* Timer 9 Width Register */
-#define                   TIMER10_CONFIG  0xffc00620   /* Timer 10 Configuration Register */
-#define                  TIMER10_COUNTER  0xffc00624   /* Timer 10 Counter Register */
-#define                   TIMER10_PERIOD  0xffc00628   /* Timer 10 Period Register */
-#define                    TIMER10_WIDTH  0xffc0062c   /* Timer 10 Width Register */
-
-/* Timer Group of 3 Registers */
-
-#define                    TIMER_ENABLE1  0xffc00640   /* Timer Group of 3 Enable Register */
-#define                   TIMER_DISABLE1  0xffc00644   /* Timer Group of 3 Disable Register */
-#define                    TIMER_STATUS1  0xffc00648   /* Timer Group of 3 Status Register */
-
-/* SPORT0 Registers */
-
-#define                      SPORT0_TCR1  0xffc00800   /* SPORT0 Transmit Configuration 1 Register */
-#define                      SPORT0_TCR2  0xffc00804   /* SPORT0 Transmit Configuration 2 Register */
-#define                   SPORT0_TCLKDIV  0xffc00808   /* SPORT0 Transmit Serial Clock Divider Register */
-#define                    SPORT0_TFSDIV  0xffc0080c   /* SPORT0 Transmit Frame Sync Divider Register */
-#define                        SPORT0_TX  0xffc00810   /* SPORT0 Transmit Data Register */
-#define                        SPORT0_RX  0xffc00818   /* SPORT0 Receive Data Register */
-#define                      SPORT0_RCR1  0xffc00820   /* SPORT0 Receive Configuration 1 Register */
-#define                      SPORT0_RCR2  0xffc00824   /* SPORT0 Receive Configuration 2 Register */
-#define                   SPORT0_RCLKDIV  0xffc00828   /* SPORT0 Receive Serial Clock Divider Register */
-#define                    SPORT0_RFSDIV  0xffc0082c   /* SPORT0 Receive Frame Sync Divider Register */
-#define                      SPORT0_STAT  0xffc00830   /* SPORT0 Status Register */
-#define                      SPORT0_CHNL  0xffc00834   /* SPORT0 Current Channel Register */
-#define                     SPORT0_MCMC1  0xffc00838   /* SPORT0 Multi channel Configuration Register 1 */
-#define                     SPORT0_MCMC2  0xffc0083c   /* SPORT0 Multi channel Configuration Register 2 */
-#define                     SPORT0_MTCS0  0xffc00840   /* SPORT0 Multi channel Transmit Select Register 0 */
-#define                     SPORT0_MTCS1  0xffc00844   /* SPORT0 Multi channel Transmit Select Register 1 */
-#define                     SPORT0_MTCS2  0xffc00848   /* SPORT0 Multi channel Transmit Select Register 2 */
-#define                     SPORT0_MTCS3  0xffc0084c   /* SPORT0 Multi channel Transmit Select Register 3 */
-#define                     SPORT0_MRCS0  0xffc00850   /* SPORT0 Multi channel Receive Select Register 0 */
-#define                     SPORT0_MRCS1  0xffc00854   /* SPORT0 Multi channel Receive Select Register 1 */
-#define                     SPORT0_MRCS2  0xffc00858   /* SPORT0 Multi channel Receive Select Register 2 */
-#define                     SPORT0_MRCS3  0xffc0085c   /* SPORT0 Multi channel Receive Select Register 3 */
-
-/* EPPI0 Registers */
-
-#define                     EPPI0_STATUS  0xffc01000   /* EPPI0 Status Register */
-#define                     EPPI0_HCOUNT  0xffc01004   /* EPPI0 Horizontal Transfer Count Register */
-#define                     EPPI0_HDELAY  0xffc01008   /* EPPI0 Horizontal Delay Count Register */
-#define                     EPPI0_VCOUNT  0xffc0100c   /* EPPI0 Vertical Transfer Count Register */
-#define                     EPPI0_VDELAY  0xffc01010   /* EPPI0 Vertical Delay Count Register */
-#define                      EPPI0_FRAME  0xffc01014   /* EPPI0 Lines per Frame Register */
-#define                       EPPI0_LINE  0xffc01018   /* EPPI0 Samples per Line Register */
-#define                     EPPI0_CLKDIV  0xffc0101c   /* EPPI0 Clock Divide Register */
-#define                    EPPI0_CONTROL  0xffc01020   /* EPPI0 Control Register */
-#define                   EPPI0_FS1W_HBL  0xffc01024   /* EPPI0 FS1 Width Register / EPPI0 Horizontal Blanking Samples Per Line Register */
-#define                  EPPI0_FS1P_AVPL  0xffc01028   /* EPPI0 FS1 Period Register / EPPI0 Active Video Samples Per Line Register */
-#define                   EPPI0_FS2W_LVB  0xffc0102c   /* EPPI0 FS2 Width Register / EPPI0 Lines of Vertical Blanking Register */
-#define                  EPPI0_FS2P_LAVF  0xffc01030   /* EPPI0 FS2 Period Register/ EPPI0 Lines of Active Video Per Field Register */
-#define                       EPPI0_CLIP  0xffc01034   /* EPPI0 Clipping Register */
-
-/* UART2 Registers */
-
-#define                        UART2_DLL  0xffc02100   /* Divisor Latch Low Byte */
-#define                        UART2_DLH  0xffc02104   /* Divisor Latch High Byte */
-#define                       UART2_GCTL  0xffc02108   /* Global Control Register */
-#define                        UART2_LCR  0xffc0210c   /* Line Control Register */
-#define                        UART2_MCR  0xffc02110   /* Modem Control Register */
-#define                        UART2_LSR  0xffc02114   /* Line Status Register */
-#define                        UART2_MSR  0xffc02118   /* Modem Status Register */
-#define                        UART2_SCR  0xffc0211c   /* Scratch Register */
-#define                    UART2_IER_SET  0xffc02120   /* Interrupt Enable Register Set */
-#define                  UART2_IER_CLEAR  0xffc02124   /* Interrupt Enable Register Clear */
-#define                        UART2_RBR  0xffc0212c   /* Receive Buffer Register */
-
-/* Two Wire Interface Registers (TWI1) */
-
-#define                     TWI1_REGBASE  0xffc02200
-#define                      TWI1_CLKDIV  0xffc02200   /* Clock Divider Register */
-#define                     TWI1_CONTROL  0xffc02204   /* TWI Control Register */
-#define                  TWI1_SLAVE_CTRL  0xffc02208   /* TWI Slave Mode Control Register */
-#define                  TWI1_SLAVE_STAT  0xffc0220c   /* TWI Slave Mode Status Register */
-#define                  TWI1_SLAVE_ADDR  0xffc02210   /* TWI Slave Mode Address Register */
-#define                 TWI1_MASTER_CTRL  0xffc02214   /* TWI Master Mode Control Register */
-#define                 TWI1_MASTER_STAT  0xffc02218   /* TWI Master Mode Status Register */
-#define                 TWI1_MASTER_ADDR  0xffc0221c   /* TWI Master Mode Address Register */
-#define                    TWI1_INT_STAT  0xffc02220   /* TWI Interrupt Status Register */
-#define                    TWI1_INT_MASK  0xffc02224   /* TWI Interrupt Mask Register */
-#define                   TWI1_FIFO_CTRL  0xffc02228   /* TWI FIFO Control Register */
-#define                   TWI1_FIFO_STAT  0xffc0222c   /* TWI FIFO Status Register */
-#define                   TWI1_XMT_DATA8  0xffc02280   /* TWI FIFO Transmit Data Single Byte Register */
-#define                  TWI1_XMT_DATA16  0xffc02284   /* TWI FIFO Transmit Data Double Byte Register */
-#define                   TWI1_RCV_DATA8  0xffc02288   /* TWI FIFO Receive Data Single Byte Register */
-#define                  TWI1_RCV_DATA16  0xffc0228c   /* TWI FIFO Receive Data Double Byte Register */
-
-/* SPI2  Registers */
-
-#define                     SPI2_REGBASE  0xffc02400
-#define                         SPI2_CTL  0xffc02400   /* SPI2 Control Register */
-#define                         SPI2_FLG  0xffc02404   /* SPI2 Flag Register */
-#define                        SPI2_STAT  0xffc02408   /* SPI2 Status Register */
-#define                        SPI2_TDBR  0xffc0240c   /* SPI2 Transmit Data Buffer Register */
-#define                        SPI2_RDBR  0xffc02410   /* SPI2 Receive Data Buffer Register */
-#define                        SPI2_BAUD  0xffc02414   /* SPI2 Baud Rate Register */
-#define                      SPI2_SHADOW  0xffc02418   /* SPI2 Receive Data Buffer Shadow Register */
+/* The BF548 is like the BF547, but has additional CANs */
+#include "defBF547.h"
 
 /* CAN Controller 1 Config 1 Registers */
 
@@ -508,1096 +401,4 @@
 #define                    CAN1_MB31_ID0  0xffc037f8   /* CAN Controller 1 Mailbox 31 ID0 Register */
 #define                    CAN1_MB31_ID1  0xffc037fc   /* CAN Controller 1 Mailbox 31 ID1 Register */
 
-/* ATAPI Registers */
-
-#define                    ATAPI_CONTROL  0xffc03800   /* ATAPI Control Register */
-#define                     ATAPI_STATUS  0xffc03804   /* ATAPI Status Register */
-#define                   ATAPI_DEV_ADDR  0xffc03808   /* ATAPI Device Register Address */
-#define                  ATAPI_DEV_TXBUF  0xffc0380c   /* ATAPI Device Register Write Data */
-#define                  ATAPI_DEV_RXBUF  0xffc03810   /* ATAPI Device Register Read Data */
-#define                   ATAPI_INT_MASK  0xffc03814   /* ATAPI Interrupt Mask Register */
-#define                 ATAPI_INT_STATUS  0xffc03818   /* ATAPI Interrupt Status Register */
-#define                   ATAPI_XFER_LEN  0xffc0381c   /* ATAPI Length of Transfer */
-#define                ATAPI_LINE_STATUS  0xffc03820   /* ATAPI Line Status */
-#define                   ATAPI_SM_STATE  0xffc03824   /* ATAPI State Machine Status */
-#define                  ATAPI_TERMINATE  0xffc03828   /* ATAPI Host Terminate */
-#define                 ATAPI_PIO_TFRCNT  0xffc0382c   /* ATAPI PIO mode transfer count */
-#define                 ATAPI_DMA_TFRCNT  0xffc03830   /* ATAPI DMA mode transfer count */
-#define               ATAPI_UMAIN_TFRCNT  0xffc03834   /* ATAPI UDMAIN transfer count */
-#define             ATAPI_UDMAOUT_TFRCNT  0xffc03838   /* ATAPI UDMAOUT transfer count */
-#define                  ATAPI_REG_TIM_0  0xffc03840   /* ATAPI Register Transfer Timing 0 */
-#define                  ATAPI_PIO_TIM_0  0xffc03844   /* ATAPI PIO Timing 0 Register */
-#define                  ATAPI_PIO_TIM_1  0xffc03848   /* ATAPI PIO Timing 1 Register */
-#define                ATAPI_MULTI_TIM_0  0xffc03850   /* ATAPI Multi-DMA Timing 0 Register */
-#define                ATAPI_MULTI_TIM_1  0xffc03854   /* ATAPI Multi-DMA Timing 1 Register */
-#define                ATAPI_MULTI_TIM_2  0xffc03858   /* ATAPI Multi-DMA Timing 2 Register */
-#define                ATAPI_ULTRA_TIM_0  0xffc03860   /* ATAPI Ultra-DMA Timing 0 Register */
-#define                ATAPI_ULTRA_TIM_1  0xffc03864   /* ATAPI Ultra-DMA Timing 1 Register */
-#define                ATAPI_ULTRA_TIM_2  0xffc03868   /* ATAPI Ultra-DMA Timing 2 Register */
-#define                ATAPI_ULTRA_TIM_3  0xffc0386c   /* ATAPI Ultra-DMA Timing 3 Register */
-
-/* SDH Registers */
-
-#define                      SDH_PWR_CTL  0xffc03900   /* SDH Power Control */
-#define                      SDH_CLK_CTL  0xffc03904   /* SDH Clock Control */
-#define                     SDH_ARGUMENT  0xffc03908   /* SDH Argument */
-#define                      SDH_COMMAND  0xffc0390c   /* SDH Command */
-#define                     SDH_RESP_CMD  0xffc03910   /* SDH Response Command */
-#define                    SDH_RESPONSE0  0xffc03914   /* SDH Response0 */
-#define                    SDH_RESPONSE1  0xffc03918   /* SDH Response1 */
-#define                    SDH_RESPONSE2  0xffc0391c   /* SDH Response2 */
-#define                    SDH_RESPONSE3  0xffc03920   /* SDH Response3 */
-#define                   SDH_DATA_TIMER  0xffc03924   /* SDH Data Timer */
-#define                    SDH_DATA_LGTH  0xffc03928   /* SDH Data Length */
-#define                     SDH_DATA_CTL  0xffc0392c   /* SDH Data Control */
-#define                     SDH_DATA_CNT  0xffc03930   /* SDH Data Counter */
-#define                       SDH_STATUS  0xffc03934   /* SDH Status */
-#define                   SDH_STATUS_CLR  0xffc03938   /* SDH Status Clear */
-#define                        SDH_MASK0  0xffc0393c   /* SDH Interrupt0 Mask */
-#define                        SDH_MASK1  0xffc03940   /* SDH Interrupt1 Mask */
-#define                     SDH_FIFO_CNT  0xffc03948   /* SDH FIFO Counter */
-#define                         SDH_FIFO  0xffc03980   /* SDH Data FIFO */
-#define                     SDH_E_STATUS  0xffc039c0   /* SDH Exception Status */
-#define                       SDH_E_MASK  0xffc039c4   /* SDH Exception Mask */
-#define                          SDH_CFG  0xffc039c8   /* SDH Configuration */
-#define                   SDH_RD_WAIT_EN  0xffc039cc   /* SDH Read Wait Enable */
-#define                         SDH_PID0  0xffc039d0   /* SDH Peripheral Identification0 */
-#define                         SDH_PID1  0xffc039d4   /* SDH Peripheral Identification1 */
-#define                         SDH_PID2  0xffc039d8   /* SDH Peripheral Identification2 */
-#define                         SDH_PID3  0xffc039dc   /* SDH Peripheral Identification3 */
-#define                         SDH_PID4  0xffc039e0   /* SDH Peripheral Identification4 */
-#define                         SDH_PID5  0xffc039e4   /* SDH Peripheral Identification5 */
-#define                         SDH_PID6  0xffc039e8   /* SDH Peripheral Identification6 */
-#define                         SDH_PID7  0xffc039ec   /* SDH Peripheral Identification7 */
-
-/* HOST Port Registers */
-
-#define                     HOST_CONTROL  0xffc03a00   /* HOST Control Register */
-#define                      HOST_STATUS  0xffc03a04   /* HOST Status Register */
-#define                     HOST_TIMEOUT  0xffc03a08   /* HOST Acknowledge Mode Timeout Register */
-
-/* USB Control Registers */
-
-#define                        USB_FADDR  0xffc03c00   /* Function address register */
-#define                        USB_POWER  0xffc03c04   /* Power management register */
-#define                       USB_INTRTX  0xffc03c08   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
-#define                       USB_INTRRX  0xffc03c0c   /* Interrupt register for Rx endpoints 1 to 7 */
-#define                      USB_INTRTXE  0xffc03c10   /* Interrupt enable register for IntrTx */
-#define                      USB_INTRRXE  0xffc03c14   /* Interrupt enable register for IntrRx */
-#define                      USB_INTRUSB  0xffc03c18   /* Interrupt register for common USB interrupts */
-#define                     USB_INTRUSBE  0xffc03c1c   /* Interrupt enable register for IntrUSB */
-#define                        USB_FRAME  0xffc03c20   /* USB frame number */
-#define                        USB_INDEX  0xffc03c24   /* Index register for selecting the indexed endpoint registers */
-#define                     USB_TESTMODE  0xffc03c28   /* Enabled USB 20 test modes */
-#define                     USB_GLOBINTR  0xffc03c2c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
-#define                   USB_GLOBAL_CTL  0xffc03c30   /* Global Clock Control for the core */
-
-/* USB Packet Control Registers */
-
-#define                USB_TX_MAX_PACKET  0xffc03c40   /* Maximum packet size for Host Tx endpoint */
-#define                         USB_CSR0  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                        USB_TXCSR  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                USB_RX_MAX_PACKET  0xffc03c48   /* Maximum packet size for Host Rx endpoint */
-#define                        USB_RXCSR  0xffc03c4c   /* Control Status register for Host Rx endpoint */
-#define                       USB_COUNT0  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                      USB_RXCOUNT  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                       USB_TXTYPE  0xffc03c54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
-#define                    USB_NAKLIMIT0  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                   USB_TXINTERVAL  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                       USB_RXTYPE  0xffc03c5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
-#define                   USB_RXINTERVAL  0xffc03c60   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
-#define                      USB_TXCOUNT  0xffc03c68   /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* USB Endpoint FIFO Registers */
-
-#define                     USB_EP0_FIFO  0xffc03c80   /* Endpoint 0 FIFO */
-#define                     USB_EP1_FIFO  0xffc03c88   /* Endpoint 1 FIFO */
-#define                     USB_EP2_FIFO  0xffc03c90   /* Endpoint 2 FIFO */
-#define                     USB_EP3_FIFO  0xffc03c98   /* Endpoint 3 FIFO */
-#define                     USB_EP4_FIFO  0xffc03ca0   /* Endpoint 4 FIFO */
-#define                     USB_EP5_FIFO  0xffc03ca8   /* Endpoint 5 FIFO */
-#define                     USB_EP6_FIFO  0xffc03cb0   /* Endpoint 6 FIFO */
-#define                     USB_EP7_FIFO  0xffc03cb8   /* Endpoint 7 FIFO */
-
-/* USB OTG Control Registers */
-
-#define                  USB_OTG_DEV_CTL  0xffc03d00   /* OTG Device Control Register */
-#define                 USB_OTG_VBUS_IRQ  0xffc03d04   /* OTG VBUS Control Interrupts */
-#define                USB_OTG_VBUS_MASK  0xffc03d08   /* VBUS Control Interrupt Enable */
-
-/* USB Phy Control Registers */
-
-#define                     USB_LINKINFO  0xffc03d48   /* Enables programming of some PHY-side delays */
-#define                        USB_VPLEN  0xffc03d4c   /* Determines duration of VBUS pulse for VBUS charging */
-#define                      USB_HS_EOF1  0xffc03d50   /* Time buffer for High-Speed transactions */
-#define                      USB_FS_EOF1  0xffc03d54   /* Time buffer for Full-Speed transactions */
-#define                      USB_LS_EOF1  0xffc03d58   /* Time buffer for Low-Speed transactions */
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define                   USB_APHY_CNTRL  0xffc03de0   /* Register that increases visibility of Analog PHY */
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
-#define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
-#define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
-#define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
-
-/* USB Endpoint 0 Control Registers */
-
-#define                USB_EP_NI0_TXMAXP  0xffc03e00   /* Maximum packet size for Host Tx endpoint0 */
-#define                 USB_EP_NI0_TXCSR  0xffc03e04   /* Control Status register for endpoint 0 */
-#define                USB_EP_NI0_RXMAXP  0xffc03e08   /* Maximum packet size for Host Rx endpoint0 */
-#define                 USB_EP_NI0_RXCSR  0xffc03e0c   /* Control Status register for Host Rx endpoint0 */
-#define               USB_EP_NI0_RXCOUNT  0xffc03e10   /* Number of bytes received in endpoint 0 FIFO */
-#define                USB_EP_NI0_TXTYPE  0xffc03e14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
-#define            USB_EP_NI0_TXINTERVAL  0xffc03e18   /* Sets the NAK response timeout on Endpoint 0 */
-#define                USB_EP_NI0_RXTYPE  0xffc03e1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
-#define            USB_EP_NI0_RXINTERVAL  0xffc03e20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
-
-/* USB Endpoint 1 Control Registers */
-
-#define               USB_EP_NI0_TXCOUNT  0xffc03e28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
-#define                USB_EP_NI1_TXMAXP  0xffc03e40   /* Maximum packet size for Host Tx endpoint1 */
-#define                 USB_EP_NI1_TXCSR  0xffc03e44   /* Control Status register for endpoint1 */
-#define                USB_EP_NI1_RXMAXP  0xffc03e48   /* Maximum packet size for Host Rx endpoint1 */
-#define                 USB_EP_NI1_RXCSR  0xffc03e4c   /* Control Status register for Host Rx endpoint1 */
-#define               USB_EP_NI1_RXCOUNT  0xffc03e50   /* Number of bytes received in endpoint1 FIFO */
-#define                USB_EP_NI1_TXTYPE  0xffc03e54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
-#define            USB_EP_NI1_TXINTERVAL  0xffc03e58   /* Sets the NAK response timeout on Endpoint1 */
-#define                USB_EP_NI1_RXTYPE  0xffc03e5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
-#define            USB_EP_NI1_RXINTERVAL  0xffc03e60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
-
-/* USB Endpoint 2 Control Registers */
-
-#define               USB_EP_NI1_TXCOUNT  0xffc03e68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
-#define                USB_EP_NI2_TXMAXP  0xffc03e80   /* Maximum packet size for Host Tx endpoint2 */
-#define                 USB_EP_NI2_TXCSR  0xffc03e84   /* Control Status register for endpoint2 */
-#define                USB_EP_NI2_RXMAXP  0xffc03e88   /* Maximum packet size for Host Rx endpoint2 */
-#define                 USB_EP_NI2_RXCSR  0xffc03e8c   /* Control Status register for Host Rx endpoint2 */
-#define               USB_EP_NI2_RXCOUNT  0xffc03e90   /* Number of bytes received in endpoint2 FIFO */
-#define                USB_EP_NI2_TXTYPE  0xffc03e94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
-#define            USB_EP_NI2_TXINTERVAL  0xffc03e98   /* Sets the NAK response timeout on Endpoint2 */
-#define                USB_EP_NI2_RXTYPE  0xffc03e9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
-#define            USB_EP_NI2_RXINTERVAL  0xffc03ea0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
-
-/* USB Endpoint 3 Control Registers */
-
-#define               USB_EP_NI2_TXCOUNT  0xffc03ea8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
-#define                USB_EP_NI3_TXMAXP  0xffc03ec0   /* Maximum packet size for Host Tx endpoint3 */
-#define                 USB_EP_NI3_TXCSR  0xffc03ec4   /* Control Status register for endpoint3 */
-#define                USB_EP_NI3_RXMAXP  0xffc03ec8   /* Maximum packet size for Host Rx endpoint3 */
-#define                 USB_EP_NI3_RXCSR  0xffc03ecc   /* Control Status register for Host Rx endpoint3 */
-#define               USB_EP_NI3_RXCOUNT  0xffc03ed0   /* Number of bytes received in endpoint3 FIFO */
-#define                USB_EP_NI3_TXTYPE  0xffc03ed4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
-#define            USB_EP_NI3_TXINTERVAL  0xffc03ed8   /* Sets the NAK response timeout on Endpoint3 */
-#define                USB_EP_NI3_RXTYPE  0xffc03edc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
-#define            USB_EP_NI3_RXINTERVAL  0xffc03ee0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
-
-/* USB Endpoint 4 Control Registers */
-
-#define               USB_EP_NI3_TXCOUNT  0xffc03ee8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
-#define                USB_EP_NI4_TXMAXP  0xffc03f00   /* Maximum packet size for Host Tx endpoint4 */
-#define                 USB_EP_NI4_TXCSR  0xffc03f04   /* Control Status register for endpoint4 */
-#define                USB_EP_NI4_RXMAXP  0xffc03f08   /* Maximum packet size for Host Rx endpoint4 */
-#define                 USB_EP_NI4_RXCSR  0xffc03f0c   /* Control Status register for Host Rx endpoint4 */
-#define               USB_EP_NI4_RXCOUNT  0xffc03f10   /* Number of bytes received in endpoint4 FIFO */
-#define                USB_EP_NI4_TXTYPE  0xffc03f14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
-#define            USB_EP_NI4_TXINTERVAL  0xffc03f18   /* Sets the NAK response timeout on Endpoint4 */
-#define                USB_EP_NI4_RXTYPE  0xffc03f1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
-#define            USB_EP_NI4_RXINTERVAL  0xffc03f20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
-
-/* USB Endpoint 5 Control Registers */
-
-#define               USB_EP_NI4_TXCOUNT  0xffc03f28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
-#define                USB_EP_NI5_TXMAXP  0xffc03f40   /* Maximum packet size for Host Tx endpoint5 */
-#define                 USB_EP_NI5_TXCSR  0xffc03f44   /* Control Status register for endpoint5 */
-#define                USB_EP_NI5_RXMAXP  0xffc03f48   /* Maximum packet size for Host Rx endpoint5 */
-#define                 USB_EP_NI5_RXCSR  0xffc03f4c   /* Control Status register for Host Rx endpoint5 */
-#define               USB_EP_NI5_RXCOUNT  0xffc03f50   /* Number of bytes received in endpoint5 FIFO */
-#define                USB_EP_NI5_TXTYPE  0xffc03f54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
-#define            USB_EP_NI5_TXINTERVAL  0xffc03f58   /* Sets the NAK response timeout on Endpoint5 */
-#define                USB_EP_NI5_RXTYPE  0xffc03f5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
-#define            USB_EP_NI5_RXINTERVAL  0xffc03f60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
-
-/* USB Endpoint 6 Control Registers */
-
-#define               USB_EP_NI5_TXCOUNT  0xffc03f68   /* Number of bytes to be written to the H145endpoint5 Tx FIFO */
-#define                USB_EP_NI6_TXMAXP  0xffc03f80   /* Maximum packet size for Host Tx endpoint6 */
-#define                 USB_EP_NI6_TXCSR  0xffc03f84   /* Control Status register for endpoint6 */
-#define                USB_EP_NI6_RXMAXP  0xffc03f88   /* Maximum packet size for Host Rx endpoint6 */
-#define                 USB_EP_NI6_RXCSR  0xffc03f8c   /* Control Status register for Host Rx endpoint6 */
-#define               USB_EP_NI6_RXCOUNT  0xffc03f90   /* Number of bytes received in endpoint6 FIFO */
-#define                USB_EP_NI6_TXTYPE  0xffc03f94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
-#define            USB_EP_NI6_TXINTERVAL  0xffc03f98   /* Sets the NAK response timeout on Endpoint6 */
-#define                USB_EP_NI6_RXTYPE  0xffc03f9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
-#define            USB_EP_NI6_RXINTERVAL  0xffc03fa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
-
-/* USB Endpoint 7 Control Registers */
-
-#define               USB_EP_NI6_TXCOUNT  0xffc03fa8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
-#define                USB_EP_NI7_TXMAXP  0xffc03fc0   /* Maximum packet size for Host Tx endpoint7 */
-#define                 USB_EP_NI7_TXCSR  0xffc03fc4   /* Control Status register for endpoint7 */
-#define                USB_EP_NI7_RXMAXP  0xffc03fc8   /* Maximum packet size for Host Rx endpoint7 */
-#define                 USB_EP_NI7_RXCSR  0xffc03fcc   /* Control Status register for Host Rx endpoint7 */
-#define               USB_EP_NI7_RXCOUNT  0xffc03fd0   /* Number of bytes received in endpoint7 FIFO */
-#define                USB_EP_NI7_TXTYPE  0xffc03fd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
-#define            USB_EP_NI7_TXINTERVAL  0xffc03fd8   /* Sets the NAK response timeout on Endpoint7 */
-#define                USB_EP_NI7_RXTYPE  0xffc03fdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
-#define            USB_EP_NI7_RXINTERVAL  0xffc03ff0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
-#define               USB_EP_NI7_TXCOUNT  0xffc03ff8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
-#define                USB_DMA_INTERRUPT  0xffc04000   /* Indicates pending interrupts for the DMA channels */
-
-/* USB Channel 0 Config Registers */
-
-#define                  USB_DMA0CONTROL  0xffc04004   /* DMA master channel 0 configuration */
-#define                  USB_DMA0ADDRLOW  0xffc04008   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0ADDRHIGH  0xffc0400c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0COUNTLOW  0xffc04010   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
-#define                USB_DMA0COUNTHIGH  0xffc04014   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
-
-/* USB Channel 1 Config Registers */
-
-#define                  USB_DMA1CONTROL  0xffc04024   /* DMA master channel 1 configuration */
-#define                  USB_DMA1ADDRLOW  0xffc04028   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1ADDRHIGH  0xffc0402c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1COUNTLOW  0xffc04030   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
-#define                USB_DMA1COUNTHIGH  0xffc04034   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
-
-/* USB Channel 2 Config Registers */
-
-#define                  USB_DMA2CONTROL  0xffc04044   /* DMA master channel 2 configuration */
-#define                  USB_DMA2ADDRLOW  0xffc04048   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2ADDRHIGH  0xffc0404c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2COUNTLOW  0xffc04050   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
-#define                USB_DMA2COUNTHIGH  0xffc04054   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
-
-/* USB Channel 3 Config Registers */
-
-#define                  USB_DMA3CONTROL  0xffc04064   /* DMA master channel 3 configuration */
-#define                  USB_DMA3ADDRLOW  0xffc04068   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3ADDRHIGH  0xffc0406c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3COUNTLOW  0xffc04070   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
-#define                USB_DMA3COUNTHIGH  0xffc04074   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
-
-/* USB Channel 4 Config Registers */
-
-#define                  USB_DMA4CONTROL  0xffc04084   /* DMA master channel 4 configuration */
-#define                  USB_DMA4ADDRLOW  0xffc04088   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4ADDRHIGH  0xffc0408c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4COUNTLOW  0xffc04090   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
-#define                USB_DMA4COUNTHIGH  0xffc04094   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
-
-/* USB Channel 5 Config Registers */
-
-#define                  USB_DMA5CONTROL  0xffc040a4   /* DMA master channel 5 configuration */
-#define                  USB_DMA5ADDRLOW  0xffc040a8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5ADDRHIGH  0xffc040ac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5COUNTLOW  0xffc040b0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
-#define                USB_DMA5COUNTHIGH  0xffc040b4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
-
-/* USB Channel 6 Config Registers */
-
-#define                  USB_DMA6CONTROL  0xffc040c4   /* DMA master channel 6 configuration */
-#define                  USB_DMA6ADDRLOW  0xffc040c8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6ADDRHIGH  0xffc040cc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6COUNTLOW  0xffc040d0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
-#define                USB_DMA6COUNTHIGH  0xffc040d4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
-
-/* USB Channel 7 Config Registers */
-
-#define                  USB_DMA7CONTROL  0xffc040e4   /* DMA master channel 7 configuration */
-#define                  USB_DMA7ADDRLOW  0xffc040e8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7ADDRHIGH  0xffc040ec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7COUNTLOW  0xffc040f0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
-#define                USB_DMA7COUNTHIGH  0xffc040f4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
-
-/* Keypad Registers */
-
-#define                         KPAD_CTL  0xffc04100   /* Controls keypad module enable and disable */
-#define                    KPAD_PRESCALE  0xffc04104   /* Establish a time base for programing the KPAD_MSEL register */
-#define                        KPAD_MSEL  0xffc04108   /* Selects delay parameters for keypad interface sensitivity */
-#define                      KPAD_ROWCOL  0xffc0410c   /* Captures the row and column output values of the keys pressed */
-#define                        KPAD_STAT  0xffc04110   /* Holds and clears the status of the keypad interface interrupt */
-#define                    KPAD_SOFTEVAL  0xffc04114   /* Lets software force keypad interface to check for keys being pressed */
-
-/* Pixel Compositor (PIXC) Registers */
-
-#define                         PIXC_CTL  0xffc04400   /* Overlay enable, resampling mode, I/O data format, transparency enable, watermark level, FIFO status */
-#define                         PIXC_PPL  0xffc04404   /* Holds the number of pixels per line of the display */
-#define                         PIXC_LPF  0xffc04408   /* Holds the number of lines per frame of the display */
-#define                     PIXC_AHSTART  0xffc0440c   /* Contains horizontal start pixel information of the overlay data (set A) */
-#define                       PIXC_AHEND  0xffc04410   /* Contains horizontal end pixel information of the overlay data (set A) */
-#define                     PIXC_AVSTART  0xffc04414   /* Contains vertical start pixel information of the overlay data (set A) */
-#define                       PIXC_AVEND  0xffc04418   /* Contains vertical end pixel information of the overlay data (set A) */
-#define                     PIXC_ATRANSP  0xffc0441c   /* Contains the transparency ratio (set A) */
-#define                     PIXC_BHSTART  0xffc04420   /* Contains horizontal start pixel information of the overlay data (set B) */
-#define                       PIXC_BHEND  0xffc04424   /* Contains horizontal end pixel information of the overlay data (set B) */
-#define                     PIXC_BVSTART  0xffc04428   /* Contains vertical start pixel information of the overlay data (set B) */
-#define                       PIXC_BVEND  0xffc0442c   /* Contains vertical end pixel information of the overlay data (set B) */
-#define                     PIXC_BTRANSP  0xffc04430   /* Contains the transparency ratio (set B) */
-#define                    PIXC_INTRSTAT  0xffc0443c   /* Overlay interrupt configuration/status */
-#define                       PIXC_RYCON  0xffc04440   /* Color space conversion matrix register. Contains the R/Y conversion coefficients */
-#define                       PIXC_GUCON  0xffc04444   /* Color space conversion matrix register. Contains the G/U conversion coefficients */
-#define                       PIXC_BVCON  0xffc04448   /* Color space conversion matrix register. Contains the B/V conversion coefficients */
-#define                      PIXC_CCBIAS  0xffc0444c   /* Bias values for the color space conversion matrix */
-#define                          PIXC_TC  0xffc04450   /* Holds the transparent color value */
-
-/* Handshake MDMA 0 Registers */
-
-#define                   HMDMA0_CONTROL  0xffc04500   /* Handshake MDMA0 Control Register */
-#define                    HMDMA0_ECINIT  0xffc04504   /* Handshake MDMA0 Initial Edge Count Register */
-#define                    HMDMA0_BCINIT  0xffc04508   /* Handshake MDMA0 Initial Block Count Register */
-#define                  HMDMA0_ECURGENT  0xffc0450c   /* Handshake MDMA0 Urgent Edge Count Threshold Register */
-#define                HMDMA0_ECOVERFLOW  0xffc04510   /* Handshake MDMA0 Edge Count Overflow Interrupt Register */
-#define                    HMDMA0_ECOUNT  0xffc04514   /* Handshake MDMA0 Current Edge Count Register */
-#define                    HMDMA0_BCOUNT  0xffc04518   /* Handshake MDMA0 Current Block Count Register */
-
-/* Handshake MDMA 1 Registers */
-
-#define                   HMDMA1_CONTROL  0xffc04540   /* Handshake MDMA1 Control Register */
-#define                    HMDMA1_ECINIT  0xffc04544   /* Handshake MDMA1 Initial Edge Count Register */
-#define                    HMDMA1_BCINIT  0xffc04548   /* Handshake MDMA1 Initial Block Count Register */
-#define                  HMDMA1_ECURGENT  0xffc0454c   /* Handshake MDMA1 Urgent Edge Count Threshold Register */
-#define                HMDMA1_ECOVERFLOW  0xffc04550   /* Handshake MDMA1 Edge Count Overflow Interrupt Register */
-#define                    HMDMA1_ECOUNT  0xffc04554   /* Handshake MDMA1 Current Edge Count Register */
-#define                    HMDMA1_BCOUNT  0xffc04558   /* Handshake MDMA1 Current Block Count Register */
-
-
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for PIXC_CTL */
-
-#define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
-#define                  OVR_A_EN  0x2        /* Overlay A Enable */
-#define                  OVR_B_EN  0x4        /* Overlay B Enable */
-#define                  IMG_FORM  0x8        /* Image Data Format */
-#define                  OVR_FORM  0x10       /* Overlay Data Format */
-#define                  OUT_FORM  0x20       /* Output Data Format */
-#define                   UDS_MOD  0x40       /* Resampling Mode */
-#define                     TC_EN  0x80       /* Transparent Color Enable */
-#define                  IMG_STAT  0x300      /* Image FIFO Status */
-#define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
-#define                    WM_LVL  0x3000     /* FIFO Watermark Level */
-
-/* Bit masks for PIXC_AHSTART */
-
-#define                  A_HSTART  0xfff      /* Horizontal Start Coordinates */
-
-/* Bit masks for PIXC_AHEND */
-
-#define                    A_HEND  0xfff      /* Horizontal End Coordinates */
-
-/* Bit masks for PIXC_AVSTART */
-
-#define                  A_VSTART  0x3ff      /* Vertical Start Coordinates */
-
-/* Bit masks for PIXC_AVEND */
-
-#define                    A_VEND  0x3ff      /* Vertical End Coordinates */
-
-/* Bit masks for PIXC_ATRANSP */
-
-#define                  A_TRANSP  0xf        /* Transparency Value */
-
-/* Bit masks for PIXC_BHSTART */
-
-#define                  B_HSTART  0xfff      /* Horizontal Start Coordinates */
-
-/* Bit masks for PIXC_BHEND */
-
-#define                    B_HEND  0xfff      /* Horizontal End Coordinates */
-
-/* Bit masks for PIXC_BVSTART */
-
-#define                  B_VSTART  0x3ff      /* Vertical Start Coordinates */
-
-/* Bit masks for PIXC_BVEND */
-
-#define                    B_VEND  0x3ff      /* Vertical End Coordinates */
-
-/* Bit masks for PIXC_BTRANSP */
-
-#define                  B_TRANSP  0xf        /* Transparency Value */
-
-/* Bit masks for PIXC_INTRSTAT */
-
-#define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
-#define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
-#define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
-#define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
-
-/* Bit masks for PIXC_RYCON */
-
-#define                       A11  0x3ff      /* A11 in the Coefficient Matrix */
-#define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
-#define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
-#define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_GUCON */
-
-#define                       A21  0x3ff      /* A21 in the Coefficient Matrix */
-#define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
-#define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
-#define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_BVCON */
-
-#define                       A31  0x3ff      /* A31 in the Coefficient Matrix */
-#define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
-#define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
-#define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_CCBIAS */
-
-#define                       A14  0x3ff      /* A14 in the Bias Vector */
-#define                       A24  0xffc00    /* A24 in the Bias Vector */
-#define                       A34  0x3ff00000 /* A34 in the Bias Vector */
-
-/* Bit masks for PIXC_TC */
-
-#define                  RY_TRANS  0xff       /* Transparent Color - R/Y Component */
-#define                  GU_TRANS  0xff00     /* Transparent Color - G/U Component */
-#define                  BV_TRANS  0xff0000   /* Transparent Color - B/V Component */
-
-/* Bit masks for HOST_CONTROL */
-
-#define                   HOST_EN  0x1        /* Host Enable */
-#define                  HOST_END  0x2        /* Host Endianess */
-#define                 DATA_SIZE  0x4        /* Data Size */
-#define                  HOST_RST  0x8        /* Host Reset */
-#define                  HRDY_OVR  0x20       /* Host Ready Override */
-#define                  INT_MODE  0x40       /* Interrupt Mode */
-#define                     BT_EN  0x80       /* Bus Timeout Enable */
-#define                       EHW  0x100      /* Enable Host Write */
-#define                       EHR  0x200      /* Enable Host Read */
-#define                       BDR  0x400      /* Burst DMA Requests */
-
-/* Bit masks for HOST_STATUS */
-
-#define                 DMA_READY  0x1        /* DMA Ready */
-#define                  FIFOFULL  0x2        /* FIFO Full */
-#define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define              DMA_COMPLETE  0x8        /* DMA Complete */
-#define                      HSHK  0x10       /* Host Handshake */
-#define                 HSTIMEOUT  0x20       /* Host Timeout */
-#define                      HIRQ  0x40       /* Host Interrupt Request */
-#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define                   DMA_DIR  0x100      /* DMA Direction */
-#define                       BTE  0x200      /* Bus Timeout Enabled */
-
-/* Bit masks for HOST_TIMEOUT */
-
-#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
-
-/* Bit masks for KPAD_CTL */
-
-#define                   KPAD_EN  0x1        /* Keypad Enable */
-#define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
-#define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
-#define                KPAD_COLEN  0xe000     /* Column Enable Width */
-
-/* Bit masks for KPAD_PRESCALE */
-
-#define         KPAD_PRESCALE_VAL  0x3f       /* Key Prescale Value */
-
-/* Bit masks for KPAD_MSEL */
-
-#define                DBON_SCALE  0xff       /* Debounce Scale Value */
-#define              COLDRV_SCALE  0xff00     /* Column Driver Scale Value */
-
-/* Bit masks for KPAD_ROWCOL */
-
-#define                  KPAD_ROW  0xff       /* Rows Pressed */
-#define                  KPAD_COL  0xff00     /* Columns Pressed */
-
-/* Bit masks for KPAD_STAT */
-
-#define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
-#define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
-#define              KPAD_PRESSED  0x8        /* Key press current status */
-
-/* Bit masks for KPAD_SOFTEVAL */
-
-#define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
-
-/* Bit masks for SDH_COMMAND */
-
-#define                   CMD_IDX  0x3f       /* Command Index */
-#define                   CMD_RSP  0x40       /* Response */
-#define                 CMD_L_RSP  0x80       /* Long Response */
-#define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                CMD_PEND_E  0x200      /* Command Pending */
-#define                     CMD_E  0x400      /* Command Enable */
-
-/* Bit masks for SDH_PWR_CTL */
-
-#define                    PWR_ON  0x3        /* Power On */
-#if 0
-#define                       TBD  0x3c       /* TBD */
-#endif
-#define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                   ROD_CTL  0x80       /* Rod Control */
-
-/* Bit masks for SDH_CLK_CTL */
-
-#define                    CLKDIV  0xff       /* MC_CLK Divisor */
-#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-
-/* Bit masks for SDH_RESP_CMD */
-
-#define                  RESP_CMD  0x3f       /* Response Command */
-
-/* Bit masks for SDH_DATA_CTL */
-
-#define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
-
-/* Bit masks for SDH_STATUS */
-
-#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
-#define               DAT_TIME_OUT  0x8        /* Data Time Out */
-#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define              CMD_RESP_END  0x40       /* CMD Response End */
-#define                  CMD_SENT  0x80       /* CMD Sent */
-#define                   DAT_END  0x100      /* Data End */
-#define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define               DAT_BLK_END  0x400      /* Data Block End */
-#define                   CMD_ACT  0x800      /* CMD Active */
-#define                    TX_ACT  0x1000     /* Transmit Active */
-#define                    RX_ACT  0x2000     /* Receive Active */
-#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-
-/* Bit masks for SDH_STATUS_CLR */
-
-#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define              DAT_END_STAT  0x100      /* Data End Status */
-#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-
-/* Bit masks for SDH_MASK0 */
-
-#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define              DAT_END_MASK  0x100      /* Data End Mask */
-#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-
-/* Bit masks for SDH_FIFO_CNT */
-
-#define                FIFO_COUNT  0x7fff     /* FIFO Count */
-
-/* Bit masks for SDH_E_STATUS */
-
-#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define               SD_CARD_DET  0x10       /* SD Card Detect */
-
-/* Bit masks for SDH_E_MASK */
-
-#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                   SCD_MSK  0x40       /* Mask Card Detect */
-
-/* Bit masks for SDH_CFG */
-
-#define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                       MWE  0x8        /* Moving Window Enable */
-#define                    SD_RST  0x10       /* SDMMC Reset */
-#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-
-/* Bit masks for SDH_RD_WAIT_EN */
-
-#define                       RWR  0x1        /* Read Wait Request */
-
-/* Bit masks for ATAPI_CONTROL */
-
-#define                 PIO_START  0x1        /* Start PIO/Reg Op */
-#define               MULTI_START  0x2        /* Start Multi-DMA Op */
-#define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
-#define                  XFER_DIR  0x8        /* Transfer Direction */
-#define                  IORDY_EN  0x10       /* IORDY Enable */
-#define                FIFO_FLUSH  0x20       /* Flush FIFOs */
-#define                  SOFT_RST  0x40       /* Soft Reset */
-#define                   DEV_RST  0x80       /* Device Reset */
-#define                TFRCNT_RST  0x100      /* Trans Count Reset */
-#define               END_ON_TERM  0x200      /* End/Terminate Select */
-#define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
-#define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
-
-/* Bit masks for ATAPI_STATUS */
-
-#define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
-#define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
-#define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
-#define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
-
-/* Bit masks for ATAPI_DEV_ADDR */
-
-#define                  DEV_ADDR  0x1f       /* Device Address */
-
-/* Bit masks for ATAPI_INT_MASK */
-
-#define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
-#define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
-#define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
-#define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
-#define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
-#define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
-#define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
-#define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
-
-/* Bit masks for ATAPI_INT_STATUS */
-
-#define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
-#define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
-#define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
-#define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
-#define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
-#define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
-#define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
-#define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
-
-/* Bit masks for ATAPI_LINE_STATUS */
-
-#define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
-#define                ATAPI_DASP  0x2        /* Device dasp to host line status */
-#define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
-#define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
-#define                ATAPI_ADDR  0x70       /* ATAPI address line status */
-#define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
-#define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
-#define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
-#define               ATAPI_DIORN  0x400      /* ATAPI read line status */
-#define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
-
-/* Bit masks for ATAPI_SM_STATE */
-
-#define                PIO_CSTATE  0xf        /* PIO mode state machine current state */
-#define                DMA_CSTATE  0xf0       /* DMA mode state machine current state */
-#define             UDMAIN_CSTATE  0xf00      /* Ultra DMA-In mode state machine current state */
-#define            UDMAOUT_CSTATE  0xf000     /* ATAPI IORDY line status */
-
-/* Bit masks for ATAPI_TERMINATE */
-
-#define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
-
-/* Bit masks for ATAPI_REG_TIM_0 */
-
-#define                    T2_REG  0xff       /* End of cycle time for register access transfers */
-#define                  TEOC_REG  0xff00     /* Selects DIOR/DIOW pulsewidth */
-
-/* Bit masks for ATAPI_PIO_TIM_0 */
-
-#define                    T1_REG  0xf        /* Time from address valid to DIOR/DIOW */
-#define                T2_REG_PIO  0xff0      /* DIOR/DIOW pulsewidth */
-#define                    T4_REG  0xf000     /* DIOW data hold */
-
-/* Bit masks for ATAPI_PIO_TIM_1 */
-
-#define              TEOC_REG_PIO  0xff       /* End of cycle time for PIO access transfers. */
-
-/* Bit masks for ATAPI_MULTI_TIM_0 */
-
-#define                        TD  0xff       /* DIOR/DIOW asserted pulsewidth */
-#define                        TM  0xff00     /* Time from address valid to DIOR/DIOW */
-
-/* Bit masks for ATAPI_MULTI_TIM_1 */
-
-#define                       TKW  0xff       /* Selects DIOW negated pulsewidth */
-#define                       TKR  0xff00     /* Selects DIOR negated pulsewidth */
-
-/* Bit masks for ATAPI_MULTI_TIM_2 */
-
-#define                        TH  0xff       /* Selects DIOW data hold */
-#define                      TEOC  0xff00     /* Selects end of cycle for DMA */
-
-/* Bit masks for ATAPI_ULTRA_TIM_0 */
-
-#define                      TACK  0xff       /* Selects setup and hold times for TACK */
-#define                      TENV  0xff00     /* Selects envelope time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_1 */
-
-#define                      TDVS  0xff       /* Selects data valid setup time */
-#define                 TCYC_TDVS  0xff00     /* Selects cycle time - TDVS time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_2 */
-
-#define                       TSS  0xff       /* Selects time from STROBE edge to negation of DMARQ or assertion of STOP */
-#define                      TMLI  0xff00     /* Selects interlock time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_3 */
-
-#define                      TZAH  0xff       /* Selects minimum delay required for output */
-#define               READY_PAUSE  0xff00     /* Selects ready to pause */
-
-/* Bit masks for TIMER_ENABLE1 */
-
-#define                    TIMEN8  0x1        /* Timer 8 Enable */
-#define                    TIMEN9  0x2        /* Timer 9 Enable */
-#define                   TIMEN10  0x4        /* Timer 10 Enable */
-
-/* Bit masks for TIMER_DISABLE1 */
-
-#define                   TIMDIS8  0x1        /* Timer 8 Disable */
-#define                   TIMDIS9  0x2        /* Timer 9 Disable */
-#define                  TIMDIS10  0x4        /* Timer 10 Disable */
-
-/* Bit masks for TIMER_STATUS1 */
-
-#define                    TIMIL8  0x1        /* Timer 8 Interrupt */
-#define                    TIMIL9  0x2        /* Timer 9 Interrupt */
-#define                   TIMIL10  0x4        /* Timer 10 Interrupt */
-#define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
-#define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
-#define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
-#define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
-#define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
-#define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
-
-/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
-
-/* Bit masks for USB_FADDR */
-
-#define          FUNCTION_ADDRESS  0x7f       /* Function address */
-
-/* Bit masks for USB_POWER */
-
-#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define               RESUME_MODE  0x4        /* DMA Mode */
-#define                     RESET  0x8        /* Reset indicator */
-#define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                 SOFT_CONN  0x40       /* Soft connect */
-#define                ISO_UPDATE  0x80       /* Isochronous update */
-
-/* Bit masks for USB_INTRTX */
-
-#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-
-/* Bit masks for USB_INTRRX */
-
-#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-
-/* Bit masks for USB_INTRTXE */
-
-#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-
-/* Bit masks for USB_INTRRXE */
-
-#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-
-/* Bit masks for USB_INTRUSB */
-
-#define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                  RESUME_B  0x2        /* Resume indicator */
-#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define                     SOF_B  0x8        /* Start of frame */
-#define                    CONN_B  0x10       /* Connection indicator */
-#define                  DISCON_B  0x20       /* Disconnect indicator */
-#define             SESSION_REQ_B  0x40       /* Session Request */
-#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-
-/* Bit masks for USB_INTRUSBE */
-
-#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-
-/* Bit masks for USB_FRAME */
-
-#define              FRAME_NUMBER  0x7ff      /* Frame number */
-
-/* Bit masks for USB_INDEX */
-
-#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
-
-/* Bit masks for USB_GLOBAL_CTL */
-
-#define                GLOBAL_ENA  0x1        /* enables USB module */
-#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-
-/* Bit masks for USB_OTG_DEV_CTL */
-
-#define                   SESSION  0x1        /* session indicator */
-#define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                     LSDEV  0x20       /* Low-speed indicator */
-#define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-
-/* Bit masks for USB_OTG_VBUS_IRQ */
-
-#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-
-/* Bit masks for USB_OTG_VBUS_MASK */
-
-#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-
-/* Bit masks for USB_CSR0 */
-
-#define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                STALL_SENT  0x4        /* STALL handshake sent */
-#define                   DATAEND  0x8        /* Data end indicator */
-#define                  SETUPEND  0x10       /* Setup end */
-#define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-
-/* Bit masks for USB_COUNT0 */
-
-#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
-
-/* Bit masks for USB_NAKLIMIT0 */
-
-#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
-
-/* Bit masks for USB_TX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_RX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_TXCSR */
-
-#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                  ERROR_TH  0x4        /* error condition host mode */
-#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-
-/* Bit masks for USB_TXCOUNT */
-
-#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* Bit masks for USB_RXCSR */
-
-#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-
-/* Bit masks for USB_RXCOUNT */
-
-#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
-
-/* Bit masks for USB_TXTYPE */
-
-#define            TARGET_EP_NO_T  0xf        /* EP number */
-#define                PROTOCOL_T  0xc        /* transfer type */
-
-/* Bit masks for USB_TXINTERVAL */
-
-#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
-
-/* Bit masks for USB_RXTYPE */
-
-#define            TARGET_EP_NO_R  0xf        /* EP number */
-#define                PROTOCOL_R  0xc        /* transfer type */
-
-/* Bit masks for USB_RXINTERVAL */
-
-#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
-
-/* Bit masks for USB_DMA_INTERRUPT */
-
-#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-
-/* Bit masks for USB_DMAxCONTROL */
-
-#define                   DMA_ENA  0x1        /* DMA enable */
-#define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                      MODE  0x4        /* DMA Bus error */
-#define                   INT_ENA  0x8        /* Interrupt enable */
-#define                     EPNUM  0xf0       /* EP number */
-#define                  BUSERROR  0x100      /* DMA Bus error */
-
-/* Bit masks for USB_DMAxADDRHIGH */
-
-#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxADDRLOW */
-
-#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTHIGH */
-
-#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTLOW */
-
-#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
-
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
-
 #endif /* _DEF_BF548_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF549.h b/arch/blackfin/mach-bf548/include/mach/defBF549.h
index f7f0435..5a04e6d 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF549.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF549.h
@@ -10,121 +10,13 @@
 /* Include all Core registers and bit definitions */
 #include <asm/def_LPBlackfin.h>
 
-
 /* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF549 */
 
 /* Include defBF54x_base.h for the set of #defines that are common to all ADSP-BF54x processors */
 #include "defBF54x_base.h"
 
-/* The following are the #defines needed by ADSP-BF549 that are not in the common header */
-
-/* Timer Registers */
-
-#define                    TIMER8_CONFIG  0xffc00600   /* Timer 8 Configuration Register */
-#define                   TIMER8_COUNTER  0xffc00604   /* Timer 8 Counter Register */
-#define                    TIMER8_PERIOD  0xffc00608   /* Timer 8 Period Register */
-#define                     TIMER8_WIDTH  0xffc0060c   /* Timer 8 Width Register */
-#define                    TIMER9_CONFIG  0xffc00610   /* Timer 9 Configuration Register */
-#define                   TIMER9_COUNTER  0xffc00614   /* Timer 9 Counter Register */
-#define                    TIMER9_PERIOD  0xffc00618   /* Timer 9 Period Register */
-#define                     TIMER9_WIDTH  0xffc0061c   /* Timer 9 Width Register */
-#define                   TIMER10_CONFIG  0xffc00620   /* Timer 10 Configuration Register */
-#define                  TIMER10_COUNTER  0xffc00624   /* Timer 10 Counter Register */
-#define                   TIMER10_PERIOD  0xffc00628   /* Timer 10 Period Register */
-#define                    TIMER10_WIDTH  0xffc0062c   /* Timer 10 Width Register */
-
-/* Timer Group of 3 Registers */
-
-#define                    TIMER_ENABLE1  0xffc00640   /* Timer Group of 3 Enable Register */
-#define                   TIMER_DISABLE1  0xffc00644   /* Timer Group of 3 Disable Register */
-#define                    TIMER_STATUS1  0xffc00648   /* Timer Group of 3 Status Register */
-
-/* SPORT0 Registers */
-
-#define                      SPORT0_TCR1  0xffc00800   /* SPORT0 Transmit Configuration 1 Register */
-#define                      SPORT0_TCR2  0xffc00804   /* SPORT0 Transmit Configuration 2 Register */
-#define                   SPORT0_TCLKDIV  0xffc00808   /* SPORT0 Transmit Serial Clock Divider Register */
-#define                    SPORT0_TFSDIV  0xffc0080c   /* SPORT0 Transmit Frame Sync Divider Register */
-#define                        SPORT0_TX  0xffc00810   /* SPORT0 Transmit Data Register */
-#define                        SPORT0_RX  0xffc00818   /* SPORT0 Receive Data Register */
-#define                      SPORT0_RCR1  0xffc00820   /* SPORT0 Receive Configuration 1 Register */
-#define                      SPORT0_RCR2  0xffc00824   /* SPORT0 Receive Configuration 2 Register */
-#define                   SPORT0_RCLKDIV  0xffc00828   /* SPORT0 Receive Serial Clock Divider Register */
-#define                    SPORT0_RFSDIV  0xffc0082c   /* SPORT0 Receive Frame Sync Divider Register */
-#define                      SPORT0_STAT  0xffc00830   /* SPORT0 Status Register */
-#define                      SPORT0_CHNL  0xffc00834   /* SPORT0 Current Channel Register */
-#define                     SPORT0_MCMC1  0xffc00838   /* SPORT0 Multi channel Configuration Register 1 */
-#define                     SPORT0_MCMC2  0xffc0083c   /* SPORT0 Multi channel Configuration Register 2 */
-#define                     SPORT0_MTCS0  0xffc00840   /* SPORT0 Multi channel Transmit Select Register 0 */
-#define                     SPORT0_MTCS1  0xffc00844   /* SPORT0 Multi channel Transmit Select Register 1 */
-#define                     SPORT0_MTCS2  0xffc00848   /* SPORT0 Multi channel Transmit Select Register 2 */
-#define                     SPORT0_MTCS3  0xffc0084c   /* SPORT0 Multi channel Transmit Select Register 3 */
-#define                     SPORT0_MRCS0  0xffc00850   /* SPORT0 Multi channel Receive Select Register 0 */
-#define                     SPORT0_MRCS1  0xffc00854   /* SPORT0 Multi channel Receive Select Register 1 */
-#define                     SPORT0_MRCS2  0xffc00858   /* SPORT0 Multi channel Receive Select Register 2 */
-#define                     SPORT0_MRCS3  0xffc0085c   /* SPORT0 Multi channel Receive Select Register 3 */
-
-/* EPPI0 Registers */
-
-#define                     EPPI0_STATUS  0xffc01000   /* EPPI0 Status Register */
-#define                     EPPI0_HCOUNT  0xffc01004   /* EPPI0 Horizontal Transfer Count Register */
-#define                     EPPI0_HDELAY  0xffc01008   /* EPPI0 Horizontal Delay Count Register */
-#define                     EPPI0_VCOUNT  0xffc0100c   /* EPPI0 Vertical Transfer Count Register */
-#define                     EPPI0_VDELAY  0xffc01010   /* EPPI0 Vertical Delay Count Register */
-#define                      EPPI0_FRAME  0xffc01014   /* EPPI0 Lines per Frame Register */
-#define                       EPPI0_LINE  0xffc01018   /* EPPI0 Samples per Line Register */
-#define                     EPPI0_CLKDIV  0xffc0101c   /* EPPI0 Clock Divide Register */
-#define                    EPPI0_CONTROL  0xffc01020   /* EPPI0 Control Register */
-#define                   EPPI0_FS1W_HBL  0xffc01024   /* EPPI0 FS1 Width Register / EPPI0 Horizontal Blanking Samples Per Line Register */
-#define                  EPPI0_FS1P_AVPL  0xffc01028   /* EPPI0 FS1 Period Register / EPPI0 Active Video Samples Per Line Register */
-#define                   EPPI0_FS2W_LVB  0xffc0102c   /* EPPI0 FS2 Width Register / EPPI0 Lines of Vertical Blanking Register */
-#define                  EPPI0_FS2P_LAVF  0xffc01030   /* EPPI0 FS2 Period Register/ EPPI0 Lines of Active Video Per Field Register */
-#define                       EPPI0_CLIP  0xffc01034   /* EPPI0 Clipping Register */
-
-/* UART2 Registers */
-
-#define                        UART2_DLL  0xffc02100   /* Divisor Latch Low Byte */
-#define                        UART2_DLH  0xffc02104   /* Divisor Latch High Byte */
-#define                       UART2_GCTL  0xffc02108   /* Global Control Register */
-#define                        UART2_LCR  0xffc0210c   /* Line Control Register */
-#define                        UART2_MCR  0xffc02110   /* Modem Control Register */
-#define                        UART2_LSR  0xffc02114   /* Line Status Register */
-#define                        UART2_MSR  0xffc02118   /* Modem Status Register */
-#define                        UART2_SCR  0xffc0211c   /* Scratch Register */
-#define                    UART2_IER_SET  0xffc02120   /* Interrupt Enable Register Set */
-#define                  UART2_IER_CLEAR  0xffc02124   /* Interrupt Enable Register Clear */
-#define                        UART2_RBR  0xffc0212c   /* Receive Buffer Register */
-
-/* Two Wire Interface Registers (TWI1) */
-
-#define                     TWI1_REGBASE  0xffc02200
-#define                      TWI1_CLKDIV  0xffc02200   /* Clock Divider Register */
-#define                     TWI1_CONTROL  0xffc02204   /* TWI Control Register */
-#define                  TWI1_SLAVE_CTRL  0xffc02208   /* TWI Slave Mode Control Register */
-#define                  TWI1_SLAVE_STAT  0xffc0220c   /* TWI Slave Mode Status Register */
-#define                  TWI1_SLAVE_ADDR  0xffc02210   /* TWI Slave Mode Address Register */
-#define                 TWI1_MASTER_CTRL  0xffc02214   /* TWI Master Mode Control Register */
-#define                 TWI1_MASTER_STAT  0xffc02218   /* TWI Master Mode Status Register */
-#define                 TWI1_MASTER_ADDR  0xffc0221c   /* TWI Master Mode Address Register */
-#define                    TWI1_INT_STAT  0xffc02220   /* TWI Interrupt Status Register */
-#define                    TWI1_INT_MASK  0xffc02224   /* TWI Interrupt Mask Register */
-#define                   TWI1_FIFO_CTRL  0xffc02228   /* TWI FIFO Control Register */
-#define                   TWI1_FIFO_STAT  0xffc0222c   /* TWI FIFO Status Register */
-#define                   TWI1_XMT_DATA8  0xffc02280   /* TWI FIFO Transmit Data Single Byte Register */
-#define                  TWI1_XMT_DATA16  0xffc02284   /* TWI FIFO Transmit Data Double Byte Register */
-#define                   TWI1_RCV_DATA8  0xffc02288   /* TWI FIFO Receive Data Single Byte Register */
-#define                  TWI1_RCV_DATA16  0xffc0228c   /* TWI FIFO Receive Data Double Byte Register */
-
-/* SPI2  Registers */
-
-#define                     SPI2_REGBASE  0xffc02400
-#define                         SPI2_CTL  0xffc02400   /* SPI2 Control Register */
-#define                         SPI2_FLG  0xffc02404   /* SPI2 Flag Register */
-#define                        SPI2_STAT  0xffc02408   /* SPI2 Status Register */
-#define                        SPI2_TDBR  0xffc0240c   /* SPI2 Transmit Data Buffer Register */
-#define                        SPI2_RDBR  0xffc02410   /* SPI2 Receive Data Buffer Register */
-#define                        SPI2_BAUD  0xffc02414   /* SPI2 Baud Rate Register */
-#define                      SPI2_SHADOW  0xffc02418   /* SPI2 Receive Data Buffer Shadow Register */
+/* The BF549 is like the BF544, but has MXVR */
+#include "defBF547.h"
 
 /* MXVR Registers */
 
@@ -296,2418 +188,4 @@
 #define                     MXVR_PIN_CTL  0xffc028dc   /* MXVR Pin Control Register */
 #define                    MXVR_SCLK_CNT  0xffc028e0   /* MXVR System Clock Counter Register */
 
-/* CAN Controller 1 Config 1 Registers */
-
-#define                         CAN1_MC1  0xffc03200   /* CAN Controller 1 Mailbox Configuration Register 1 */
-#define                         CAN1_MD1  0xffc03204   /* CAN Controller 1 Mailbox Direction Register 1 */
-#define                        CAN1_TRS1  0xffc03208   /* CAN Controller 1 Transmit Request Set Register 1 */
-#define                        CAN1_TRR1  0xffc0320c   /* CAN Controller 1 Transmit Request Reset Register 1 */
-#define                         CAN1_TA1  0xffc03210   /* CAN Controller 1 Transmit Acknowledge Register 1 */
-#define                         CAN1_AA1  0xffc03214   /* CAN Controller 1 Abort Acknowledge Register 1 */
-#define                        CAN1_RMP1  0xffc03218   /* CAN Controller 1 Receive Message Pending Register 1 */
-#define                        CAN1_RML1  0xffc0321c   /* CAN Controller 1 Receive Message Lost Register 1 */
-#define                      CAN1_MBTIF1  0xffc03220   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 1 */
-#define                      CAN1_MBRIF1  0xffc03224   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 1 */
-#define                       CAN1_MBIM1  0xffc03228   /* CAN Controller 1 Mailbox Interrupt Mask Register 1 */
-#define                        CAN1_RFH1  0xffc0322c   /* CAN Controller 1 Remote Frame Handling Enable Register 1 */
-#define                       CAN1_OPSS1  0xffc03230   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 1 */
-
-/* CAN Controller 1 Config 2 Registers */
-
-#define                         CAN1_MC2  0xffc03240   /* CAN Controller 1 Mailbox Configuration Register 2 */
-#define                         CAN1_MD2  0xffc03244   /* CAN Controller 1 Mailbox Direction Register 2 */
-#define                        CAN1_TRS2  0xffc03248   /* CAN Controller 1 Transmit Request Set Register 2 */
-#define                        CAN1_TRR2  0xffc0324c   /* CAN Controller 1 Transmit Request Reset Register 2 */
-#define                         CAN1_TA2  0xffc03250   /* CAN Controller 1 Transmit Acknowledge Register 2 */
-#define                         CAN1_AA2  0xffc03254   /* CAN Controller 1 Abort Acknowledge Register 2 */
-#define                        CAN1_RMP2  0xffc03258   /* CAN Controller 1 Receive Message Pending Register 2 */
-#define                        CAN1_RML2  0xffc0325c   /* CAN Controller 1 Receive Message Lost Register 2 */
-#define                      CAN1_MBTIF2  0xffc03260   /* CAN Controller 1 Mailbox Transmit Interrupt Flag Register 2 */
-#define                      CAN1_MBRIF2  0xffc03264   /* CAN Controller 1 Mailbox Receive Interrupt Flag Register 2 */
-#define                       CAN1_MBIM2  0xffc03268   /* CAN Controller 1 Mailbox Interrupt Mask Register 2 */
-#define                        CAN1_RFH2  0xffc0326c   /* CAN Controller 1 Remote Frame Handling Enable Register 2 */
-#define                       CAN1_OPSS2  0xffc03270   /* CAN Controller 1 Overwrite Protection Single Shot Transmit Register 2 */
-
-/* CAN Controller 1 Clock/Interrupt/Counter Registers */
-
-#define                       CAN1_CLOCK  0xffc03280   /* CAN Controller 1 Clock Register */
-#define                      CAN1_TIMING  0xffc03284   /* CAN Controller 1 Timing Register */
-#define                       CAN1_DEBUG  0xffc03288   /* CAN Controller 1 Debug Register */
-#define                      CAN1_STATUS  0xffc0328c   /* CAN Controller 1 Global Status Register */
-#define                         CAN1_CEC  0xffc03290   /* CAN Controller 1 Error Counter Register */
-#define                         CAN1_GIS  0xffc03294   /* CAN Controller 1 Global Interrupt Status Register */
-#define                         CAN1_GIM  0xffc03298   /* CAN Controller 1 Global Interrupt Mask Register */
-#define                         CAN1_GIF  0xffc0329c   /* CAN Controller 1 Global Interrupt Flag Register */
-#define                     CAN1_CONTROL  0xffc032a0   /* CAN Controller 1 Master Control Register */
-#define                        CAN1_INTR  0xffc032a4   /* CAN Controller 1 Interrupt Pending Register */
-#define                        CAN1_MBTD  0xffc032ac   /* CAN Controller 1 Mailbox Temporary Disable Register */
-#define                         CAN1_EWR  0xffc032b0   /* CAN Controller 1 Programmable Warning Level Register */
-#define                         CAN1_ESR  0xffc032b4   /* CAN Controller 1 Error Status Register */
-#define                       CAN1_UCCNT  0xffc032c4   /* CAN Controller 1 Universal Counter Register */
-#define                        CAN1_UCRC  0xffc032c8   /* CAN Controller 1 Universal Counter Force Reload Register */
-#define                       CAN1_UCCNF  0xffc032cc   /* CAN Controller 1 Universal Counter Configuration Register */
-
-/* CAN Controller 1 Mailbox Acceptance Registers */
-
-#define                       CAN1_AM00L  0xffc03300   /* CAN Controller 1 Mailbox 0 Acceptance Mask High Register */
-#define                       CAN1_AM00H  0xffc03304   /* CAN Controller 1 Mailbox 0 Acceptance Mask Low Register */
-#define                       CAN1_AM01L  0xffc03308   /* CAN Controller 1 Mailbox 1 Acceptance Mask High Register */
-#define                       CAN1_AM01H  0xffc0330c   /* CAN Controller 1 Mailbox 1 Acceptance Mask Low Register */
-#define                       CAN1_AM02L  0xffc03310   /* CAN Controller 1 Mailbox 2 Acceptance Mask High Register */
-#define                       CAN1_AM02H  0xffc03314   /* CAN Controller 1 Mailbox 2 Acceptance Mask Low Register */
-#define                       CAN1_AM03L  0xffc03318   /* CAN Controller 1 Mailbox 3 Acceptance Mask High Register */
-#define                       CAN1_AM03H  0xffc0331c   /* CAN Controller 1 Mailbox 3 Acceptance Mask Low Register */
-#define                       CAN1_AM04L  0xffc03320   /* CAN Controller 1 Mailbox 4 Acceptance Mask High Register */
-#define                       CAN1_AM04H  0xffc03324   /* CAN Controller 1 Mailbox 4 Acceptance Mask Low Register */
-#define                       CAN1_AM05L  0xffc03328   /* CAN Controller 1 Mailbox 5 Acceptance Mask High Register */
-#define                       CAN1_AM05H  0xffc0332c   /* CAN Controller 1 Mailbox 5 Acceptance Mask Low Register */
-#define                       CAN1_AM06L  0xffc03330   /* CAN Controller 1 Mailbox 6 Acceptance Mask High Register */
-#define                       CAN1_AM06H  0xffc03334   /* CAN Controller 1 Mailbox 6 Acceptance Mask Low Register */
-#define                       CAN1_AM07L  0xffc03338   /* CAN Controller 1 Mailbox 7 Acceptance Mask High Register */
-#define                       CAN1_AM07H  0xffc0333c   /* CAN Controller 1 Mailbox 7 Acceptance Mask Low Register */
-#define                       CAN1_AM08L  0xffc03340   /* CAN Controller 1 Mailbox 8 Acceptance Mask High Register */
-#define                       CAN1_AM08H  0xffc03344   /* CAN Controller 1 Mailbox 8 Acceptance Mask Low Register */
-#define                       CAN1_AM09L  0xffc03348   /* CAN Controller 1 Mailbox 9 Acceptance Mask High Register */
-#define                       CAN1_AM09H  0xffc0334c   /* CAN Controller 1 Mailbox 9 Acceptance Mask Low Register */
-#define                       CAN1_AM10L  0xffc03350   /* CAN Controller 1 Mailbox 10 Acceptance Mask High Register */
-#define                       CAN1_AM10H  0xffc03354   /* CAN Controller 1 Mailbox 10 Acceptance Mask Low Register */
-#define                       CAN1_AM11L  0xffc03358   /* CAN Controller 1 Mailbox 11 Acceptance Mask High Register */
-#define                       CAN1_AM11H  0xffc0335c   /* CAN Controller 1 Mailbox 11 Acceptance Mask Low Register */
-#define                       CAN1_AM12L  0xffc03360   /* CAN Controller 1 Mailbox 12 Acceptance Mask High Register */
-#define                       CAN1_AM12H  0xffc03364   /* CAN Controller 1 Mailbox 12 Acceptance Mask Low Register */
-#define                       CAN1_AM13L  0xffc03368   /* CAN Controller 1 Mailbox 13 Acceptance Mask High Register */
-#define                       CAN1_AM13H  0xffc0336c   /* CAN Controller 1 Mailbox 13 Acceptance Mask Low Register */
-#define                       CAN1_AM14L  0xffc03370   /* CAN Controller 1 Mailbox 14 Acceptance Mask High Register */
-#define                       CAN1_AM14H  0xffc03374   /* CAN Controller 1 Mailbox 14 Acceptance Mask Low Register */
-#define                       CAN1_AM15L  0xffc03378   /* CAN Controller 1 Mailbox 15 Acceptance Mask High Register */
-#define                       CAN1_AM15H  0xffc0337c   /* CAN Controller 1 Mailbox 15 Acceptance Mask Low Register */
-
-/* CAN Controller 1 Mailbox Acceptance Registers */
-
-#define                       CAN1_AM16L  0xffc03380   /* CAN Controller 1 Mailbox 16 Acceptance Mask High Register */
-#define                       CAN1_AM16H  0xffc03384   /* CAN Controller 1 Mailbox 16 Acceptance Mask Low Register */
-#define                       CAN1_AM17L  0xffc03388   /* CAN Controller 1 Mailbox 17 Acceptance Mask High Register */
-#define                       CAN1_AM17H  0xffc0338c   /* CAN Controller 1 Mailbox 17 Acceptance Mask Low Register */
-#define                       CAN1_AM18L  0xffc03390   /* CAN Controller 1 Mailbox 18 Acceptance Mask High Register */
-#define                       CAN1_AM18H  0xffc03394   /* CAN Controller 1 Mailbox 18 Acceptance Mask Low Register */
-#define                       CAN1_AM19L  0xffc03398   /* CAN Controller 1 Mailbox 19 Acceptance Mask High Register */
-#define                       CAN1_AM19H  0xffc0339c   /* CAN Controller 1 Mailbox 19 Acceptance Mask Low Register */
-#define                       CAN1_AM20L  0xffc033a0   /* CAN Controller 1 Mailbox 20 Acceptance Mask High Register */
-#define                       CAN1_AM20H  0xffc033a4   /* CAN Controller 1 Mailbox 20 Acceptance Mask Low Register */
-#define                       CAN1_AM21L  0xffc033a8   /* CAN Controller 1 Mailbox 21 Acceptance Mask High Register */
-#define                       CAN1_AM21H  0xffc033ac   /* CAN Controller 1 Mailbox 21 Acceptance Mask Low Register */
-#define                       CAN1_AM22L  0xffc033b0   /* CAN Controller 1 Mailbox 22 Acceptance Mask High Register */
-#define                       CAN1_AM22H  0xffc033b4   /* CAN Controller 1 Mailbox 22 Acceptance Mask Low Register */
-#define                       CAN1_AM23L  0xffc033b8   /* CAN Controller 1 Mailbox 23 Acceptance Mask High Register */
-#define                       CAN1_AM23H  0xffc033bc   /* CAN Controller 1 Mailbox 23 Acceptance Mask Low Register */
-#define                       CAN1_AM24L  0xffc033c0   /* CAN Controller 1 Mailbox 24 Acceptance Mask High Register */
-#define                       CAN1_AM24H  0xffc033c4   /* CAN Controller 1 Mailbox 24 Acceptance Mask Low Register */
-#define                       CAN1_AM25L  0xffc033c8   /* CAN Controller 1 Mailbox 25 Acceptance Mask High Register */
-#define                       CAN1_AM25H  0xffc033cc   /* CAN Controller 1 Mailbox 25 Acceptance Mask Low Register */
-#define                       CAN1_AM26L  0xffc033d0   /* CAN Controller 1 Mailbox 26 Acceptance Mask High Register */
-#define                       CAN1_AM26H  0xffc033d4   /* CAN Controller 1 Mailbox 26 Acceptance Mask Low Register */
-#define                       CAN1_AM27L  0xffc033d8   /* CAN Controller 1 Mailbox 27 Acceptance Mask High Register */
-#define                       CAN1_AM27H  0xffc033dc   /* CAN Controller 1 Mailbox 27 Acceptance Mask Low Register */
-#define                       CAN1_AM28L  0xffc033e0   /* CAN Controller 1 Mailbox 28 Acceptance Mask High Register */
-#define                       CAN1_AM28H  0xffc033e4   /* CAN Controller 1 Mailbox 28 Acceptance Mask Low Register */
-#define                       CAN1_AM29L  0xffc033e8   /* CAN Controller 1 Mailbox 29 Acceptance Mask High Register */
-#define                       CAN1_AM29H  0xffc033ec   /* CAN Controller 1 Mailbox 29 Acceptance Mask Low Register */
-#define                       CAN1_AM30L  0xffc033f0   /* CAN Controller 1 Mailbox 30 Acceptance Mask High Register */
-#define                       CAN1_AM30H  0xffc033f4   /* CAN Controller 1 Mailbox 30 Acceptance Mask Low Register */
-#define                       CAN1_AM31L  0xffc033f8   /* CAN Controller 1 Mailbox 31 Acceptance Mask High Register */
-#define                       CAN1_AM31H  0xffc033fc   /* CAN Controller 1 Mailbox 31 Acceptance Mask Low Register */
-
-/* CAN Controller 1 Mailbox Data Registers */
-
-#define                  CAN1_MB00_DATA0  0xffc03400   /* CAN Controller 1 Mailbox 0 Data 0 Register */
-#define                  CAN1_MB00_DATA1  0xffc03404   /* CAN Controller 1 Mailbox 0 Data 1 Register */
-#define                  CAN1_MB00_DATA2  0xffc03408   /* CAN Controller 1 Mailbox 0 Data 2 Register */
-#define                  CAN1_MB00_DATA3  0xffc0340c   /* CAN Controller 1 Mailbox 0 Data 3 Register */
-#define                 CAN1_MB00_LENGTH  0xffc03410   /* CAN Controller 1 Mailbox 0 Length Register */
-#define              CAN1_MB00_TIMESTAMP  0xffc03414   /* CAN Controller 1 Mailbox 0 Timestamp Register */
-#define                    CAN1_MB00_ID0  0xffc03418   /* CAN Controller 1 Mailbox 0 ID0 Register */
-#define                    CAN1_MB00_ID1  0xffc0341c   /* CAN Controller 1 Mailbox 0 ID1 Register */
-#define                  CAN1_MB01_DATA0  0xffc03420   /* CAN Controller 1 Mailbox 1 Data 0 Register */
-#define                  CAN1_MB01_DATA1  0xffc03424   /* CAN Controller 1 Mailbox 1 Data 1 Register */
-#define                  CAN1_MB01_DATA2  0xffc03428   /* CAN Controller 1 Mailbox 1 Data 2 Register */
-#define                  CAN1_MB01_DATA3  0xffc0342c   /* CAN Controller 1 Mailbox 1 Data 3 Register */
-#define                 CAN1_MB01_LENGTH  0xffc03430   /* CAN Controller 1 Mailbox 1 Length Register */
-#define              CAN1_MB01_TIMESTAMP  0xffc03434   /* CAN Controller 1 Mailbox 1 Timestamp Register */
-#define                    CAN1_MB01_ID0  0xffc03438   /* CAN Controller 1 Mailbox 1 ID0 Register */
-#define                    CAN1_MB01_ID1  0xffc0343c   /* CAN Controller 1 Mailbox 1 ID1 Register */
-#define                  CAN1_MB02_DATA0  0xffc03440   /* CAN Controller 1 Mailbox 2 Data 0 Register */
-#define                  CAN1_MB02_DATA1  0xffc03444   /* CAN Controller 1 Mailbox 2 Data 1 Register */
-#define                  CAN1_MB02_DATA2  0xffc03448   /* CAN Controller 1 Mailbox 2 Data 2 Register */
-#define                  CAN1_MB02_DATA3  0xffc0344c   /* CAN Controller 1 Mailbox 2 Data 3 Register */
-#define                 CAN1_MB02_LENGTH  0xffc03450   /* CAN Controller 1 Mailbox 2 Length Register */
-#define              CAN1_MB02_TIMESTAMP  0xffc03454   /* CAN Controller 1 Mailbox 2 Timestamp Register */
-#define                    CAN1_MB02_ID0  0xffc03458   /* CAN Controller 1 Mailbox 2 ID0 Register */
-#define                    CAN1_MB02_ID1  0xffc0345c   /* CAN Controller 1 Mailbox 2 ID1 Register */
-#define                  CAN1_MB03_DATA0  0xffc03460   /* CAN Controller 1 Mailbox 3 Data 0 Register */
-#define                  CAN1_MB03_DATA1  0xffc03464   /* CAN Controller 1 Mailbox 3 Data 1 Register */
-#define                  CAN1_MB03_DATA2  0xffc03468   /* CAN Controller 1 Mailbox 3 Data 2 Register */
-#define                  CAN1_MB03_DATA3  0xffc0346c   /* CAN Controller 1 Mailbox 3 Data 3 Register */
-#define                 CAN1_MB03_LENGTH  0xffc03470   /* CAN Controller 1 Mailbox 3 Length Register */
-#define              CAN1_MB03_TIMESTAMP  0xffc03474   /* CAN Controller 1 Mailbox 3 Timestamp Register */
-#define                    CAN1_MB03_ID0  0xffc03478   /* CAN Controller 1 Mailbox 3 ID0 Register */
-#define                    CAN1_MB03_ID1  0xffc0347c   /* CAN Controller 1 Mailbox 3 ID1 Register */
-#define                  CAN1_MB04_DATA0  0xffc03480   /* CAN Controller 1 Mailbox 4 Data 0 Register */
-#define                  CAN1_MB04_DATA1  0xffc03484   /* CAN Controller 1 Mailbox 4 Data 1 Register */
-#define                  CAN1_MB04_DATA2  0xffc03488   /* CAN Controller 1 Mailbox 4 Data 2 Register */
-#define                  CAN1_MB04_DATA3  0xffc0348c   /* CAN Controller 1 Mailbox 4 Data 3 Register */
-#define                 CAN1_MB04_LENGTH  0xffc03490   /* CAN Controller 1 Mailbox 4 Length Register */
-#define              CAN1_MB04_TIMESTAMP  0xffc03494   /* CAN Controller 1 Mailbox 4 Timestamp Register */
-#define                    CAN1_MB04_ID0  0xffc03498   /* CAN Controller 1 Mailbox 4 ID0 Register */
-#define                    CAN1_MB04_ID1  0xffc0349c   /* CAN Controller 1 Mailbox 4 ID1 Register */
-#define                  CAN1_MB05_DATA0  0xffc034a0   /* CAN Controller 1 Mailbox 5 Data 0 Register */
-#define                  CAN1_MB05_DATA1  0xffc034a4   /* CAN Controller 1 Mailbox 5 Data 1 Register */
-#define                  CAN1_MB05_DATA2  0xffc034a8   /* CAN Controller 1 Mailbox 5 Data 2 Register */
-#define                  CAN1_MB05_DATA3  0xffc034ac   /* CAN Controller 1 Mailbox 5 Data 3 Register */
-#define                 CAN1_MB05_LENGTH  0xffc034b0   /* CAN Controller 1 Mailbox 5 Length Register */
-#define              CAN1_MB05_TIMESTAMP  0xffc034b4   /* CAN Controller 1 Mailbox 5 Timestamp Register */
-#define                    CAN1_MB05_ID0  0xffc034b8   /* CAN Controller 1 Mailbox 5 ID0 Register */
-#define                    CAN1_MB05_ID1  0xffc034bc   /* CAN Controller 1 Mailbox 5 ID1 Register */
-#define                  CAN1_MB06_DATA0  0xffc034c0   /* CAN Controller 1 Mailbox 6 Data 0 Register */
-#define                  CAN1_MB06_DATA1  0xffc034c4   /* CAN Controller 1 Mailbox 6 Data 1 Register */
-#define                  CAN1_MB06_DATA2  0xffc034c8   /* CAN Controller 1 Mailbox 6 Data 2 Register */
-#define                  CAN1_MB06_DATA3  0xffc034cc   /* CAN Controller 1 Mailbox 6 Data 3 Register */
-#define                 CAN1_MB06_LENGTH  0xffc034d0   /* CAN Controller 1 Mailbox 6 Length Register */
-#define              CAN1_MB06_TIMESTAMP  0xffc034d4   /* CAN Controller 1 Mailbox 6 Timestamp Register */
-#define                    CAN1_MB06_ID0  0xffc034d8   /* CAN Controller 1 Mailbox 6 ID0 Register */
-#define                    CAN1_MB06_ID1  0xffc034dc   /* CAN Controller 1 Mailbox 6 ID1 Register */
-#define                  CAN1_MB07_DATA0  0xffc034e0   /* CAN Controller 1 Mailbox 7 Data 0 Register */
-#define                  CAN1_MB07_DATA1  0xffc034e4   /* CAN Controller 1 Mailbox 7 Data 1 Register */
-#define                  CAN1_MB07_DATA2  0xffc034e8   /* CAN Controller 1 Mailbox 7 Data 2 Register */
-#define                  CAN1_MB07_DATA3  0xffc034ec   /* CAN Controller 1 Mailbox 7 Data 3 Register */
-#define                 CAN1_MB07_LENGTH  0xffc034f0   /* CAN Controller 1 Mailbox 7 Length Register */
-#define              CAN1_MB07_TIMESTAMP  0xffc034f4   /* CAN Controller 1 Mailbox 7 Timestamp Register */
-#define                    CAN1_MB07_ID0  0xffc034f8   /* CAN Controller 1 Mailbox 7 ID0 Register */
-#define                    CAN1_MB07_ID1  0xffc034fc   /* CAN Controller 1 Mailbox 7 ID1 Register */
-#define                  CAN1_MB08_DATA0  0xffc03500   /* CAN Controller 1 Mailbox 8 Data 0 Register */
-#define                  CAN1_MB08_DATA1  0xffc03504   /* CAN Controller 1 Mailbox 8 Data 1 Register */
-#define                  CAN1_MB08_DATA2  0xffc03508   /* CAN Controller 1 Mailbox 8 Data 2 Register */
-#define                  CAN1_MB08_DATA3  0xffc0350c   /* CAN Controller 1 Mailbox 8 Data 3 Register */
-#define                 CAN1_MB08_LENGTH  0xffc03510   /* CAN Controller 1 Mailbox 8 Length Register */
-#define              CAN1_MB08_TIMESTAMP  0xffc03514   /* CAN Controller 1 Mailbox 8 Timestamp Register */
-#define                    CAN1_MB08_ID0  0xffc03518   /* CAN Controller 1 Mailbox 8 ID0 Register */
-#define                    CAN1_MB08_ID1  0xffc0351c   /* CAN Controller 1 Mailbox 8 ID1 Register */
-#define                  CAN1_MB09_DATA0  0xffc03520   /* CAN Controller 1 Mailbox 9 Data 0 Register */
-#define                  CAN1_MB09_DATA1  0xffc03524   /* CAN Controller 1 Mailbox 9 Data 1 Register */
-#define                  CAN1_MB09_DATA2  0xffc03528   /* CAN Controller 1 Mailbox 9 Data 2 Register */
-#define                  CAN1_MB09_DATA3  0xffc0352c   /* CAN Controller 1 Mailbox 9 Data 3 Register */
-#define                 CAN1_MB09_LENGTH  0xffc03530   /* CAN Controller 1 Mailbox 9 Length Register */
-#define              CAN1_MB09_TIMESTAMP  0xffc03534   /* CAN Controller 1 Mailbox 9 Timestamp Register */
-#define                    CAN1_MB09_ID0  0xffc03538   /* CAN Controller 1 Mailbox 9 ID0 Register */
-#define                    CAN1_MB09_ID1  0xffc0353c   /* CAN Controller 1 Mailbox 9 ID1 Register */
-#define                  CAN1_MB10_DATA0  0xffc03540   /* CAN Controller 1 Mailbox 10 Data 0 Register */
-#define                  CAN1_MB10_DATA1  0xffc03544   /* CAN Controller 1 Mailbox 10 Data 1 Register */
-#define                  CAN1_MB10_DATA2  0xffc03548   /* CAN Controller 1 Mailbox 10 Data 2 Register */
-#define                  CAN1_MB10_DATA3  0xffc0354c   /* CAN Controller 1 Mailbox 10 Data 3 Register */
-#define                 CAN1_MB10_LENGTH  0xffc03550   /* CAN Controller 1 Mailbox 10 Length Register */
-#define              CAN1_MB10_TIMESTAMP  0xffc03554   /* CAN Controller 1 Mailbox 10 Timestamp Register */
-#define                    CAN1_MB10_ID0  0xffc03558   /* CAN Controller 1 Mailbox 10 ID0 Register */
-#define                    CAN1_MB10_ID1  0xffc0355c   /* CAN Controller 1 Mailbox 10 ID1 Register */
-#define                  CAN1_MB11_DATA0  0xffc03560   /* CAN Controller 1 Mailbox 11 Data 0 Register */
-#define                  CAN1_MB11_DATA1  0xffc03564   /* CAN Controller 1 Mailbox 11 Data 1 Register */
-#define                  CAN1_MB11_DATA2  0xffc03568   /* CAN Controller 1 Mailbox 11 Data 2 Register */
-#define                  CAN1_MB11_DATA3  0xffc0356c   /* CAN Controller 1 Mailbox 11 Data 3 Register */
-#define                 CAN1_MB11_LENGTH  0xffc03570   /* CAN Controller 1 Mailbox 11 Length Register */
-#define              CAN1_MB11_TIMESTAMP  0xffc03574   /* CAN Controller 1 Mailbox 11 Timestamp Register */
-#define                    CAN1_MB11_ID0  0xffc03578   /* CAN Controller 1 Mailbox 11 ID0 Register */
-#define                    CAN1_MB11_ID1  0xffc0357c   /* CAN Controller 1 Mailbox 11 ID1 Register */
-#define                  CAN1_MB12_DATA0  0xffc03580   /* CAN Controller 1 Mailbox 12 Data 0 Register */
-#define                  CAN1_MB12_DATA1  0xffc03584   /* CAN Controller 1 Mailbox 12 Data 1 Register */
-#define                  CAN1_MB12_DATA2  0xffc03588   /* CAN Controller 1 Mailbox 12 Data 2 Register */
-#define                  CAN1_MB12_DATA3  0xffc0358c   /* CAN Controller 1 Mailbox 12 Data 3 Register */
-#define                 CAN1_MB12_LENGTH  0xffc03590   /* CAN Controller 1 Mailbox 12 Length Register */
-#define              CAN1_MB12_TIMESTAMP  0xffc03594   /* CAN Controller 1 Mailbox 12 Timestamp Register */
-#define                    CAN1_MB12_ID0  0xffc03598   /* CAN Controller 1 Mailbox 12 ID0 Register */
-#define                    CAN1_MB12_ID1  0xffc0359c   /* CAN Controller 1 Mailbox 12 ID1 Register */
-#define                  CAN1_MB13_DATA0  0xffc035a0   /* CAN Controller 1 Mailbox 13 Data 0 Register */
-#define                  CAN1_MB13_DATA1  0xffc035a4   /* CAN Controller 1 Mailbox 13 Data 1 Register */
-#define                  CAN1_MB13_DATA2  0xffc035a8   /* CAN Controller 1 Mailbox 13 Data 2 Register */
-#define                  CAN1_MB13_DATA3  0xffc035ac   /* CAN Controller 1 Mailbox 13 Data 3 Register */
-#define                 CAN1_MB13_LENGTH  0xffc035b0   /* CAN Controller 1 Mailbox 13 Length Register */
-#define              CAN1_MB13_TIMESTAMP  0xffc035b4   /* CAN Controller 1 Mailbox 13 Timestamp Register */
-#define                    CAN1_MB13_ID0  0xffc035b8   /* CAN Controller 1 Mailbox 13 ID0 Register */
-#define                    CAN1_MB13_ID1  0xffc035bc   /* CAN Controller 1 Mailbox 13 ID1 Register */
-#define                  CAN1_MB14_DATA0  0xffc035c0   /* CAN Controller 1 Mailbox 14 Data 0 Register */
-#define                  CAN1_MB14_DATA1  0xffc035c4   /* CAN Controller 1 Mailbox 14 Data 1 Register */
-#define                  CAN1_MB14_DATA2  0xffc035c8   /* CAN Controller 1 Mailbox 14 Data 2 Register */
-#define                  CAN1_MB14_DATA3  0xffc035cc   /* CAN Controller 1 Mailbox 14 Data 3 Register */
-#define                 CAN1_MB14_LENGTH  0xffc035d0   /* CAN Controller 1 Mailbox 14 Length Register */
-#define              CAN1_MB14_TIMESTAMP  0xffc035d4   /* CAN Controller 1 Mailbox 14 Timestamp Register */
-#define                    CAN1_MB14_ID0  0xffc035d8   /* CAN Controller 1 Mailbox 14 ID0 Register */
-#define                    CAN1_MB14_ID1  0xffc035dc   /* CAN Controller 1 Mailbox 14 ID1 Register */
-#define                  CAN1_MB15_DATA0  0xffc035e0   /* CAN Controller 1 Mailbox 15 Data 0 Register */
-#define                  CAN1_MB15_DATA1  0xffc035e4   /* CAN Controller 1 Mailbox 15 Data 1 Register */
-#define                  CAN1_MB15_DATA2  0xffc035e8   /* CAN Controller 1 Mailbox 15 Data 2 Register */
-#define                  CAN1_MB15_DATA3  0xffc035ec   /* CAN Controller 1 Mailbox 15 Data 3 Register */
-#define                 CAN1_MB15_LENGTH  0xffc035f0   /* CAN Controller 1 Mailbox 15 Length Register */
-#define              CAN1_MB15_TIMESTAMP  0xffc035f4   /* CAN Controller 1 Mailbox 15 Timestamp Register */
-#define                    CAN1_MB15_ID0  0xffc035f8   /* CAN Controller 1 Mailbox 15 ID0 Register */
-#define                    CAN1_MB15_ID1  0xffc035fc   /* CAN Controller 1 Mailbox 15 ID1 Register */
-
-/* CAN Controller 1 Mailbox Data Registers */
-
-#define                  CAN1_MB16_DATA0  0xffc03600   /* CAN Controller 1 Mailbox 16 Data 0 Register */
-#define                  CAN1_MB16_DATA1  0xffc03604   /* CAN Controller 1 Mailbox 16 Data 1 Register */
-#define                  CAN1_MB16_DATA2  0xffc03608   /* CAN Controller 1 Mailbox 16 Data 2 Register */
-#define                  CAN1_MB16_DATA3  0xffc0360c   /* CAN Controller 1 Mailbox 16 Data 3 Register */
-#define                 CAN1_MB16_LENGTH  0xffc03610   /* CAN Controller 1 Mailbox 16 Length Register */
-#define              CAN1_MB16_TIMESTAMP  0xffc03614   /* CAN Controller 1 Mailbox 16 Timestamp Register */
-#define                    CAN1_MB16_ID0  0xffc03618   /* CAN Controller 1 Mailbox 16 ID0 Register */
-#define                    CAN1_MB16_ID1  0xffc0361c   /* CAN Controller 1 Mailbox 16 ID1 Register */
-#define                  CAN1_MB17_DATA0  0xffc03620   /* CAN Controller 1 Mailbox 17 Data 0 Register */
-#define                  CAN1_MB17_DATA1  0xffc03624   /* CAN Controller 1 Mailbox 17 Data 1 Register */
-#define                  CAN1_MB17_DATA2  0xffc03628   /* CAN Controller 1 Mailbox 17 Data 2 Register */
-#define                  CAN1_MB17_DATA3  0xffc0362c   /* CAN Controller 1 Mailbox 17 Data 3 Register */
-#define                 CAN1_MB17_LENGTH  0xffc03630   /* CAN Controller 1 Mailbox 17 Length Register */
-#define              CAN1_MB17_TIMESTAMP  0xffc03634   /* CAN Controller 1 Mailbox 17 Timestamp Register */
-#define                    CAN1_MB17_ID0  0xffc03638   /* CAN Controller 1 Mailbox 17 ID0 Register */
-#define                    CAN1_MB17_ID1  0xffc0363c   /* CAN Controller 1 Mailbox 17 ID1 Register */
-#define                  CAN1_MB18_DATA0  0xffc03640   /* CAN Controller 1 Mailbox 18 Data 0 Register */
-#define                  CAN1_MB18_DATA1  0xffc03644   /* CAN Controller 1 Mailbox 18 Data 1 Register */
-#define                  CAN1_MB18_DATA2  0xffc03648   /* CAN Controller 1 Mailbox 18 Data 2 Register */
-#define                  CAN1_MB18_DATA3  0xffc0364c   /* CAN Controller 1 Mailbox 18 Data 3 Register */
-#define                 CAN1_MB18_LENGTH  0xffc03650   /* CAN Controller 1 Mailbox 18 Length Register */
-#define              CAN1_MB18_TIMESTAMP  0xffc03654   /* CAN Controller 1 Mailbox 18 Timestamp Register */
-#define                    CAN1_MB18_ID0  0xffc03658   /* CAN Controller 1 Mailbox 18 ID0 Register */
-#define                    CAN1_MB18_ID1  0xffc0365c   /* CAN Controller 1 Mailbox 18 ID1 Register */
-#define                  CAN1_MB19_DATA0  0xffc03660   /* CAN Controller 1 Mailbox 19 Data 0 Register */
-#define                  CAN1_MB19_DATA1  0xffc03664   /* CAN Controller 1 Mailbox 19 Data 1 Register */
-#define                  CAN1_MB19_DATA2  0xffc03668   /* CAN Controller 1 Mailbox 19 Data 2 Register */
-#define                  CAN1_MB19_DATA3  0xffc0366c   /* CAN Controller 1 Mailbox 19 Data 3 Register */
-#define                 CAN1_MB19_LENGTH  0xffc03670   /* CAN Controller 1 Mailbox 19 Length Register */
-#define              CAN1_MB19_TIMESTAMP  0xffc03674   /* CAN Controller 1 Mailbox 19 Timestamp Register */
-#define                    CAN1_MB19_ID0  0xffc03678   /* CAN Controller 1 Mailbox 19 ID0 Register */
-#define                    CAN1_MB19_ID1  0xffc0367c   /* CAN Controller 1 Mailbox 19 ID1 Register */
-#define                  CAN1_MB20_DATA0  0xffc03680   /* CAN Controller 1 Mailbox 20 Data 0 Register */
-#define                  CAN1_MB20_DATA1  0xffc03684   /* CAN Controller 1 Mailbox 20 Data 1 Register */
-#define                  CAN1_MB20_DATA2  0xffc03688   /* CAN Controller 1 Mailbox 20 Data 2 Register */
-#define                  CAN1_MB20_DATA3  0xffc0368c   /* CAN Controller 1 Mailbox 20 Data 3 Register */
-#define                 CAN1_MB20_LENGTH  0xffc03690   /* CAN Controller 1 Mailbox 20 Length Register */
-#define              CAN1_MB20_TIMESTAMP  0xffc03694   /* CAN Controller 1 Mailbox 20 Timestamp Register */
-#define                    CAN1_MB20_ID0  0xffc03698   /* CAN Controller 1 Mailbox 20 ID0 Register */
-#define                    CAN1_MB20_ID1  0xffc0369c   /* CAN Controller 1 Mailbox 20 ID1 Register */
-#define                  CAN1_MB21_DATA0  0xffc036a0   /* CAN Controller 1 Mailbox 21 Data 0 Register */
-#define                  CAN1_MB21_DATA1  0xffc036a4   /* CAN Controller 1 Mailbox 21 Data 1 Register */
-#define                  CAN1_MB21_DATA2  0xffc036a8   /* CAN Controller 1 Mailbox 21 Data 2 Register */
-#define                  CAN1_MB21_DATA3  0xffc036ac   /* CAN Controller 1 Mailbox 21 Data 3 Register */
-#define                 CAN1_MB21_LENGTH  0xffc036b0   /* CAN Controller 1 Mailbox 21 Length Register */
-#define              CAN1_MB21_TIMESTAMP  0xffc036b4   /* CAN Controller 1 Mailbox 21 Timestamp Register */
-#define                    CAN1_MB21_ID0  0xffc036b8   /* CAN Controller 1 Mailbox 21 ID0 Register */
-#define                    CAN1_MB21_ID1  0xffc036bc   /* CAN Controller 1 Mailbox 21 ID1 Register */
-#define                  CAN1_MB22_DATA0  0xffc036c0   /* CAN Controller 1 Mailbox 22 Data 0 Register */
-#define                  CAN1_MB22_DATA1  0xffc036c4   /* CAN Controller 1 Mailbox 22 Data 1 Register */
-#define                  CAN1_MB22_DATA2  0xffc036c8   /* CAN Controller 1 Mailbox 22 Data 2 Register */
-#define                  CAN1_MB22_DATA3  0xffc036cc   /* CAN Controller 1 Mailbox 22 Data 3 Register */
-#define                 CAN1_MB22_LENGTH  0xffc036d0   /* CAN Controller 1 Mailbox 22 Length Register */
-#define              CAN1_MB22_TIMESTAMP  0xffc036d4   /* CAN Controller 1 Mailbox 22 Timestamp Register */
-#define                    CAN1_MB22_ID0  0xffc036d8   /* CAN Controller 1 Mailbox 22 ID0 Register */
-#define                    CAN1_MB22_ID1  0xffc036dc   /* CAN Controller 1 Mailbox 22 ID1 Register */
-#define                  CAN1_MB23_DATA0  0xffc036e0   /* CAN Controller 1 Mailbox 23 Data 0 Register */
-#define                  CAN1_MB23_DATA1  0xffc036e4   /* CAN Controller 1 Mailbox 23 Data 1 Register */
-#define                  CAN1_MB23_DATA2  0xffc036e8   /* CAN Controller 1 Mailbox 23 Data 2 Register */
-#define                  CAN1_MB23_DATA3  0xffc036ec   /* CAN Controller 1 Mailbox 23 Data 3 Register */
-#define                 CAN1_MB23_LENGTH  0xffc036f0   /* CAN Controller 1 Mailbox 23 Length Register */
-#define              CAN1_MB23_TIMESTAMP  0xffc036f4   /* CAN Controller 1 Mailbox 23 Timestamp Register */
-#define                    CAN1_MB23_ID0  0xffc036f8   /* CAN Controller 1 Mailbox 23 ID0 Register */
-#define                    CAN1_MB23_ID1  0xffc036fc   /* CAN Controller 1 Mailbox 23 ID1 Register */
-#define                  CAN1_MB24_DATA0  0xffc03700   /* CAN Controller 1 Mailbox 24 Data 0 Register */
-#define                  CAN1_MB24_DATA1  0xffc03704   /* CAN Controller 1 Mailbox 24 Data 1 Register */
-#define                  CAN1_MB24_DATA2  0xffc03708   /* CAN Controller 1 Mailbox 24 Data 2 Register */
-#define                  CAN1_MB24_DATA3  0xffc0370c   /* CAN Controller 1 Mailbox 24 Data 3 Register */
-#define                 CAN1_MB24_LENGTH  0xffc03710   /* CAN Controller 1 Mailbox 24 Length Register */
-#define              CAN1_MB24_TIMESTAMP  0xffc03714   /* CAN Controller 1 Mailbox 24 Timestamp Register */
-#define                    CAN1_MB24_ID0  0xffc03718   /* CAN Controller 1 Mailbox 24 ID0 Register */
-#define                    CAN1_MB24_ID1  0xffc0371c   /* CAN Controller 1 Mailbox 24 ID1 Register */
-#define                  CAN1_MB25_DATA0  0xffc03720   /* CAN Controller 1 Mailbox 25 Data 0 Register */
-#define                  CAN1_MB25_DATA1  0xffc03724   /* CAN Controller 1 Mailbox 25 Data 1 Register */
-#define                  CAN1_MB25_DATA2  0xffc03728   /* CAN Controller 1 Mailbox 25 Data 2 Register */
-#define                  CAN1_MB25_DATA3  0xffc0372c   /* CAN Controller 1 Mailbox 25 Data 3 Register */
-#define                 CAN1_MB25_LENGTH  0xffc03730   /* CAN Controller 1 Mailbox 25 Length Register */
-#define              CAN1_MB25_TIMESTAMP  0xffc03734   /* CAN Controller 1 Mailbox 25 Timestamp Register */
-#define                    CAN1_MB25_ID0  0xffc03738   /* CAN Controller 1 Mailbox 25 ID0 Register */
-#define                    CAN1_MB25_ID1  0xffc0373c   /* CAN Controller 1 Mailbox 25 ID1 Register */
-#define                  CAN1_MB26_DATA0  0xffc03740   /* CAN Controller 1 Mailbox 26 Data 0 Register */
-#define                  CAN1_MB26_DATA1  0xffc03744   /* CAN Controller 1 Mailbox 26 Data 1 Register */
-#define                  CAN1_MB26_DATA2  0xffc03748   /* CAN Controller 1 Mailbox 26 Data 2 Register */
-#define                  CAN1_MB26_DATA3  0xffc0374c   /* CAN Controller 1 Mailbox 26 Data 3 Register */
-#define                 CAN1_MB26_LENGTH  0xffc03750   /* CAN Controller 1 Mailbox 26 Length Register */
-#define              CAN1_MB26_TIMESTAMP  0xffc03754   /* CAN Controller 1 Mailbox 26 Timestamp Register */
-#define                    CAN1_MB26_ID0  0xffc03758   /* CAN Controller 1 Mailbox 26 ID0 Register */
-#define                    CAN1_MB26_ID1  0xffc0375c   /* CAN Controller 1 Mailbox 26 ID1 Register */
-#define                  CAN1_MB27_DATA0  0xffc03760   /* CAN Controller 1 Mailbox 27 Data 0 Register */
-#define                  CAN1_MB27_DATA1  0xffc03764   /* CAN Controller 1 Mailbox 27 Data 1 Register */
-#define                  CAN1_MB27_DATA2  0xffc03768   /* CAN Controller 1 Mailbox 27 Data 2 Register */
-#define                  CAN1_MB27_DATA3  0xffc0376c   /* CAN Controller 1 Mailbox 27 Data 3 Register */
-#define                 CAN1_MB27_LENGTH  0xffc03770   /* CAN Controller 1 Mailbox 27 Length Register */
-#define              CAN1_MB27_TIMESTAMP  0xffc03774   /* CAN Controller 1 Mailbox 27 Timestamp Register */
-#define                    CAN1_MB27_ID0  0xffc03778   /* CAN Controller 1 Mailbox 27 ID0 Register */
-#define                    CAN1_MB27_ID1  0xffc0377c   /* CAN Controller 1 Mailbox 27 ID1 Register */
-#define                  CAN1_MB28_DATA0  0xffc03780   /* CAN Controller 1 Mailbox 28 Data 0 Register */
-#define                  CAN1_MB28_DATA1  0xffc03784   /* CAN Controller 1 Mailbox 28 Data 1 Register */
-#define                  CAN1_MB28_DATA2  0xffc03788   /* CAN Controller 1 Mailbox 28 Data 2 Register */
-#define                  CAN1_MB28_DATA3  0xffc0378c   /* CAN Controller 1 Mailbox 28 Data 3 Register */
-#define                 CAN1_MB28_LENGTH  0xffc03790   /* CAN Controller 1 Mailbox 28 Length Register */
-#define              CAN1_MB28_TIMESTAMP  0xffc03794   /* CAN Controller 1 Mailbox 28 Timestamp Register */
-#define                    CAN1_MB28_ID0  0xffc03798   /* CAN Controller 1 Mailbox 28 ID0 Register */
-#define                    CAN1_MB28_ID1  0xffc0379c   /* CAN Controller 1 Mailbox 28 ID1 Register */
-#define                  CAN1_MB29_DATA0  0xffc037a0   /* CAN Controller 1 Mailbox 29 Data 0 Register */
-#define                  CAN1_MB29_DATA1  0xffc037a4   /* CAN Controller 1 Mailbox 29 Data 1 Register */
-#define                  CAN1_MB29_DATA2  0xffc037a8   /* CAN Controller 1 Mailbox 29 Data 2 Register */
-#define                  CAN1_MB29_DATA3  0xffc037ac   /* CAN Controller 1 Mailbox 29 Data 3 Register */
-#define                 CAN1_MB29_LENGTH  0xffc037b0   /* CAN Controller 1 Mailbox 29 Length Register */
-#define              CAN1_MB29_TIMESTAMP  0xffc037b4   /* CAN Controller 1 Mailbox 29 Timestamp Register */
-#define                    CAN1_MB29_ID0  0xffc037b8   /* CAN Controller 1 Mailbox 29 ID0 Register */
-#define                    CAN1_MB29_ID1  0xffc037bc   /* CAN Controller 1 Mailbox 29 ID1 Register */
-#define                  CAN1_MB30_DATA0  0xffc037c0   /* CAN Controller 1 Mailbox 30 Data 0 Register */
-#define                  CAN1_MB30_DATA1  0xffc037c4   /* CAN Controller 1 Mailbox 30 Data 1 Register */
-#define                  CAN1_MB30_DATA2  0xffc037c8   /* CAN Controller 1 Mailbox 30 Data 2 Register */
-#define                  CAN1_MB30_DATA3  0xffc037cc   /* CAN Controller 1 Mailbox 30 Data 3 Register */
-#define                 CAN1_MB30_LENGTH  0xffc037d0   /* CAN Controller 1 Mailbox 30 Length Register */
-#define              CAN1_MB30_TIMESTAMP  0xffc037d4   /* CAN Controller 1 Mailbox 30 Timestamp Register */
-#define                    CAN1_MB30_ID0  0xffc037d8   /* CAN Controller 1 Mailbox 30 ID0 Register */
-#define                    CAN1_MB30_ID1  0xffc037dc   /* CAN Controller 1 Mailbox 30 ID1 Register */
-#define                  CAN1_MB31_DATA0  0xffc037e0   /* CAN Controller 1 Mailbox 31 Data 0 Register */
-#define                  CAN1_MB31_DATA1  0xffc037e4   /* CAN Controller 1 Mailbox 31 Data 1 Register */
-#define                  CAN1_MB31_DATA2  0xffc037e8   /* CAN Controller 1 Mailbox 31 Data 2 Register */
-#define                  CAN1_MB31_DATA3  0xffc037ec   /* CAN Controller 1 Mailbox 31 Data 3 Register */
-#define                 CAN1_MB31_LENGTH  0xffc037f0   /* CAN Controller 1 Mailbox 31 Length Register */
-#define              CAN1_MB31_TIMESTAMP  0xffc037f4   /* CAN Controller 1 Mailbox 31 Timestamp Register */
-#define                    CAN1_MB31_ID0  0xffc037f8   /* CAN Controller 1 Mailbox 31 ID0 Register */
-#define                    CAN1_MB31_ID1  0xffc037fc   /* CAN Controller 1 Mailbox 31 ID1 Register */
-
-/* ATAPI Registers */
-
-#define                    ATAPI_CONTROL  0xffc03800   /* ATAPI Control Register */
-#define                     ATAPI_STATUS  0xffc03804   /* ATAPI Status Register */
-#define                   ATAPI_DEV_ADDR  0xffc03808   /* ATAPI Device Register Address */
-#define                  ATAPI_DEV_TXBUF  0xffc0380c   /* ATAPI Device Register Write Data */
-#define                  ATAPI_DEV_RXBUF  0xffc03810   /* ATAPI Device Register Read Data */
-#define                   ATAPI_INT_MASK  0xffc03814   /* ATAPI Interrupt Mask Register */
-#define                 ATAPI_INT_STATUS  0xffc03818   /* ATAPI Interrupt Status Register */
-#define                   ATAPI_XFER_LEN  0xffc0381c   /* ATAPI Length of Transfer */
-#define                ATAPI_LINE_STATUS  0xffc03820   /* ATAPI Line Status */
-#define                   ATAPI_SM_STATE  0xffc03824   /* ATAPI State Machine Status */
-#define                  ATAPI_TERMINATE  0xffc03828   /* ATAPI Host Terminate */
-#define                 ATAPI_PIO_TFRCNT  0xffc0382c   /* ATAPI PIO mode transfer count */
-#define                 ATAPI_DMA_TFRCNT  0xffc03830   /* ATAPI DMA mode transfer count */
-#define               ATAPI_UMAIN_TFRCNT  0xffc03834   /* ATAPI UDMAIN transfer count */
-#define             ATAPI_UDMAOUT_TFRCNT  0xffc03838   /* ATAPI UDMAOUT transfer count */
-#define                  ATAPI_REG_TIM_0  0xffc03840   /* ATAPI Register Transfer Timing 0 */
-#define                  ATAPI_PIO_TIM_0  0xffc03844   /* ATAPI PIO Timing 0 Register */
-#define                  ATAPI_PIO_TIM_1  0xffc03848   /* ATAPI PIO Timing 1 Register */
-#define                ATAPI_MULTI_TIM_0  0xffc03850   /* ATAPI Multi-DMA Timing 0 Register */
-#define                ATAPI_MULTI_TIM_1  0xffc03854   /* ATAPI Multi-DMA Timing 1 Register */
-#define                ATAPI_MULTI_TIM_2  0xffc03858   /* ATAPI Multi-DMA Timing 2 Register */
-#define                ATAPI_ULTRA_TIM_0  0xffc03860   /* ATAPI Ultra-DMA Timing 0 Register */
-#define                ATAPI_ULTRA_TIM_1  0xffc03864   /* ATAPI Ultra-DMA Timing 1 Register */
-#define                ATAPI_ULTRA_TIM_2  0xffc03868   /* ATAPI Ultra-DMA Timing 2 Register */
-#define                ATAPI_ULTRA_TIM_3  0xffc0386c   /* ATAPI Ultra-DMA Timing 3 Register */
-
-/* SDH Registers */
-
-#define                      SDH_PWR_CTL  0xffc03900   /* SDH Power Control */
-#define                      SDH_CLK_CTL  0xffc03904   /* SDH Clock Control */
-#define                     SDH_ARGUMENT  0xffc03908   /* SDH Argument */
-#define                      SDH_COMMAND  0xffc0390c   /* SDH Command */
-#define                     SDH_RESP_CMD  0xffc03910   /* SDH Response Command */
-#define                    SDH_RESPONSE0  0xffc03914   /* SDH Response0 */
-#define                    SDH_RESPONSE1  0xffc03918   /* SDH Response1 */
-#define                    SDH_RESPONSE2  0xffc0391c   /* SDH Response2 */
-#define                    SDH_RESPONSE3  0xffc03920   /* SDH Response3 */
-#define                   SDH_DATA_TIMER  0xffc03924   /* SDH Data Timer */
-#define                    SDH_DATA_LGTH  0xffc03928   /* SDH Data Length */
-#define                     SDH_DATA_CTL  0xffc0392c   /* SDH Data Control */
-#define                     SDH_DATA_CNT  0xffc03930   /* SDH Data Counter */
-#define                       SDH_STATUS  0xffc03934   /* SDH Status */
-#define                   SDH_STATUS_CLR  0xffc03938   /* SDH Status Clear */
-#define                        SDH_MASK0  0xffc0393c   /* SDH Interrupt0 Mask */
-#define                        SDH_MASK1  0xffc03940   /* SDH Interrupt1 Mask */
-#define                     SDH_FIFO_CNT  0xffc03948   /* SDH FIFO Counter */
-#define                         SDH_FIFO  0xffc03980   /* SDH Data FIFO */
-#define                     SDH_E_STATUS  0xffc039c0   /* SDH Exception Status */
-#define                       SDH_E_MASK  0xffc039c4   /* SDH Exception Mask */
-#define                          SDH_CFG  0xffc039c8   /* SDH Configuration */
-#define                   SDH_RD_WAIT_EN  0xffc039cc   /* SDH Read Wait Enable */
-#define                         SDH_PID0  0xffc039d0   /* SDH Peripheral Identification0 */
-#define                         SDH_PID1  0xffc039d4   /* SDH Peripheral Identification1 */
-#define                         SDH_PID2  0xffc039d8   /* SDH Peripheral Identification2 */
-#define                         SDH_PID3  0xffc039dc   /* SDH Peripheral Identification3 */
-#define                         SDH_PID4  0xffc039e0   /* SDH Peripheral Identification4 */
-#define                         SDH_PID5  0xffc039e4   /* SDH Peripheral Identification5 */
-#define                         SDH_PID6  0xffc039e8   /* SDH Peripheral Identification6 */
-#define                         SDH_PID7  0xffc039ec   /* SDH Peripheral Identification7 */
-
-/* HOST Port Registers */
-
-#define                     HOST_CONTROL  0xffc03a00   /* HOST Control Register */
-#define                      HOST_STATUS  0xffc03a04   /* HOST Status Register */
-#define                     HOST_TIMEOUT  0xffc03a08   /* HOST Acknowledge Mode Timeout Register */
-
-/* USB Control Registers */
-
-#define                        USB_FADDR  0xffc03c00   /* Function address register */
-#define                        USB_POWER  0xffc03c04   /* Power management register */
-#define                       USB_INTRTX  0xffc03c08   /* Interrupt register for endpoint 0 and Tx endpoint 1 to 7 */
-#define                       USB_INTRRX  0xffc03c0c   /* Interrupt register for Rx endpoints 1 to 7 */
-#define                      USB_INTRTXE  0xffc03c10   /* Interrupt enable register for IntrTx */
-#define                      USB_INTRRXE  0xffc03c14   /* Interrupt enable register for IntrRx */
-#define                      USB_INTRUSB  0xffc03c18   /* Interrupt register for common USB interrupts */
-#define                     USB_INTRUSBE  0xffc03c1c   /* Interrupt enable register for IntrUSB */
-#define                        USB_FRAME  0xffc03c20   /* USB frame number */
-#define                        USB_INDEX  0xffc03c24   /* Index register for selecting the indexed endpoint registers */
-#define                     USB_TESTMODE  0xffc03c28   /* Enabled USB 20 test modes */
-#define                     USB_GLOBINTR  0xffc03c2c   /* Global Interrupt Mask register and Wakeup Exception Interrupt */
-#define                   USB_GLOBAL_CTL  0xffc03c30   /* Global Clock Control for the core */
-
-/* USB Packet Control Registers */
-
-#define                USB_TX_MAX_PACKET  0xffc03c40   /* Maximum packet size for Host Tx endpoint */
-#define                         USB_CSR0  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                        USB_TXCSR  0xffc03c44   /* Control Status register for endpoint 0 and Control Status register for Host Tx endpoint */
-#define                USB_RX_MAX_PACKET  0xffc03c48   /* Maximum packet size for Host Rx endpoint */
-#define                        USB_RXCSR  0xffc03c4c   /* Control Status register for Host Rx endpoint */
-#define                       USB_COUNT0  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                      USB_RXCOUNT  0xffc03c50   /* Number of bytes received in endpoint 0 FIFO and Number of bytes received in Host Tx endpoint */
-#define                       USB_TXTYPE  0xffc03c54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint */
-#define                    USB_NAKLIMIT0  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                   USB_TXINTERVAL  0xffc03c58   /* Sets the NAK response timeout on Endpoint 0 and on Bulk transfers for Host Tx endpoint */
-#define                       USB_RXTYPE  0xffc03c5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint */
-#define                   USB_RXINTERVAL  0xffc03c60   /* Sets the polling interval for Interrupt and Isochronous transfers or the NAK response timeout on Bulk transfers */
-#define                      USB_TXCOUNT  0xffc03c68   /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* USB Endpoint FIFO Registers */
-
-#define                     USB_EP0_FIFO  0xffc03c80   /* Endpoint 0 FIFO */
-#define                     USB_EP1_FIFO  0xffc03c88   /* Endpoint 1 FIFO */
-#define                     USB_EP2_FIFO  0xffc03c90   /* Endpoint 2 FIFO */
-#define                     USB_EP3_FIFO  0xffc03c98   /* Endpoint 3 FIFO */
-#define                     USB_EP4_FIFO  0xffc03ca0   /* Endpoint 4 FIFO */
-#define                     USB_EP5_FIFO  0xffc03ca8   /* Endpoint 5 FIFO */
-#define                     USB_EP6_FIFO  0xffc03cb0   /* Endpoint 6 FIFO */
-#define                     USB_EP7_FIFO  0xffc03cb8   /* Endpoint 7 FIFO */
-
-/* USB OTG Control Registers */
-
-#define                  USB_OTG_DEV_CTL  0xffc03d00   /* OTG Device Control Register */
-#define                 USB_OTG_VBUS_IRQ  0xffc03d04   /* OTG VBUS Control Interrupts */
-#define                USB_OTG_VBUS_MASK  0xffc03d08   /* VBUS Control Interrupt Enable */
-
-/* USB Phy Control Registers */
-
-#define                     USB_LINKINFO  0xffc03d48   /* Enables programming of some PHY-side delays */
-#define                        USB_VPLEN  0xffc03d4c   /* Determines duration of VBUS pulse for VBUS charging */
-#define                      USB_HS_EOF1  0xffc03d50   /* Time buffer for High-Speed transactions */
-#define                      USB_FS_EOF1  0xffc03d54   /* Time buffer for Full-Speed transactions */
-#define                      USB_LS_EOF1  0xffc03d58   /* Time buffer for Low-Speed transactions */
-
-/* (APHY_CNTRL is for ADI usage only) */
-
-#define                   USB_APHY_CNTRL  0xffc03de0   /* Register that increases visibility of Analog PHY */
-
-/* (APHY_CALIB is for ADI usage only) */
-
-#define                   USB_APHY_CALIB  0xffc03de4   /* Register used to set some calibration values */
-#define                  USB_APHY_CNTRL2  0xffc03de8   /* Register used to prevent re-enumeration once Moab goes into hibernate mode */
-
-/* (PHY_TEST is for ADI usage only) */
-
-#define                     USB_PHY_TEST  0xffc03dec   /* Used for reducing simulation time and simplifies FIFO testability */
-#define                  USB_PLLOSC_CTRL  0xffc03df0   /* Used to program different parameters for USB PLL and Oscillator */
-#define                   USB_SRP_CLKDIV  0xffc03df4   /* Used to program clock divide value for the clock fed to the SRP detection logic */
-
-/* USB Endpoint 0 Control Registers */
-
-#define                USB_EP_NI0_TXMAXP  0xffc03e00   /* Maximum packet size for Host Tx endpoint0 */
-#define                 USB_EP_NI0_TXCSR  0xffc03e04   /* Control Status register for endpoint 0 */
-#define                USB_EP_NI0_RXMAXP  0xffc03e08   /* Maximum packet size for Host Rx endpoint0 */
-#define                 USB_EP_NI0_RXCSR  0xffc03e0c   /* Control Status register for Host Rx endpoint0 */
-#define               USB_EP_NI0_RXCOUNT  0xffc03e10   /* Number of bytes received in endpoint 0 FIFO */
-#define                USB_EP_NI0_TXTYPE  0xffc03e14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint0 */
-#define            USB_EP_NI0_TXINTERVAL  0xffc03e18   /* Sets the NAK response timeout on Endpoint 0 */
-#define                USB_EP_NI0_RXTYPE  0xffc03e1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint0 */
-#define            USB_EP_NI0_RXINTERVAL  0xffc03e20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint0 */
-
-/* USB Endpoint 1 Control Registers */
-
-#define               USB_EP_NI0_TXCOUNT  0xffc03e28   /* Number of bytes to be written to the endpoint0 Tx FIFO */
-#define                USB_EP_NI1_TXMAXP  0xffc03e40   /* Maximum packet size for Host Tx endpoint1 */
-#define                 USB_EP_NI1_TXCSR  0xffc03e44   /* Control Status register for endpoint1 */
-#define                USB_EP_NI1_RXMAXP  0xffc03e48   /* Maximum packet size for Host Rx endpoint1 */
-#define                 USB_EP_NI1_RXCSR  0xffc03e4c   /* Control Status register for Host Rx endpoint1 */
-#define               USB_EP_NI1_RXCOUNT  0xffc03e50   /* Number of bytes received in endpoint1 FIFO */
-#define                USB_EP_NI1_TXTYPE  0xffc03e54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint1 */
-#define            USB_EP_NI1_TXINTERVAL  0xffc03e58   /* Sets the NAK response timeout on Endpoint1 */
-#define                USB_EP_NI1_RXTYPE  0xffc03e5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint1 */
-#define            USB_EP_NI1_RXINTERVAL  0xffc03e60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint1 */
-
-/* USB Endpoint 2 Control Registers */
-
-#define               USB_EP_NI1_TXCOUNT  0xffc03e68   /* Number of bytes to be written to the+H102 endpoint1 Tx FIFO */
-#define                USB_EP_NI2_TXMAXP  0xffc03e80   /* Maximum packet size for Host Tx endpoint2 */
-#define                 USB_EP_NI2_TXCSR  0xffc03e84   /* Control Status register for endpoint2 */
-#define                USB_EP_NI2_RXMAXP  0xffc03e88   /* Maximum packet size for Host Rx endpoint2 */
-#define                 USB_EP_NI2_RXCSR  0xffc03e8c   /* Control Status register for Host Rx endpoint2 */
-#define               USB_EP_NI2_RXCOUNT  0xffc03e90   /* Number of bytes received in endpoint2 FIFO */
-#define                USB_EP_NI2_TXTYPE  0xffc03e94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint2 */
-#define            USB_EP_NI2_TXINTERVAL  0xffc03e98   /* Sets the NAK response timeout on Endpoint2 */
-#define                USB_EP_NI2_RXTYPE  0xffc03e9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint2 */
-#define            USB_EP_NI2_RXINTERVAL  0xffc03ea0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint2 */
-
-/* USB Endpoint 3 Control Registers */
-
-#define               USB_EP_NI2_TXCOUNT  0xffc03ea8   /* Number of bytes to be written to the endpoint2 Tx FIFO */
-#define                USB_EP_NI3_TXMAXP  0xffc03ec0   /* Maximum packet size for Host Tx endpoint3 */
-#define                 USB_EP_NI3_TXCSR  0xffc03ec4   /* Control Status register for endpoint3 */
-#define                USB_EP_NI3_RXMAXP  0xffc03ec8   /* Maximum packet size for Host Rx endpoint3 */
-#define                 USB_EP_NI3_RXCSR  0xffc03ecc   /* Control Status register for Host Rx endpoint3 */
-#define               USB_EP_NI3_RXCOUNT  0xffc03ed0   /* Number of bytes received in endpoint3 FIFO */
-#define                USB_EP_NI3_TXTYPE  0xffc03ed4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint3 */
-#define            USB_EP_NI3_TXINTERVAL  0xffc03ed8   /* Sets the NAK response timeout on Endpoint3 */
-#define                USB_EP_NI3_RXTYPE  0xffc03edc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint3 */
-#define            USB_EP_NI3_RXINTERVAL  0xffc03ee0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint3 */
-
-/* USB Endpoint 4 Control Registers */
-
-#define               USB_EP_NI3_TXCOUNT  0xffc03ee8   /* Number of bytes to be written to the H124endpoint3 Tx FIFO */
-#define                USB_EP_NI4_TXMAXP  0xffc03f00   /* Maximum packet size for Host Tx endpoint4 */
-#define                 USB_EP_NI4_TXCSR  0xffc03f04   /* Control Status register for endpoint4 */
-#define                USB_EP_NI4_RXMAXP  0xffc03f08   /* Maximum packet size for Host Rx endpoint4 */
-#define                 USB_EP_NI4_RXCSR  0xffc03f0c   /* Control Status register for Host Rx endpoint4 */
-#define               USB_EP_NI4_RXCOUNT  0xffc03f10   /* Number of bytes received in endpoint4 FIFO */
-#define                USB_EP_NI4_TXTYPE  0xffc03f14   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint4 */
-#define            USB_EP_NI4_TXINTERVAL  0xffc03f18   /* Sets the NAK response timeout on Endpoint4 */
-#define                USB_EP_NI4_RXTYPE  0xffc03f1c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint4 */
-#define            USB_EP_NI4_RXINTERVAL  0xffc03f20   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint4 */
-
-/* USB Endpoint 5 Control Registers */
-
-#define               USB_EP_NI4_TXCOUNT  0xffc03f28   /* Number of bytes to be written to the endpoint4 Tx FIFO */
-#define                USB_EP_NI5_TXMAXP  0xffc03f40   /* Maximum packet size for Host Tx endpoint5 */
-#define                 USB_EP_NI5_TXCSR  0xffc03f44   /* Control Status register for endpoint5 */
-#define                USB_EP_NI5_RXMAXP  0xffc03f48   /* Maximum packet size for Host Rx endpoint5 */
-#define                 USB_EP_NI5_RXCSR  0xffc03f4c   /* Control Status register for Host Rx endpoint5 */
-#define               USB_EP_NI5_RXCOUNT  0xffc03f50   /* Number of bytes received in endpoint5 FIFO */
-#define                USB_EP_NI5_TXTYPE  0xffc03f54   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint5 */
-#define            USB_EP_NI5_TXINTERVAL  0xffc03f58   /* Sets the NAK response timeout on Endpoint5 */
-#define                USB_EP_NI5_RXTYPE  0xffc03f5c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint5 */
-#define            USB_EP_NI5_RXINTERVAL  0xffc03f60   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint5 */
-
-/* USB Endpoint 6 Control Registers */
-
-#define               USB_EP_NI5_TXCOUNT  0xffc03f68   /* Number of bytes to be written to the H145endpoint5 Tx FIFO */
-#define                USB_EP_NI6_TXMAXP  0xffc03f80   /* Maximum packet size for Host Tx endpoint6 */
-#define                 USB_EP_NI6_TXCSR  0xffc03f84   /* Control Status register for endpoint6 */
-#define                USB_EP_NI6_RXMAXP  0xffc03f88   /* Maximum packet size for Host Rx endpoint6 */
-#define                 USB_EP_NI6_RXCSR  0xffc03f8c   /* Control Status register for Host Rx endpoint6 */
-#define               USB_EP_NI6_RXCOUNT  0xffc03f90   /* Number of bytes received in endpoint6 FIFO */
-#define                USB_EP_NI6_TXTYPE  0xffc03f94   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint6 */
-#define            USB_EP_NI6_TXINTERVAL  0xffc03f98   /* Sets the NAK response timeout on Endpoint6 */
-#define                USB_EP_NI6_RXTYPE  0xffc03f9c   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint6 */
-#define            USB_EP_NI6_RXINTERVAL  0xffc03fa0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint6 */
-
-/* USB Endpoint 7 Control Registers */
-
-#define               USB_EP_NI6_TXCOUNT  0xffc03fa8   /* Number of bytes to be written to the endpoint6 Tx FIFO */
-#define                USB_EP_NI7_TXMAXP  0xffc03fc0   /* Maximum packet size for Host Tx endpoint7 */
-#define                 USB_EP_NI7_TXCSR  0xffc03fc4   /* Control Status register for endpoint7 */
-#define                USB_EP_NI7_RXMAXP  0xffc03fc8   /* Maximum packet size for Host Rx endpoint7 */
-#define                 USB_EP_NI7_RXCSR  0xffc03fcc   /* Control Status register for Host Rx endpoint7 */
-#define               USB_EP_NI7_RXCOUNT  0xffc03fd0   /* Number of bytes received in endpoint7 FIFO */
-#define                USB_EP_NI7_TXTYPE  0xffc03fd4   /* Sets the transaction protocol and peripheral endpoint number for the Host Tx endpoint7 */
-#define            USB_EP_NI7_TXINTERVAL  0xffc03fd8   /* Sets the NAK response timeout on Endpoint7 */
-#define                USB_EP_NI7_RXTYPE  0xffc03fdc   /* Sets the transaction protocol and peripheral endpoint number for the Host Rx endpoint7 */
-#define            USB_EP_NI7_RXINTERVAL  0xffc03ff0   /* Sets the polling interval for Interrupt/Isochronous transfers or the NAK response timeout on Bulk transfers for Host Rx endpoint7 */
-#define               USB_EP_NI7_TXCOUNT  0xffc03ff8   /* Number of bytes to be written to the endpoint7 Tx FIFO */
-#define                USB_DMA_INTERRUPT  0xffc04000   /* Indicates pending interrupts for the DMA channels */
-
-/* USB Channel 0 Config Registers */
-
-#define                  USB_DMA0CONTROL  0xffc04004   /* DMA master channel 0 configuration */
-#define                  USB_DMA0ADDRLOW  0xffc04008   /* Lower 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0ADDRHIGH  0xffc0400c   /* Upper 16-bits of memory source/destination address for DMA master channel 0 */
-#define                 USB_DMA0COUNTLOW  0xffc04010   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 0 */
-#define                USB_DMA0COUNTHIGH  0xffc04014   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 0 */
-
-/* USB Channel 1 Config Registers */
-
-#define                  USB_DMA1CONTROL  0xffc04024   /* DMA master channel 1 configuration */
-#define                  USB_DMA1ADDRLOW  0xffc04028   /* Lower 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1ADDRHIGH  0xffc0402c   /* Upper 16-bits of memory source/destination address for DMA master channel 1 */
-#define                 USB_DMA1COUNTLOW  0xffc04030   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 1 */
-#define                USB_DMA1COUNTHIGH  0xffc04034   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 1 */
-
-/* USB Channel 2 Config Registers */
-
-#define                  USB_DMA2CONTROL  0xffc04044   /* DMA master channel 2 configuration */
-#define                  USB_DMA2ADDRLOW  0xffc04048   /* Lower 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2ADDRHIGH  0xffc0404c   /* Upper 16-bits of memory source/destination address for DMA master channel 2 */
-#define                 USB_DMA2COUNTLOW  0xffc04050   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 2 */
-#define                USB_DMA2COUNTHIGH  0xffc04054   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 2 */
-
-/* USB Channel 3 Config Registers */
-
-#define                  USB_DMA3CONTROL  0xffc04064   /* DMA master channel 3 configuration */
-#define                  USB_DMA3ADDRLOW  0xffc04068   /* Lower 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3ADDRHIGH  0xffc0406c   /* Upper 16-bits of memory source/destination address for DMA master channel 3 */
-#define                 USB_DMA3COUNTLOW  0xffc04070   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 3 */
-#define                USB_DMA3COUNTHIGH  0xffc04074   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 3 */
-
-/* USB Channel 4 Config Registers */
-
-#define                  USB_DMA4CONTROL  0xffc04084   /* DMA master channel 4 configuration */
-#define                  USB_DMA4ADDRLOW  0xffc04088   /* Lower 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4ADDRHIGH  0xffc0408c   /* Upper 16-bits of memory source/destination address for DMA master channel 4 */
-#define                 USB_DMA4COUNTLOW  0xffc04090   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 4 */
-#define                USB_DMA4COUNTHIGH  0xffc04094   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 4 */
-
-/* USB Channel 5 Config Registers */
-
-#define                  USB_DMA5CONTROL  0xffc040a4   /* DMA master channel 5 configuration */
-#define                  USB_DMA5ADDRLOW  0xffc040a8   /* Lower 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5ADDRHIGH  0xffc040ac   /* Upper 16-bits of memory source/destination address for DMA master channel 5 */
-#define                 USB_DMA5COUNTLOW  0xffc040b0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 5 */
-#define                USB_DMA5COUNTHIGH  0xffc040b4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 5 */
-
-/* USB Channel 6 Config Registers */
-
-#define                  USB_DMA6CONTROL  0xffc040c4   /* DMA master channel 6 configuration */
-#define                  USB_DMA6ADDRLOW  0xffc040c8   /* Lower 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6ADDRHIGH  0xffc040cc   /* Upper 16-bits of memory source/destination address for DMA master channel 6 */
-#define                 USB_DMA6COUNTLOW  0xffc040d0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 6 */
-#define                USB_DMA6COUNTHIGH  0xffc040d4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 6 */
-
-/* USB Channel 7 Config Registers */
-
-#define                  USB_DMA7CONTROL  0xffc040e4   /* DMA master channel 7 configuration */
-#define                  USB_DMA7ADDRLOW  0xffc040e8   /* Lower 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7ADDRHIGH  0xffc040ec   /* Upper 16-bits of memory source/destination address for DMA master channel 7 */
-#define                 USB_DMA7COUNTLOW  0xffc040f0   /* Lower 16-bits of byte count of DMA transfer for DMA master channel 7 */
-#define                USB_DMA7COUNTHIGH  0xffc040f4   /* Upper 16-bits of byte count of DMA transfer for DMA master channel 7 */
-
-/* Keypad Registers */
-
-#define                         KPAD_CTL  0xffc04100   /* Controls keypad module enable and disable */
-#define                    KPAD_PRESCALE  0xffc04104   /* Establish a time base for programing the KPAD_MSEL register */
-#define                        KPAD_MSEL  0xffc04108   /* Selects delay parameters for keypad interface sensitivity */
-#define                      KPAD_ROWCOL  0xffc0410c   /* Captures the row and column output values of the keys pressed */
-#define                        KPAD_STAT  0xffc04110   /* Holds and clears the status of the keypad interface interrupt */
-#define                    KPAD_SOFTEVAL  0xffc04114   /* Lets software force keypad interface to check for keys being pressed */
-
-/* Pixel Compositor (PIXC) Registers */
-
-#define                         PIXC_CTL  0xffc04400   /* Overlay enable, resampling mode, I/O data format, transparency enable, watermark level, FIFO status */
-#define                         PIXC_PPL  0xffc04404   /* Holds the number of pixels per line of the display */
-#define                         PIXC_LPF  0xffc04408   /* Holds the number of lines per frame of the display */
-#define                     PIXC_AHSTART  0xffc0440c   /* Contains horizontal start pixel information of the overlay data (set A) */
-#define                       PIXC_AHEND  0xffc04410   /* Contains horizontal end pixel information of the overlay data (set A) */
-#define                     PIXC_AVSTART  0xffc04414   /* Contains vertical start pixel information of the overlay data (set A) */
-#define                       PIXC_AVEND  0xffc04418   /* Contains vertical end pixel information of the overlay data (set A) */
-#define                     PIXC_ATRANSP  0xffc0441c   /* Contains the transparency ratio (set A) */
-#define                     PIXC_BHSTART  0xffc04420   /* Contains horizontal start pixel information of the overlay data (set B) */
-#define                       PIXC_BHEND  0xffc04424   /* Contains horizontal end pixel information of the overlay data (set B) */
-#define                     PIXC_BVSTART  0xffc04428   /* Contains vertical start pixel information of the overlay data (set B) */
-#define                       PIXC_BVEND  0xffc0442c   /* Contains vertical end pixel information of the overlay data (set B) */
-#define                     PIXC_BTRANSP  0xffc04430   /* Contains the transparency ratio (set B) */
-#define                    PIXC_INTRSTAT  0xffc0443c   /* Overlay interrupt configuration/status */
-#define                       PIXC_RYCON  0xffc04440   /* Color space conversion matrix register. Contains the R/Y conversion coefficients */
-#define                       PIXC_GUCON  0xffc04444   /* Color space conversion matrix register. Contains the G/U conversion coefficients */
-#define                       PIXC_BVCON  0xffc04448   /* Color space conversion matrix register. Contains the B/V conversion coefficients */
-#define                      PIXC_CCBIAS  0xffc0444c   /* Bias values for the color space conversion matrix */
-#define                          PIXC_TC  0xffc04450   /* Holds the transparent color value */
-
-/* Handshake MDMA 0 Registers */
-
-#define                   HMDMA0_CONTROL  0xffc04500   /* Handshake MDMA0 Control Register */
-#define                    HMDMA0_ECINIT  0xffc04504   /* Handshake MDMA0 Initial Edge Count Register */
-#define                    HMDMA0_BCINIT  0xffc04508   /* Handshake MDMA0 Initial Block Count Register */
-#define                  HMDMA0_ECURGENT  0xffc0450c   /* Handshake MDMA0 Urgent Edge Count Threshold Register */
-#define                HMDMA0_ECOVERFLOW  0xffc04510   /* Handshake MDMA0 Edge Count Overflow Interrupt Register */
-#define                    HMDMA0_ECOUNT  0xffc04514   /* Handshake MDMA0 Current Edge Count Register */
-#define                    HMDMA0_BCOUNT  0xffc04518   /* Handshake MDMA0 Current Block Count Register */
-
-/* Handshake MDMA 1 Registers */
-
-#define                   HMDMA1_CONTROL  0xffc04540   /* Handshake MDMA1 Control Register */
-#define                    HMDMA1_ECINIT  0xffc04544   /* Handshake MDMA1 Initial Edge Count Register */
-#define                    HMDMA1_BCINIT  0xffc04548   /* Handshake MDMA1 Initial Block Count Register */
-#define                  HMDMA1_ECURGENT  0xffc0454c   /* Handshake MDMA1 Urgent Edge Count Threshold Register */
-#define                HMDMA1_ECOVERFLOW  0xffc04550   /* Handshake MDMA1 Edge Count Overflow Interrupt Register */
-#define                    HMDMA1_ECOUNT  0xffc04554   /* Handshake MDMA1 Current Edge Count Register */
-#define                    HMDMA1_BCOUNT  0xffc04558   /* Handshake MDMA1 Current Block Count Register */
-
-
-/* ********************************************************** */
-/*     SINGLE BIT MACRO PAIRS (bit mask and negated one)      */
-/*     and MULTI BIT READ MACROS                              */
-/* ********************************************************** */
-
-/* Bit masks for PIXC_CTL */
-
-#define                   PIXC_EN  0x1        /* Pixel Compositor Enable */
-#define                  OVR_A_EN  0x2        /* Overlay A Enable */
-#define                  OVR_B_EN  0x4        /* Overlay B Enable */
-#define                  IMG_FORM  0x8        /* Image Data Format */
-#define                  OVR_FORM  0x10       /* Overlay Data Format */
-#define                  OUT_FORM  0x20       /* Output Data Format */
-#define                   UDS_MOD  0x40       /* Resampling Mode */
-#define                     TC_EN  0x80       /* Transparent Color Enable */
-#define                  IMG_STAT  0x300      /* Image FIFO Status */
-#define                  OVR_STAT  0xc00      /* Overlay FIFO Status */
-#define                    WM_LVL  0x3000     /* FIFO Watermark Level */
-
-/* Bit masks for PIXC_AHSTART */
-
-#define                  A_HSTART  0xfff      /* Horizontal Start Coordinates */
-
-/* Bit masks for PIXC_AHEND */
-
-#define                    A_HEND  0xfff      /* Horizontal End Coordinates */
-
-/* Bit masks for PIXC_AVSTART */
-
-#define                  A_VSTART  0x3ff      /* Vertical Start Coordinates */
-
-/* Bit masks for PIXC_AVEND */
-
-#define                    A_VEND  0x3ff      /* Vertical End Coordinates */
-
-/* Bit masks for PIXC_ATRANSP */
-
-#define                  A_TRANSP  0xf        /* Transparency Value */
-
-/* Bit masks for PIXC_BHSTART */
-
-#define                  B_HSTART  0xfff      /* Horizontal Start Coordinates */
-
-/* Bit masks for PIXC_BHEND */
-
-#define                    B_HEND  0xfff      /* Horizontal End Coordinates */
-
-/* Bit masks for PIXC_BVSTART */
-
-#define                  B_VSTART  0x3ff      /* Vertical Start Coordinates */
-
-/* Bit masks for PIXC_BVEND */
-
-#define                    B_VEND  0x3ff      /* Vertical End Coordinates */
-
-/* Bit masks for PIXC_BTRANSP */
-
-#define                  B_TRANSP  0xf        /* Transparency Value */
-
-/* Bit masks for PIXC_INTRSTAT */
-
-#define                OVR_INT_EN  0x1        /* Interrupt at End of Last Valid Overlay */
-#define                FRM_INT_EN  0x2        /* Interrupt at End of Frame */
-#define              OVR_INT_STAT  0x4        /* Overlay Interrupt Status */
-#define              FRM_INT_STAT  0x8        /* Frame Interrupt Status */
-
-/* Bit masks for PIXC_RYCON */
-
-#define                       A11  0x3ff      /* A11 in the Coefficient Matrix */
-#define                       A12  0xffc00    /* A12 in the Coefficient Matrix */
-#define                       A13  0x3ff00000 /* A13 in the Coefficient Matrix */
-#define                  RY_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_GUCON */
-
-#define                       A21  0x3ff      /* A21 in the Coefficient Matrix */
-#define                       A22  0xffc00    /* A22 in the Coefficient Matrix */
-#define                       A23  0x3ff00000 /* A23 in the Coefficient Matrix */
-#define                  GU_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_BVCON */
-
-#define                       A31  0x3ff      /* A31 in the Coefficient Matrix */
-#define                       A32  0xffc00    /* A32 in the Coefficient Matrix */
-#define                       A33  0x3ff00000 /* A33 in the Coefficient Matrix */
-#define                  BV_MULT4  0x40000000 /* Multiply Row by 4 */
-
-/* Bit masks for PIXC_CCBIAS */
-
-#define                       A14  0x3ff      /* A14 in the Bias Vector */
-#define                       A24  0xffc00    /* A24 in the Bias Vector */
-#define                       A34  0x3ff00000 /* A34 in the Bias Vector */
-
-/* Bit masks for PIXC_TC */
-
-#define                  RY_TRANS  0xff       /* Transparent Color - R/Y Component */
-#define                  GU_TRANS  0xff00     /* Transparent Color - G/U Component */
-#define                  BV_TRANS  0xff0000   /* Transparent Color - B/V Component */
-
-/* Bit masks for HOST_CONTROL */
-
-#define                   HOST_EN  0x1        /* Host Enable */
-#define                  HOST_END  0x2        /* Host Endianess */
-#define                 DATA_SIZE  0x4        /* Data Size */
-#define                  HOST_RST  0x8        /* Host Reset */
-#define                  HRDY_OVR  0x20       /* Host Ready Override */
-#define                  INT_MODE  0x40       /* Interrupt Mode */
-#define                     BT_EN  0x80       /* Bus Timeout Enable */
-#define                       EHW  0x100      /* Enable Host Write */
-#define                       EHR  0x200      /* Enable Host Read */
-#define                       BDR  0x400      /* Burst DMA Requests */
-
-/* Bit masks for HOST_STATUS */
-
-#define                 DMA_READY  0x1        /* DMA Ready */
-#define                  FIFOFULL  0x2        /* FIFO Full */
-#define                 FIFOEMPTY  0x4        /* FIFO Empty */
-#define              DMA_COMPLETE  0x8        /* DMA Complete */
-#define                      HSHK  0x10       /* Host Handshake */
-#define                   TIMEOUT  0x20       /* Host Timeout */
-#define                      HIRQ  0x40       /* Host Interrupt Request */
-#define                ALLOW_CNFG  0x80       /* Allow New Configuration */
-#define                   DMA_DIR  0x100      /* DMA Direction */
-#define                       BTE  0x200      /* Bus Timeout Enabled */
-
-/* Bit masks for HOST_TIMEOUT */
-
-#define             COUNT_TIMEOUT  0x7ff      /* Host Timeout count */
-
-/* Bit masks for MXVR_CONFIG */
-
-#define                    MXVREN  0x1        /* MXVR Enable */
-#define                      MMSM  0x2        /* MXVR Master/Slave Mode Select */
-#define                    ACTIVE  0x4        /* Active Mode */
-#define                    SDELAY  0x8        /* Synchronous Data Delay */
-#define                   NCMRXEN  0x10       /* Normal Control Message Receive Enable */
-#define                   RWRRXEN  0x20       /* Remote Write Receive Enable */
-#define                     MTXEN  0x40       /* MXVR Transmit Data Enable */
-#define                    MTXONB  0x80       /* MXVR Phy Transmitter On */
-#define                   EPARITY  0x100      /* Even Parity Select */
-#define                       MSB  0x1e00     /* Master Synchronous Boundary */
-#define                    APRXEN  0x2000     /* Asynchronous Packet Receive Enable */
-#define                    WAKEUP  0x4000     /* Wake-Up */
-#define                     LMECH  0x8000     /* Lock Mechanism Select */
-
-/* Bit masks for MXVR_STATE_0 */
-
-#define                      NACT  0x1        /* Network Activity */
-#define                    SBLOCK  0x2        /* Super Block Lock */
-#define                   FMPLLST  0xc        /* Frequency Multiply PLL SM State */
-#define                  CDRPLLST  0xe0       /* Clock/Data Recovery PLL SM State */
-#define                     APBSY  0x100      /* Asynchronous Packet Transmit Buffer Busy */
-#define                     APARB  0x200      /* Asynchronous Packet Arbitrating */
-#define                      APTX  0x400      /* Asynchronous Packet Transmitting */
-#define                      APRX  0x800      /* Receiving Asynchronous Packet */
-#define                     CMBSY  0x1000     /* Control Message Transmit Buffer Busy */
-#define                     CMARB  0x2000     /* Control Message Arbitrating */
-#define                      CMTX  0x4000     /* Control Message Transmitting */
-#define                      CMRX  0x8000     /* Receiving Control Message */
-#define                    MRXONB  0x10000    /* MRXONB Pin State */
-#define                     RGSIP  0x20000    /* Remote Get Source In Progress */
-#define                     DALIP  0x40000    /* Resource Deallocate In Progress */
-#define                      ALIP  0x80000    /* Resource Allocate In Progress */
-#define                     RRDIP  0x100000   /* Remote Read In Progress */
-#define                     RWRIP  0x200000   /* Remote Write In Progress */
-#define                     FLOCK  0x400000   /* Frame Lock */
-#define                     BLOCK  0x800000   /* Block Lock */
-#define                       RSB  0xf000000  /* Received Synchronous Boundary */
-#define                   DERRNUM  0xf0000000 /* DMA Error Channel Number */
-
-/* Bit masks for MXVR_STATE_1 */
-
-#define                   SRXNUMB  0xf        /* Synchronous Receive FIFO Number of Bytes */
-#define                   STXNUMB  0xf0       /* Synchronous Transmit FIFO Number of Bytes */
-#define                    APCONT  0x100      /* Asynchronous Packet Continuation */
-#define                  OBERRNUM  0xe00      /* DMA Out of Bounds Error Channel Number */
-#define                DMAACTIVE0  0x10000    /* DMA0 Active */
-#define                DMAACTIVE1  0x20000    /* DMA1 Active */
-#define                DMAACTIVE2  0x40000    /* DMA2 Active */
-#define                DMAACTIVE3  0x80000    /* DMA3 Active */
-#define                DMAACTIVE4  0x100000   /* DMA4 Active */
-#define                DMAACTIVE5  0x200000   /* DMA5 Active */
-#define                DMAACTIVE6  0x400000   /* DMA6 Active */
-#define                DMAACTIVE7  0x800000   /* DMA7 Active */
-#define                  DMAPMEN0  0x1000000  /* DMA0 Pattern Matching Enabled */
-#define                  DMAPMEN1  0x2000000  /* DMA1 Pattern Matching Enabled */
-#define                  DMAPMEN2  0x4000000  /* DMA2 Pattern Matching Enabled */
-#define                  DMAPMEN3  0x8000000  /* DMA3 Pattern Matching Enabled */
-#define                  DMAPMEN4  0x10000000 /* DMA4 Pattern Matching Enabled */
-#define                  DMAPMEN5  0x20000000 /* DMA5 Pattern Matching Enabled */
-#define                  DMAPMEN6  0x40000000 /* DMA6 Pattern Matching Enabled */
-#define                  DMAPMEN7  0x80000000 /* DMA7 Pattern Matching Enabled */
-
-/* Bit masks for MXVR_INT_STAT_0 */
-
-#define                      NI2A  0x1        /* Network Inactive to Active */
-#define                      NA2I  0x2        /* Network Active to Inactive */
-#define                     SBU2L  0x4        /* Super Block Unlock to Lock */
-#define                     SBL2U  0x8        /* Super Block Lock to Unlock */
-#define                       PRU  0x10       /* Position Register Updated */
-#define                      MPRU  0x20       /* Maximum Position Register Updated */
-#define                       DRU  0x40       /* Delay Register Updated */
-#define                      MDRU  0x80       /* Maximum Delay Register Updated */
-#define                       SBU  0x100      /* Synchronous Boundary Updated */
-#define                       ATU  0x200      /* Allocation Table Updated */
-#define                      FCZ0  0x400      /* Frame Counter 0 Zero */
-#define                      FCZ1  0x800      /* Frame Counter 1 Zero */
-#define                      PERR  0x1000     /* Parity Error */
-#define                      MH2L  0x2000     /* MRXONB High to Low */
-#define                      ML2H  0x4000     /* MRXONB Low to High */
-#define                       WUP  0x8000     /* Wake-Up Preamble Received */
-#define                      FU2L  0x10000    /* Frame Unlock to Lock */
-#define                      FL2U  0x20000    /* Frame Lock to Unlock */
-#define                      BU2L  0x40000    /* Block Unlock to Lock */
-#define                      BL2U  0x80000    /* Block Lock to Unlock */
-#define                     OBERR  0x100000   /* DMA Out of Bounds Error */
-#define                       PFL  0x200000   /* PLL Frequency Locked */
-#define                       SCZ  0x400000   /* System Clock Counter Zero */
-#define                      FERR  0x800000   /* FIFO Error */
-#define                       CMR  0x1000000  /* Control Message Received */
-#define                     CMROF  0x2000000  /* Control Message Receive Buffer Overflow */
-#define                      CMTS  0x4000000  /* Control Message Transmit Buffer Successfully Sent */
-#define                      CMTC  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled */
-#define                      RWRC  0x10000000 /* Remote Write Control Message Completed */
-#define                       BCZ  0x20000000 /* Block Counter Zero */
-#define                     BMERR  0x40000000 /* Biphase Mark Coding Error */
-#define                      DERR  0x80000000 /* DMA Error */
-
-/* Bit masks for MXVR_INT_STAT_1 */
-
-#define                    HDONE0  0x1        /* DMA0 Half Done */
-#define                     DONE0  0x2        /* DMA0 Done */
-#define                       APR  0x4        /* Asynchronous Packet Received */
-#define                     APROF  0x8        /* Asynchronous Packet Receive Buffer Overflow */
-#define                    HDONE1  0x10       /* DMA1 Half Done */
-#define                     DONE1  0x20       /* DMA1 Done */
-#define                      APTS  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent */
-#define                      APTC  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled */
-#define                    HDONE2  0x100      /* DMA2 Half Done */
-#define                     DONE2  0x200      /* DMA2 Done */
-#define                     APRCE  0x400      /* Asynchronous Packet Receive CRC Error */
-#define                     APRPE  0x800      /* Asynchronous Packet Receive Packet Error */
-#define                    HDONE3  0x1000     /* DMA3 Half Done */
-#define                     DONE3  0x2000     /* DMA3 Done */
-#define                    HDONE4  0x10000    /* DMA4 Half Done */
-#define                     DONE4  0x20000    /* DMA4 Done */
-#define                    HDONE5  0x100000   /* DMA5 Half Done */
-#define                     DONE5  0x200000   /* DMA5 Done */
-#define                    HDONE6  0x1000000  /* DMA6 Half Done */
-#define                     DONE6  0x2000000  /* DMA6 Done */
-#define                    HDONE7  0x10000000 /* DMA7 Half Done */
-#define                     DONE7  0x20000000 /* DMA7 Done */
-
-/* Bit masks for MXVR_INT_EN_0 */
-
-#define                    NI2AEN  0x1        /* Network Inactive to Active Interrupt Enable */
-#define                    NA2IEN  0x2        /* Network Active to Inactive Interrupt Enable */
-#define                   SBU2LEN  0x4        /* Super Block Unlock to Lock Interrupt Enable */
-#define                   SBL2UEN  0x8        /* Super Block Lock to Unlock Interrupt Enable */
-#define                     PRUEN  0x10       /* Position Register Updated Interrupt Enable */
-#define                    MPRUEN  0x20       /* Maximum Position Register Updated Interrupt Enable */
-#define                     DRUEN  0x40       /* Delay Register Updated Interrupt Enable */
-#define                    MDRUEN  0x80       /* Maximum Delay Register Updated Interrupt Enable */
-#define                     SBUEN  0x100      /* Synchronous Boundary Updated Interrupt Enable */
-#define                     ATUEN  0x200      /* Allocation Table Updated Interrupt Enable */
-#define                    FCZ0EN  0x400      /* Frame Counter 0 Zero Interrupt Enable */
-#define                    FCZ1EN  0x800      /* Frame Counter 1 Zero Interrupt Enable */
-#define                    PERREN  0x1000     /* Parity Error Interrupt Enable */
-#define                    MH2LEN  0x2000     /* MRXONB High to Low Interrupt Enable */
-#define                    ML2HEN  0x4000     /* MRXONB Low to High Interrupt Enable */
-#define                     WUPEN  0x8000     /* Wake-Up Preamble Received Interrupt Enable */
-#define                    FU2LEN  0x10000    /* Frame Unlock to Lock Interrupt Enable */
-#define                    FL2UEN  0x20000    /* Frame Lock to Unlock Interrupt Enable */
-#define                    BU2LEN  0x40000    /* Block Unlock to Lock Interrupt Enable */
-#define                    BL2UEN  0x80000    /* Block Lock to Unlock Interrupt Enable */
-#define                   OBERREN  0x100000   /* DMA Out of Bounds Error Interrupt Enable */
-#define                     PFLEN  0x200000   /* PLL Frequency Locked Interrupt Enable */
-#define                     SCZEN  0x400000   /* System Clock Counter Zero Interrupt Enable */
-#define                    FERREN  0x800000   /* FIFO Error Interrupt Enable */
-#define                     CMREN  0x1000000  /* Control Message Received Interrupt Enable */
-#define                   CMROFEN  0x2000000  /* Control Message Receive Buffer Overflow Interrupt Enable */
-#define                    CMTSEN  0x4000000  /* Control Message Transmit Buffer Successfully Sent Interrupt Enable */
-#define                    CMTCEN  0x8000000  /* Control Message Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define                    RWRCEN  0x10000000 /* Remote Write Control Message Completed Interrupt Enable */
-#define                     BCZEN  0x20000000 /* Block Counter Zero Interrupt Enable */
-#define                   BMERREN  0x40000000 /* Biphase Mark Coding Error Interrupt Enable */
-#define                    DERREN  0x80000000 /* DMA Error Interrupt Enable */
-
-/* Bit masks for MXVR_INT_EN_1 */
-
-#define                  HDONEEN0  0x1        /* DMA0 Half Done Interrupt Enable */
-#define                   DONEEN0  0x2        /* DMA0 Done Interrupt Enable */
-#define                     APREN  0x4        /* Asynchronous Packet Received Interrupt Enable */
-#define                   APROFEN  0x8        /* Asynchronous Packet Receive Buffer Overflow Interrupt Enable */
-#define                  HDONEEN1  0x10       /* DMA1 Half Done Interrupt Enable */
-#define                   DONEEN1  0x20       /* DMA1 Done Interrupt Enable */
-#define                    APTSEN  0x40       /* Asynchronous Packet Transmit Buffer Successfully Sent Interrupt Enable */
-#define                    APTCEN  0x80       /* Asynchronous Packet Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define                  HDONEEN2  0x100      /* DMA2 Half Done Interrupt Enable */
-#define                   DONEEN2  0x200      /* DMA2 Done Interrupt Enable */
-#define                   APRCEEN  0x400      /* Asynchronous Packet Receive CRC Error Interrupt Enable */
-#define                   APRPEEN  0x800      /* Asynchronous Packet Receive Packet Error Interrupt Enable */
-#define                  HDONEEN3  0x1000     /* DMA3 Half Done Interrupt Enable */
-#define                   DONEEN3  0x2000     /* DMA3 Done Interrupt Enable */
-#define                  HDONEEN4  0x10000    /* DMA4 Half Done Interrupt Enable */
-#define                   DONEEN4  0x20000    /* DMA4 Done Interrupt Enable */
-#define                  HDONEEN5  0x100000   /* DMA5 Half Done Interrupt Enable */
-#define                   DONEEN5  0x200000   /* DMA5 Done Interrupt Enable */
-#define                  HDONEEN6  0x1000000  /* DMA6 Half Done Interrupt Enable */
-#define                   DONEEN6  0x2000000  /* DMA6 Done Interrupt Enable */
-#define                  HDONEEN7  0x10000000 /* DMA7 Half Done Interrupt Enable */
-#define                   DONEEN7  0x20000000 /* DMA7 Done Interrupt Enable */
-
-/* Bit masks for MXVR_POSITION */
-
-#define                  POSITION  0x3f       /* Node Position */
-#define                    PVALID  0x8000     /* Node Position Valid */
-
-/* Bit masks for MXVR_MAX_POSITION */
-
-#define                 MPOSITION  0x3f       /* Maximum Node Position */
-#define                   MPVALID  0x8000     /* Maximum Node Position Valid */
-
-/* Bit masks for MXVR_DELAY */
-
-#define                     DELAY  0x3f       /* Node Frame Delay */
-#define                    DVALID  0x8000     /* Node Frame Delay Valid */
-
-/* Bit masks for MXVR_MAX_DELAY */
-
-#define                    MDELAY  0x3f       /* Maximum Node Frame Delay */
-#define                   MDVALID  0x8000     /* Maximum Node Frame Delay Valid */
-
-/* Bit masks for MXVR_LADDR */
-
-#define                     LADDR  0xffff     /* Logical Address */
-#define                    LVALID  0x80000000 /* Logical Address Valid */
-
-/* Bit masks for MXVR_GADDR */
-
-#define                    GADDRL  0xff       /* Group Address Lower Byte */
-#define                    GVALID  0x8000     /* Group Address Valid */
-
-/* Bit masks for MXVR_AADDR */
-
-#define                     AADDR  0xffff     /* Alternate Address */
-#define                    AVALID  0x80000000 /* Alternate Address Valid */
-
-/* Bit masks for MXVR_ALLOC_0 */
-
-#define                       CL0  0x7f       /* Channel 0 Connection Label */
-#define                      CIU0  0x80       /* Channel 0 In Use */
-#define                       CL1  0x7f00     /* Channel 0 Connection Label */
-#define                      CIU1  0x8000     /* Channel 0 In Use */
-#define                       CL2  0x7f0000   /* Channel 0 Connection Label */
-#define                      CIU2  0x800000   /* Channel 0 In Use */
-#define                       CL3  0x7f000000 /* Channel 0 Connection Label */
-#define                      CIU3  0x80000000 /* Channel 0 In Use */
-
-/* Bit masks for MXVR_ALLOC_1 */
-
-#define                       CL4  0x7f       /* Channel 4 Connection Label */
-#define                      CIU4  0x80       /* Channel 4 In Use */
-#define                       CL5  0x7f00     /* Channel 5 Connection Label */
-#define                      CIU5  0x8000     /* Channel 5 In Use */
-#define                       CL6  0x7f0000   /* Channel 6 Connection Label */
-#define                      CIU6  0x800000   /* Channel 6 In Use */
-#define                       CL7  0x7f000000 /* Channel 7 Connection Label */
-#define                      CIU7  0x80000000 /* Channel 7 In Use */
-
-/* Bit masks for MXVR_ALLOC_2 */
-
-#define                       CL8  0x7f       /* Channel 8 Connection Label */
-#define                      CIU8  0x80       /* Channel 8 In Use */
-#define                       CL9  0x7f00     /* Channel 9 Connection Label */
-#define                      CIU9  0x8000     /* Channel 9 In Use */
-#define                      CL10  0x7f0000   /* Channel 10 Connection Label */
-#define                     CIU10  0x800000   /* Channel 10 In Use */
-#define                      CL11  0x7f000000 /* Channel 11 Connection Label */
-#define                     CIU11  0x80000000 /* Channel 11 In Use */
-
-/* Bit masks for MXVR_ALLOC_3 */
-
-#define                      CL12  0x7f       /* Channel 12 Connection Label */
-#define                     CIU12  0x80       /* Channel 12 In Use */
-#define                      CL13  0x7f00     /* Channel 13 Connection Label */
-#define                     CIU13  0x8000     /* Channel 13 In Use */
-#define                      CL14  0x7f0000   /* Channel 14 Connection Label */
-#define                     CIU14  0x800000   /* Channel 14 In Use */
-#define                      CL15  0x7f000000 /* Channel 15 Connection Label */
-#define                     CIU15  0x80000000 /* Channel 15 In Use */
-
-/* Bit masks for MXVR_ALLOC_4 */
-
-#define                      CL16  0x7f       /* Channel 16 Connection Label */
-#define                     CIU16  0x80       /* Channel 16 In Use */
-#define                      CL17  0x7f00     /* Channel 17 Connection Label */
-#define                     CIU17  0x8000     /* Channel 17 In Use */
-#define                      CL18  0x7f0000   /* Channel 18 Connection Label */
-#define                     CIU18  0x800000   /* Channel 18 In Use */
-#define                      CL19  0x7f000000 /* Channel 19 Connection Label */
-#define                     CIU19  0x80000000 /* Channel 19 In Use */
-
-/* Bit masks for MXVR_ALLOC_5 */
-
-#define                      CL20  0x7f       /* Channel 20 Connection Label */
-#define                     CIU20  0x80       /* Channel 20 In Use */
-#define                      CL21  0x7f00     /* Channel 21 Connection Label */
-#define                     CIU21  0x8000     /* Channel 21 In Use */
-#define                      CL22  0x7f0000   /* Channel 22 Connection Label */
-#define                     CIU22  0x800000   /* Channel 22 In Use */
-#define                      CL23  0x7f000000 /* Channel 23 Connection Label */
-#define                     CIU23  0x80000000 /* Channel 23 In Use */
-
-/* Bit masks for MXVR_ALLOC_6 */
-
-#define                      CL24  0x7f       /* Channel 24 Connection Label */
-#define                     CIU24  0x80       /* Channel 24 In Use */
-#define                      CL25  0x7f00     /* Channel 25 Connection Label */
-#define                     CIU25  0x8000     /* Channel 25 In Use */
-#define                      CL26  0x7f0000   /* Channel 26 Connection Label */
-#define                     CIU26  0x800000   /* Channel 26 In Use */
-#define                      CL27  0x7f000000 /* Channel 27 Connection Label */
-#define                     CIU27  0x80000000 /* Channel 27 In Use */
-
-/* Bit masks for MXVR_ALLOC_7 */
-
-#define                      CL28  0x7f       /* Channel 28 Connection Label */
-#define                     CIU28  0x80       /* Channel 28 In Use */
-#define                      CL29  0x7f00     /* Channel 29 Connection Label */
-#define                     CIU29  0x8000     /* Channel 29 In Use */
-#define                      CL30  0x7f0000   /* Channel 30 Connection Label */
-#define                     CIU30  0x800000   /* Channel 30 In Use */
-#define                      CL31  0x7f000000 /* Channel 31 Connection Label */
-#define                     CIU31  0x80000000 /* Channel 31 In Use */
-
-/* Bit masks for MXVR_ALLOC_8 */
-
-#define                      CL32  0x7f       /* Channel 32 Connection Label */
-#define                     CIU32  0x80       /* Channel 32 In Use */
-#define                      CL33  0x7f00     /* Channel 33 Connection Label */
-#define                     CIU33  0x8000     /* Channel 33 In Use */
-#define                      CL34  0x7f0000   /* Channel 34 Connection Label */
-#define                     CIU34  0x800000   /* Channel 34 In Use */
-#define                      CL35  0x7f000000 /* Channel 35 Connection Label */
-#define                     CIU35  0x80000000 /* Channel 35 In Use */
-
-/* Bit masks for MXVR_ALLOC_9 */
-
-#define                      CL36  0x7f       /* Channel 36 Connection Label */
-#define                     CIU36  0x80       /* Channel 36 In Use */
-#define                      CL37  0x7f00     /* Channel 37 Connection Label */
-#define                     CIU37  0x8000     /* Channel 37 In Use */
-#define                      CL38  0x7f0000   /* Channel 38 Connection Label */
-#define                     CIU38  0x800000   /* Channel 38 In Use */
-#define                      CL39  0x7f000000 /* Channel 39 Connection Label */
-#define                     CIU39  0x80000000 /* Channel 39 In Use */
-
-/* Bit masks for MXVR_ALLOC_10 */
-
-#define                      CL40  0x7f       /* Channel 40 Connection Label */
-#define                     CIU40  0x80       /* Channel 40 In Use */
-#define                      CL41  0x7f00     /* Channel 41 Connection Label */
-#define                     CIU41  0x8000     /* Channel 41 In Use */
-#define                      CL42  0x7f0000   /* Channel 42 Connection Label */
-#define                     CIU42  0x800000   /* Channel 42 In Use */
-#define                      CL43  0x7f000000 /* Channel 43 Connection Label */
-#define                     CIU43  0x80000000 /* Channel 43 In Use */
-
-/* Bit masks for MXVR_ALLOC_11 */
-
-#define                      CL44  0x7f       /* Channel 44 Connection Label */
-#define                     CIU44  0x80       /* Channel 44 In Use */
-#define                      CL45  0x7f00     /* Channel 45 Connection Label */
-#define                     CIU45  0x8000     /* Channel 45 In Use */
-#define                      CL46  0x7f0000   /* Channel 46 Connection Label */
-#define                     CIU46  0x800000   /* Channel 46 In Use */
-#define                      CL47  0x7f000000 /* Channel 47 Connection Label */
-#define                     CIU47  0x80000000 /* Channel 47 In Use */
-
-/* Bit masks for MXVR_ALLOC_12 */
-
-#define                      CL48  0x7f       /* Channel 48 Connection Label */
-#define                     CIU48  0x80       /* Channel 48 In Use */
-#define                      CL49  0x7f00     /* Channel 49 Connection Label */
-#define                     CIU49  0x8000     /* Channel 49 In Use */
-#define                      CL50  0x7f0000   /* Channel 50 Connection Label */
-#define                     CIU50  0x800000   /* Channel 50 In Use */
-#define                      CL51  0x7f000000 /* Channel 51 Connection Label */
-#define                     CIU51  0x80000000 /* Channel 51 In Use */
-
-/* Bit masks for MXVR_ALLOC_13 */
-
-#define                      CL52  0x7f       /* Channel 52 Connection Label */
-#define                     CIU52  0x80       /* Channel 52 In Use */
-#define                      CL53  0x7f00     /* Channel 53 Connection Label */
-#define                     CIU53  0x8000     /* Channel 53 In Use */
-#define                      CL54  0x7f0000   /* Channel 54 Connection Label */
-#define                     CIU54  0x800000   /* Channel 54 In Use */
-#define                      CL55  0x7f000000 /* Channel 55 Connection Label */
-#define                     CIU55  0x80000000 /* Channel 55 In Use */
-
-/* Bit masks for MXVR_ALLOC_14 */
-
-#define                      CL56  0x7f       /* Channel 56 Connection Label */
-#define                     CIU56  0x80       /* Channel 56 In Use */
-#define                      CL57  0x7f00     /* Channel 57 Connection Label */
-#define                     CIU57  0x8000     /* Channel 57 In Use */
-#define                      CL58  0x7f0000   /* Channel 58 Connection Label */
-#define                     CIU58  0x800000   /* Channel 58 In Use */
-#define                      CL59  0x7f000000 /* Channel 59 Connection Label */
-#define                     CIU59  0x80000000 /* Channel 59 In Use */
-
-/* MXVR_SYNC_LCHAN_0 Masks */
-
-#define LCHANPC0     0x0000000Flu
-#define LCHANPC1     0x000000F0lu
-#define LCHANPC2     0x00000F00lu
-#define LCHANPC3     0x0000F000lu
-#define LCHANPC4     0x000F0000lu
-#define LCHANPC5     0x00F00000lu
-#define LCHANPC6     0x0F000000lu
-#define LCHANPC7     0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_1 Masks */
-
-#define LCHANPC8     0x0000000Flu
-#define LCHANPC9     0x000000F0lu
-#define LCHANPC10    0x00000F00lu
-#define LCHANPC11    0x0000F000lu
-#define LCHANPC12    0x000F0000lu
-#define LCHANPC13    0x00F00000lu
-#define LCHANPC14    0x0F000000lu
-#define LCHANPC15    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_2 Masks */
-
-#define LCHANPC16    0x0000000Flu
-#define LCHANPC17    0x000000F0lu
-#define LCHANPC18    0x00000F00lu
-#define LCHANPC19    0x0000F000lu
-#define LCHANPC20    0x000F0000lu
-#define LCHANPC21    0x00F00000lu
-#define LCHANPC22    0x0F000000lu
-#define LCHANPC23    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_3 Masks */
-
-#define LCHANPC24    0x0000000Flu
-#define LCHANPC25    0x000000F0lu
-#define LCHANPC26    0x00000F00lu
-#define LCHANPC27    0x0000F000lu
-#define LCHANPC28    0x000F0000lu
-#define LCHANPC29    0x00F00000lu
-#define LCHANPC30    0x0F000000lu
-#define LCHANPC31    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_4 Masks */
-
-#define LCHANPC32    0x0000000Flu
-#define LCHANPC33    0x000000F0lu
-#define LCHANPC34    0x00000F00lu
-#define LCHANPC35    0x0000F000lu
-#define LCHANPC36    0x000F0000lu
-#define LCHANPC37    0x00F00000lu
-#define LCHANPC38    0x0F000000lu
-#define LCHANPC39    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_5 Masks */
-
-#define LCHANPC40    0x0000000Flu
-#define LCHANPC41    0x000000F0lu
-#define LCHANPC42    0x00000F00lu
-#define LCHANPC43    0x0000F000lu
-#define LCHANPC44    0x000F0000lu
-#define LCHANPC45    0x00F00000lu
-#define LCHANPC46    0x0F000000lu
-#define LCHANPC47    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_6 Masks */
-
-#define LCHANPC48    0x0000000Flu
-#define LCHANPC49    0x000000F0lu
-#define LCHANPC50    0x00000F00lu
-#define LCHANPC51    0x0000F000lu
-#define LCHANPC52    0x000F0000lu
-#define LCHANPC53    0x00F00000lu
-#define LCHANPC54    0x0F000000lu
-#define LCHANPC55    0xF0000000lu
-
-
-/* MXVR_SYNC_LCHAN_7 Masks */
-
-#define LCHANPC56    0x0000000Flu
-#define LCHANPC57    0x000000F0lu
-#define LCHANPC58    0x00000F00lu
-#define LCHANPC59    0x0000F000lu
-
-/* Bit masks for MXVR_DMAx_CONFIG */
-
-#define                    MDMAEN  0x1        /* DMA Channel Enable */
-#define                     DMADD  0x2        /* DMA Channel Direction */
-#define                 BY4SWAPEN  0x20       /* DMA Channel Four Byte Swap Enable */
-#define                     LCHAN  0x3c0      /* DMA Channel Logical Channel */
-#define                 BITSWAPEN  0x400      /* DMA Channel Bit Swap Enable */
-#define                 BY2SWAPEN  0x800      /* DMA Channel Two Byte Swap Enable */
-#define                     MFLOW  0x7000     /* DMA Channel Operation Flow */
-#define                   FIXEDPM  0x80000    /* DMA Channel Fixed Pattern Matching Select */
-#define                  STARTPAT  0x300000   /* DMA Channel Start Pattern Select */
-#define                   STOPPAT  0xc00000   /* DMA Channel Stop Pattern Select */
-#define                  COUNTPOS  0x1c000000 /* DMA Channel Count Position */
-
-/* Bit masks for MXVR_AP_CTL */
-
-#define                   STARTAP  0x1        /* Start Asynchronous Packet Transmission */
-#define                  CANCELAP  0x2        /* Cancel Asynchronous Packet Transmission */
-#define                   RESETAP  0x4        /* Reset Asynchronous Packet Arbitration */
-#define                    APRBE0  0x4000     /* Asynchronous Packet Receive Buffer Entry 0 */
-#define                    APRBE1  0x8000     /* Asynchronous Packet Receive Buffer Entry 1 */
-
-/* Bit masks for MXVR_APRB_START_ADDR */
-
-#define      MXVR_APRB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Receive Buffer Start Address */
-
-/* Bit masks for MXVR_APRB_CURR_ADDR */
-
-#define       MXVR_APRB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
-
-/* Bit masks for MXVR_APTB_START_ADDR */
-
-#define       MXVR_APTB_START_ADDR_MASK  0x1fffffe  /* Asynchronous Packet Transmit Buffer Start Address */
-
-/* Bit masks for MXVR_APTB_CURR_ADDR */
-
-#define        MXVR_APTB_CURR_ADDR_MASK  0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
-
-/* Bit masks for MXVR_CM_CTL */
-
-#define                   STARTCM  0x1        /* Start Control Message Transmission */
-#define                  CANCELCM  0x2        /* Cancel Control Message Transmission */
-#define                    CMRBE0  0x10000    /* Control Message Receive Buffer Entry 0 */
-#define                    CMRBE1  0x20000    /* Control Message Receive Buffer Entry 1 */
-#define                    CMRBE2  0x40000    /* Control Message Receive Buffer Entry 2 */
-#define                    CMRBE3  0x80000    /* Control Message Receive Buffer Entry 3 */
-#define                    CMRBE4  0x100000   /* Control Message Receive Buffer Entry 4 */
-#define                    CMRBE5  0x200000   /* Control Message Receive Buffer Entry 5 */
-#define                    CMRBE6  0x400000   /* Control Message Receive Buffer Entry 6 */
-#define                    CMRBE7  0x800000   /* Control Message Receive Buffer Entry 7 */
-#define                    CMRBE8  0x1000000  /* Control Message Receive Buffer Entry 8 */
-#define                    CMRBE9  0x2000000  /* Control Message Receive Buffer Entry 9 */
-#define                   CMRBE10  0x4000000  /* Control Message Receive Buffer Entry 10 */
-#define                   CMRBE11  0x8000000  /* Control Message Receive Buffer Entry 11 */
-#define                   CMRBE12  0x10000000 /* Control Message Receive Buffer Entry 12 */
-#define                   CMRBE13  0x20000000 /* Control Message Receive Buffer Entry 13 */
-#define                   CMRBE14  0x40000000 /* Control Message Receive Buffer Entry 14 */
-#define                   CMRBE15  0x80000000 /* Control Message Receive Buffer Entry 15 */
-
-/* Bit masks for MXVR_CMRB_START_ADDR */
-
-#define      MXVR_CMRB_START_ADDR_MASK  0x1fffffe  /* Control Message Receive Buffer Start Address */
-
-/* Bit masks for MXVR_CMRB_CURR_ADDR */
-
-#define       MXVR_CMRB_CURR_ADDR_MASK  0xffffffff /* Control Message Receive Buffer Current Address */
-
-/* Bit masks for MXVR_CMTB_START_ADDR */
-
-#define      MXVR_CMTB_START_ADDR_MASK  0x1fffffe  /* Control Message Transmit Buffer Start Address */
-
-/* Bit masks for MXVR_CMTB_CURR_ADDR */
-
-#define       MXVR_CMTB_CURR_ADDR_MASK  0xffffffff /* Control Message Transmit Buffer Current Address */
-
-/* Bit masks for MXVR_RRDB_START_ADDR */
-
-#define      MXVR_RRDB_START_ADDR_MASK  0x1fffffe  /* Remote Read Buffer Start Address */
-
-/* Bit masks for MXVR_RRDB_CURR_ADDR */
-
-#define       MXVR_RRDB_CURR_ADDR_MASK  0xffffffff /* Remote Read Buffer Current Address */
-
-/* Bit masks for MXVR_PAT_DATAx */
-
-#define              MATCH_DATA_0  0xff       /* Pattern Match Data Byte 0 */
-#define              MATCH_DATA_1  0xff00     /* Pattern Match Data Byte 1 */
-#define              MATCH_DATA_2  0xff0000   /* Pattern Match Data Byte 2 */
-#define              MATCH_DATA_3  0xff000000 /* Pattern Match Data Byte 3 */
-
-/* Bit masks for MXVR_PAT_EN_0 */
-
-#define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
-#define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
-#define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
-#define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
-#define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
-#define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
-#define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
-#define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
-#define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
-#define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
-#define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
-#define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
-#define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
-#define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
-#define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
-#define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
-#define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
-#define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
-#define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
-#define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
-#define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
-#define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
-#define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
-#define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
-#define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
-#define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
-#define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
-#define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
-#define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-
-/* Bit masks for MXVR_PAT_EN_1 */
-
-#define              MATCH_EN_0_0  0x1        /* Pattern Match Enable Byte 0 Bit 0 */
-#define              MATCH_EN_0_1  0x2        /* Pattern Match Enable Byte 0 Bit 1 */
-#define              MATCH_EN_0_2  0x4        /* Pattern Match Enable Byte 0 Bit 2 */
-#define              MATCH_EN_0_3  0x8        /* Pattern Match Enable Byte 0 Bit 3 */
-#define              MATCH_EN_0_4  0x10       /* Pattern Match Enable Byte 0 Bit 4 */
-#define              MATCH_EN_0_5  0x20       /* Pattern Match Enable Byte 0 Bit 5 */
-#define              MATCH_EN_0_6  0x40       /* Pattern Match Enable Byte 0 Bit 6 */
-#define              MATCH_EN_0_7  0x80       /* Pattern Match Enable Byte 0 Bit 7 */
-#define              MATCH_EN_1_0  0x100      /* Pattern Match Enable Byte 1 Bit 0 */
-#define              MATCH_EN_1_1  0x200      /* Pattern Match Enable Byte 1 Bit 1 */
-#define              MATCH_EN_1_2  0x400      /* Pattern Match Enable Byte 1 Bit 2 */
-#define              MATCH_EN_1_3  0x800      /* Pattern Match Enable Byte 1 Bit 3 */
-#define              MATCH_EN_1_4  0x1000     /* Pattern Match Enable Byte 1 Bit 4 */
-#define              MATCH_EN_1_5  0x2000     /* Pattern Match Enable Byte 1 Bit 5 */
-#define              MATCH_EN_1_6  0x4000     /* Pattern Match Enable Byte 1 Bit 6 */
-#define              MATCH_EN_1_7  0x8000     /* Pattern Match Enable Byte 1 Bit 7 */
-#define              MATCH_EN_2_0  0x10000    /* Pattern Match Enable Byte 2 Bit 0 */
-#define              MATCH_EN_2_1  0x20000    /* Pattern Match Enable Byte 2 Bit 1 */
-#define              MATCH_EN_2_2  0x40000    /* Pattern Match Enable Byte 2 Bit 2 */
-#define              MATCH_EN_2_3  0x80000    /* Pattern Match Enable Byte 2 Bit 3 */
-#define              MATCH_EN_2_4  0x100000   /* Pattern Match Enable Byte 2 Bit 4 */
-#define              MATCH_EN_2_5  0x200000   /* Pattern Match Enable Byte 2 Bit 5 */
-#define              MATCH_EN_2_6  0x400000   /* Pattern Match Enable Byte 2 Bit 6 */
-#define              MATCH_EN_2_7  0x800000   /* Pattern Match Enable Byte 2 Bit 7 */
-#define              MATCH_EN_3_0  0x1000000  /* Pattern Match Enable Byte 3 Bit 0 */
-#define              MATCH_EN_3_1  0x2000000  /* Pattern Match Enable Byte 3 Bit 1 */
-#define              MATCH_EN_3_2  0x4000000  /* Pattern Match Enable Byte 3 Bit 2 */
-#define              MATCH_EN_3_3  0x8000000  /* Pattern Match Enable Byte 3 Bit 3 */
-#define              MATCH_EN_3_4  0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define              MATCH_EN_3_5  0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define              MATCH_EN_3_6  0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define              MATCH_EN_3_7  0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-
-/* Bit masks for MXVR_FRAME_CNT_0 */
-
-#define                      FCNT  0xffff     /* Frame Count */
-
-/* Bit masks for MXVR_FRAME_CNT_1 */
-
-#define                      FCNT  0xffff     /* Frame Count */
-
-/* Bit masks for MXVR_ROUTING_0 */
-
-#define                    TX_CH0  0x3f       /* Transmit Channel 0 */
-#define                  MUTE_CH0  0x80       /* Mute Channel 0 */
-#define                    TX_CH1  0x3f00     /* Transmit Channel 0 */
-#define                  MUTE_CH1  0x8000     /* Mute Channel 0 */
-#define                    TX_CH2  0x3f0000   /* Transmit Channel 0 */
-#define                  MUTE_CH2  0x800000   /* Mute Channel 0 */
-#define                    TX_CH3  0x3f000000 /* Transmit Channel 0 */
-#define                  MUTE_CH3  0x80000000 /* Mute Channel 0 */
-
-/* Bit masks for MXVR_ROUTING_1 */
-
-#define                    TX_CH4  0x3f       /* Transmit Channel 4 */
-#define                  MUTE_CH4  0x80       /* Mute Channel 4 */
-#define                    TX_CH5  0x3f00     /* Transmit Channel 5 */
-#define                  MUTE_CH5  0x8000     /* Mute Channel 5 */
-#define                    TX_CH6  0x3f0000   /* Transmit Channel 6 */
-#define                  MUTE_CH6  0x800000   /* Mute Channel 6 */
-#define                    TX_CH7  0x3f000000 /* Transmit Channel 7 */
-#define                  MUTE_CH7  0x80000000 /* Mute Channel 7 */
-
-/* Bit masks for MXVR_ROUTING_2 */
-
-#define                    TX_CH8  0x3f       /* Transmit Channel 8 */
-#define                  MUTE_CH8  0x80       /* Mute Channel 8 */
-#define                    TX_CH9  0x3f00     /* Transmit Channel 9 */
-#define                  MUTE_CH9  0x8000     /* Mute Channel 9 */
-#define                   TX_CH10  0x3f0000   /* Transmit Channel 10 */
-#define                 MUTE_CH10  0x800000   /* Mute Channel 10 */
-#define                   TX_CH11  0x3f000000 /* Transmit Channel 11 */
-#define                 MUTE_CH11  0x80000000 /* Mute Channel 11 */
-
-/* Bit masks for MXVR_ROUTING_3 */
-
-#define                   TX_CH12  0x3f       /* Transmit Channel 12 */
-#define                 MUTE_CH12  0x80       /* Mute Channel 12 */
-#define                   TX_CH13  0x3f00     /* Transmit Channel 13 */
-#define                 MUTE_CH13  0x8000     /* Mute Channel 13 */
-#define                   TX_CH14  0x3f0000   /* Transmit Channel 14 */
-#define                 MUTE_CH14  0x800000   /* Mute Channel 14 */
-#define                   TX_CH15  0x3f000000 /* Transmit Channel 15 */
-#define                 MUTE_CH15  0x80000000 /* Mute Channel 15 */
-
-/* Bit masks for MXVR_ROUTING_4 */
-
-#define                   TX_CH16  0x3f       /* Transmit Channel 16 */
-#define                 MUTE_CH16  0x80       /* Mute Channel 16 */
-#define                   TX_CH17  0x3f00     /* Transmit Channel 17 */
-#define                 MUTE_CH17  0x8000     /* Mute Channel 17 */
-#define                   TX_CH18  0x3f0000   /* Transmit Channel 18 */
-#define                 MUTE_CH18  0x800000   /* Mute Channel 18 */
-#define                   TX_CH19  0x3f000000 /* Transmit Channel 19 */
-#define                 MUTE_CH19  0x80000000 /* Mute Channel 19 */
-
-/* Bit masks for MXVR_ROUTING_5 */
-
-#define                   TX_CH20  0x3f       /* Transmit Channel 20 */
-#define                 MUTE_CH20  0x80       /* Mute Channel 20 */
-#define                   TX_CH21  0x3f00     /* Transmit Channel 21 */
-#define                 MUTE_CH21  0x8000     /* Mute Channel 21 */
-#define                   TX_CH22  0x3f0000   /* Transmit Channel 22 */
-#define                 MUTE_CH22  0x800000   /* Mute Channel 22 */
-#define                   TX_CH23  0x3f000000 /* Transmit Channel 23 */
-#define                 MUTE_CH23  0x80000000 /* Mute Channel 23 */
-
-/* Bit masks for MXVR_ROUTING_6 */
-
-#define                   TX_CH24  0x3f       /* Transmit Channel 24 */
-#define                 MUTE_CH24  0x80       /* Mute Channel 24 */
-#define                   TX_CH25  0x3f00     /* Transmit Channel 25 */
-#define                 MUTE_CH25  0x8000     /* Mute Channel 25 */
-#define                   TX_CH26  0x3f0000   /* Transmit Channel 26 */
-#define                 MUTE_CH26  0x800000   /* Mute Channel 26 */
-#define                   TX_CH27  0x3f000000 /* Transmit Channel 27 */
-#define                 MUTE_CH27  0x80000000 /* Mute Channel 27 */
-
-/* Bit masks for MXVR_ROUTING_7 */
-
-#define                   TX_CH28  0x3f       /* Transmit Channel 28 */
-#define                 MUTE_CH28  0x80       /* Mute Channel 28 */
-#define                   TX_CH29  0x3f00     /* Transmit Channel 29 */
-#define                 MUTE_CH29  0x8000     /* Mute Channel 29 */
-#define                   TX_CH30  0x3f0000   /* Transmit Channel 30 */
-#define                 MUTE_CH30  0x800000   /* Mute Channel 30 */
-#define                   TX_CH31  0x3f000000 /* Transmit Channel 31 */
-#define                 MUTE_CH31  0x80000000 /* Mute Channel 31 */
-
-/* Bit masks for MXVR_ROUTING_8 */
-
-#define                   TX_CH32  0x3f       /* Transmit Channel 32 */
-#define                 MUTE_CH32  0x80       /* Mute Channel 32 */
-#define                   TX_CH33  0x3f00     /* Transmit Channel 33 */
-#define                 MUTE_CH33  0x8000     /* Mute Channel 33 */
-#define                   TX_CH34  0x3f0000   /* Transmit Channel 34 */
-#define                 MUTE_CH34  0x800000   /* Mute Channel 34 */
-#define                   TX_CH35  0x3f000000 /* Transmit Channel 35 */
-#define                 MUTE_CH35  0x80000000 /* Mute Channel 35 */
-
-/* Bit masks for MXVR_ROUTING_9 */
-
-#define                   TX_CH36  0x3f       /* Transmit Channel 36 */
-#define                 MUTE_CH36  0x80       /* Mute Channel 36 */
-#define                   TX_CH37  0x3f00     /* Transmit Channel 37 */
-#define                 MUTE_CH37  0x8000     /* Mute Channel 37 */
-#define                   TX_CH38  0x3f0000   /* Transmit Channel 38 */
-#define                 MUTE_CH38  0x800000   /* Mute Channel 38 */
-#define                   TX_CH39  0x3f000000 /* Transmit Channel 39 */
-#define                 MUTE_CH39  0x80000000 /* Mute Channel 39 */
-
-/* Bit masks for MXVR_ROUTING_10 */
-
-#define                   TX_CH40  0x3f       /* Transmit Channel 40 */
-#define                 MUTE_CH40  0x80       /* Mute Channel 40 */
-#define                   TX_CH41  0x3f00     /* Transmit Channel 41 */
-#define                 MUTE_CH41  0x8000     /* Mute Channel 41 */
-#define                   TX_CH42  0x3f0000   /* Transmit Channel 42 */
-#define                 MUTE_CH42  0x800000   /* Mute Channel 42 */
-#define                   TX_CH43  0x3f000000 /* Transmit Channel 43 */
-#define                 MUTE_CH43  0x80000000 /* Mute Channel 43 */
-
-/* Bit masks for MXVR_ROUTING_11 */
-
-#define                   TX_CH44  0x3f       /* Transmit Channel 44 */
-#define                 MUTE_CH44  0x80       /* Mute Channel 44 */
-#define                   TX_CH45  0x3f00     /* Transmit Channel 45 */
-#define                 MUTE_CH45  0x8000     /* Mute Channel 45 */
-#define                   TX_CH46  0x3f0000   /* Transmit Channel 46 */
-#define                 MUTE_CH46  0x800000   /* Mute Channel 46 */
-#define                   TX_CH47  0x3f000000 /* Transmit Channel 47 */
-#define                 MUTE_CH47  0x80000000 /* Mute Channel 47 */
-
-/* Bit masks for MXVR_ROUTING_12 */
-
-#define                   TX_CH48  0x3f       /* Transmit Channel 48 */
-#define                 MUTE_CH48  0x80       /* Mute Channel 48 */
-#define                   TX_CH49  0x3f00     /* Transmit Channel 49 */
-#define                 MUTE_CH49  0x8000     /* Mute Channel 49 */
-#define                   TX_CH50  0x3f0000   /* Transmit Channel 50 */
-#define                 MUTE_CH50  0x800000   /* Mute Channel 50 */
-#define                   TX_CH51  0x3f000000 /* Transmit Channel 51 */
-#define                 MUTE_CH51  0x80000000 /* Mute Channel 51 */
-
-/* Bit masks for MXVR_ROUTING_13 */
-
-#define                   TX_CH52  0x3f       /* Transmit Channel 52 */
-#define                 MUTE_CH52  0x80       /* Mute Channel 52 */
-#define                   TX_CH53  0x3f00     /* Transmit Channel 53 */
-#define                 MUTE_CH53  0x8000     /* Mute Channel 53 */
-#define                   TX_CH54  0x3f0000   /* Transmit Channel 54 */
-#define                 MUTE_CH54  0x800000   /* Mute Channel 54 */
-#define                   TX_CH55  0x3f000000 /* Transmit Channel 55 */
-#define                 MUTE_CH55  0x80000000 /* Mute Channel 55 */
-
-/* Bit masks for MXVR_ROUTING_14 */
-
-#define                   TX_CH56  0x3f       /* Transmit Channel 56 */
-#define                 MUTE_CH56  0x80       /* Mute Channel 56 */
-#define                   TX_CH57  0x3f00     /* Transmit Channel 57 */
-#define                 MUTE_CH57  0x8000     /* Mute Channel 57 */
-#define                   TX_CH58  0x3f0000   /* Transmit Channel 58 */
-#define                 MUTE_CH58  0x800000   /* Mute Channel 58 */
-#define                   TX_CH59  0x3f000000 /* Transmit Channel 59 */
-#define                 MUTE_CH59  0x80000000 /* Mute Channel 59 */
-
-/* Bit masks for MXVR_BLOCK_CNT */
-
-#define                      BCNT  0xffff     /* Block Count */
-
-/* Bit masks for MXVR_CLK_CTL */
-
-#define                  MXTALCEN  0x1        /* MXVR Crystal Oscillator Clock Enable */
-#define                  MXTALFEN  0x2        /* MXVR Crystal Oscillator Feedback Enable */
-#define                  MXTALMUL  0x30       /* MXVR Crystal Multiplier */
-#define                  CLKX3SEL  0x80       /* Clock Generation Source Select */
-#define                   MMCLKEN  0x100      /* Master Clock Enable */
-#define                  MMCLKMUL  0x1e00     /* Master Clock Multiplication Factor */
-#define                   PLLSMPS  0xe000     /* MXVR PLL State Machine Prescaler */
-#define                   MBCLKEN  0x10000    /* Bit Clock Enable */
-#define                  MBCLKDIV  0x1e0000   /* Bit Clock Divide Factor */
-#define                     INVRX  0x800000   /* Invert Receive Data */
-#define                     MFSEN  0x1000000  /* Frame Sync Enable */
-#define                    MFSDIV  0x1e000000 /* Frame Sync Divide Factor */
-#define                    MFSSEL  0x60000000 /* Frame Sync Select */
-#define                   MFSSYNC  0x80000000 /* Frame Sync Synchronization Select */
-
-/* Bit masks for MXVR_CDRPLL_CTL */
-
-#define                   CDRSMEN  0x1        /* MXVR CDRPLL State Machine Enable */
-#define                   CDRRSTB  0x2        /* MXVR CDRPLL Reset */
-#define                   CDRSVCO  0x4        /* MXVR CDRPLL Start VCO */
-#define                   CDRMODE  0x8        /* MXVR CDRPLL CDR Mode Select */
-#define                   CDRSCNT  0x3f0      /* MXVR CDRPLL Start Counter */
-#define                   CDRLCNT  0xfc00     /* MXVR CDRPLL Lock Counter */
-#define                 CDRSHPSEL  0x3f0000   /* MXVR CDRPLL Shaper Select */
-#define                  CDRSHPEN  0x800000   /* MXVR CDRPLL Shaper Enable */
-#define                  CDRCPSEL  0xff000000 /* MXVR CDRPLL Charge Pump Current Select */
-
-/* Bit masks for MXVR_FMPLL_CTL */
-
-#define                    FMSMEN  0x1        /* MXVR FMPLL State Machine Enable */
-#define                    FMRSTB  0x2        /* MXVR FMPLL Reset */
-#define                    FMSVCO  0x4        /* MXVR FMPLL Start VCO */
-#define                    FMSCNT  0x3f0      /* MXVR FMPLL Start Counter */
-#define                    FMLCNT  0xfc00     /* MXVR FMPLL Lock Counter */
-#define                   FMCPSEL  0xff000000 /* MXVR FMPLL Charge Pump Current Select */
-
-/* Bit masks for MXVR_PIN_CTL */
-
-#define                  MTXONBOD  0x1        /* MTXONB Open Drain Select */
-#define                   MTXONBG  0x2        /* MTXONB Gates MTX Select */
-#define                     MFSOE  0x10       /* MFS Output Enable */
-#define                  MFSGPSEL  0x20       /* MFS General Purpose Output Select */
-#define                  MFSGPDAT  0x40       /* MFS General Purpose Output Data */
-
-/* Bit masks for MXVR_SCLK_CNT */
-
-#define                      SCNT  0xffff     /* System Clock Count */
-
-/* Bit masks for KPAD_CTL */
-
-#define                   KPAD_EN  0x1        /* Keypad Enable */
-#define              KPAD_IRQMODE  0x6        /* Key Press Interrupt Enable */
-#define                KPAD_ROWEN  0x1c00     /* Row Enable Width */
-#define                KPAD_COLEN  0xe000     /* Column Enable Width */
-
-/* Bit masks for KPAD_PRESCALE */
-
-#define         KPAD_PRESCALE_VAL  0x3f       /* Key Prescale Value */
-
-/* Bit masks for KPAD_MSEL */
-
-#define                DBON_SCALE  0xff       /* Debounce Scale Value */
-#define              COLDRV_SCALE  0xff00     /* Column Driver Scale Value */
-
-/* Bit masks for KPAD_ROWCOL */
-
-#define                  KPAD_ROW  0xff       /* Rows Pressed */
-#define                  KPAD_COL  0xff00     /* Columns Pressed */
-
-/* Bit masks for KPAD_STAT */
-
-#define                  KPAD_IRQ  0x1        /* Keypad Interrupt Status */
-#define              KPAD_MROWCOL  0x6        /* Multiple Row/Column Keypress Status */
-#define              KPAD_PRESSED  0x8        /* Key press current status */
-
-/* Bit masks for KPAD_SOFTEVAL */
-
-#define           KPAD_SOFTEVAL_E  0x2        /* Software Programmable Force Evaluate */
-
-/* Bit masks for SDH_COMMAND */
-
-#define                   CMD_IDX  0x3f       /* Command Index */
-#define                   CMD_RSP  0x40       /* Response */
-#define                 CMD_L_RSP  0x80       /* Long Response */
-#define                 CMD_INT_E  0x100      /* Command Interrupt */
-#define                CMD_PEND_E  0x200      /* Command Pending */
-#define                     CMD_E  0x400      /* Command Enable */
-
-/* Bit masks for SDH_PWR_CTL */
-
-#define                    PWR_ON  0x3        /* Power On */
-#if 0
-#define                       TBD  0x3c       /* TBD */
-#endif
-#define                 SD_CMD_OD  0x40       /* Open Drain Output */
-#define                   ROD_CTL  0x80       /* Rod Control */
-
-/* Bit masks for SDH_CLK_CTL */
-
-#define                    CLKDIV  0xff       /* MC_CLK Divisor */
-#define                     CLK_E  0x100      /* MC_CLK Bus Clock Enable */
-#define                  PWR_SV_E  0x200      /* Power Save Enable */
-#define             CLKDIV_BYPASS  0x400      /* Bypass Divisor */
-#define                  WIDE_BUS  0x800      /* Wide Bus Mode Enable */
-
-/* Bit masks for SDH_RESP_CMD */
-
-#define                  RESP_CMD  0x3f       /* Response Command */
-
-/* Bit masks for SDH_DATA_CTL */
-
-#define                     DTX_E  0x1        /* Data Transfer Enable */
-#define                   DTX_DIR  0x2        /* Data Transfer Direction */
-#define                  DTX_MODE  0x4        /* Data Transfer Mode */
-#define                 DTX_DMA_E  0x8        /* Data Transfer DMA Enable */
-#define              DTX_BLK_LGTH  0xf0       /* Data Transfer Block Length */
-
-/* Bit masks for SDH_STATUS */
-
-#define              CMD_CRC_FAIL  0x1        /* CMD CRC Fail */
-#define              DAT_CRC_FAIL  0x2        /* Data CRC Fail */
-#define               CMD_TIME_OUT  0x4        /* CMD Time Out */
-#define               DAT_TIME_OUT  0x8        /* Data Time Out */
-#define               TX_UNDERRUN  0x10       /* Transmit Underrun */
-#define                RX_OVERRUN  0x20       /* Receive Overrun */
-#define              CMD_RESP_END  0x40       /* CMD Response End */
-#define                  CMD_SENT  0x80       /* CMD Sent */
-#define                   DAT_END  0x100      /* Data End */
-#define             START_BIT_ERR  0x200      /* Start Bit Error */
-#define               DAT_BLK_END  0x400      /* Data Block End */
-#define                   CMD_ACT  0x800      /* CMD Active */
-#define                    TX_ACT  0x1000     /* Transmit Active */
-#define                    RX_ACT  0x2000     /* Receive Active */
-#define              TX_FIFO_STAT  0x4000     /* Transmit FIFO Status */
-#define              RX_FIFO_STAT  0x8000     /* Receive FIFO Status */
-#define              TX_FIFO_FULL  0x10000    /* Transmit FIFO Full */
-#define              RX_FIFO_FULL  0x20000    /* Receive FIFO Full */
-#define              TX_FIFO_ZERO  0x40000    /* Transmit FIFO Empty */
-#define               RX_DAT_ZERO  0x80000    /* Receive FIFO Empty */
-#define                TX_DAT_RDY  0x100000   /* Transmit Data Available */
-#define               RX_FIFO_RDY  0x200000   /* Receive Data Available */
-
-/* Bit masks for SDH_STATUS_CLR */
-
-#define         CMD_CRC_FAIL_STAT  0x1        /* CMD CRC Fail Status */
-#define         DAT_CRC_FAIL_STAT  0x2        /* Data CRC Fail Status */
-#define          CMD_TIMEOUT_STAT  0x4        /* CMD Time Out Status */
-#define          DAT_TIMEOUT_STAT  0x8        /* Data Time Out status */
-#define          TX_UNDERRUN_STAT  0x10       /* Transmit Underrun Status */
-#define           RX_OVERRUN_STAT  0x20       /* Receive Overrun Status */
-#define         CMD_RESP_END_STAT  0x40       /* CMD Response End Status */
-#define             CMD_SENT_STAT  0x80       /* CMD Sent Status */
-#define              DAT_END_STAT  0x100      /* Data End Status */
-#define        START_BIT_ERR_STAT  0x200      /* Start Bit Error Status */
-#define          DAT_BLK_END_STAT  0x400      /* Data Block End Status */
-
-/* Bit masks for SDH_MASK0 */
-
-#define         CMD_CRC_FAIL_MASK  0x1        /* CMD CRC Fail Mask */
-#define         DAT_CRC_FAIL_MASK  0x2        /* Data CRC Fail Mask */
-#define          CMD_TIMEOUT_MASK  0x4        /* CMD Time Out Mask */
-#define          DAT_TIMEOUT_MASK  0x8        /* Data Time Out Mask */
-#define          TX_UNDERRUN_MASK  0x10       /* Transmit Underrun Mask */
-#define           RX_OVERRUN_MASK  0x20       /* Receive Overrun Mask */
-#define         CMD_RESP_END_MASK  0x40       /* CMD Response End Mask */
-#define             CMD_SENT_MASK  0x80       /* CMD Sent Mask */
-#define              DAT_END_MASK  0x100      /* Data End Mask */
-#define        START_BIT_ERR_MASK  0x200      /* Start Bit Error Mask */
-#define          DAT_BLK_END_MASK  0x400      /* Data Block End Mask */
-#define              CMD_ACT_MASK  0x800      /* CMD Active Mask */
-#define               TX_ACT_MASK  0x1000     /* Transmit Active Mask */
-#define               RX_ACT_MASK  0x2000     /* Receive Active Mask */
-#define         TX_FIFO_STAT_MASK  0x4000     /* Transmit FIFO Status Mask */
-#define         RX_FIFO_STAT_MASK  0x8000     /* Receive FIFO Status Mask */
-#define         TX_FIFO_FULL_MASK  0x10000    /* Transmit FIFO Full Mask */
-#define         RX_FIFO_FULL_MASK  0x20000    /* Receive FIFO Full Mask */
-#define         TX_FIFO_ZERO_MASK  0x40000    /* Transmit FIFO Empty Mask */
-#define          RX_DAT_ZERO_MASK  0x80000    /* Receive FIFO Empty Mask */
-#define           TX_DAT_RDY_MASK  0x100000   /* Transmit Data Available Mask */
-#define          RX_FIFO_RDY_MASK  0x200000   /* Receive Data Available Mask */
-
-/* Bit masks for SDH_FIFO_CNT */
-
-#define                FIFO_COUNT  0x7fff     /* FIFO Count */
-
-/* Bit masks for SDH_E_STATUS */
-
-#define              SDIO_INT_DET  0x2        /* SDIO Int Detected */
-#define               SD_CARD_DET  0x10       /* SD Card Detect */
-
-/* Bit masks for SDH_E_MASK */
-
-#define                  SDIO_MSK  0x2        /* Mask SDIO Int Detected */
-#define                   SCD_MSK  0x40       /* Mask Card Detect */
-
-/* Bit masks for SDH_CFG */
-
-#define                   CLKS_EN  0x1        /* Clocks Enable */
-#define                      SD4E  0x4        /* SDIO 4-Bit Enable */
-#define                       MWE  0x8        /* Moving Window Enable */
-#define                    SD_RST  0x10       /* SDMMC Reset */
-#define                 PUP_SDDAT  0x20       /* Pull-up SD_DAT */
-#define                PUP_SDDAT3  0x40       /* Pull-up SD_DAT3 */
-#define                 PD_SDDAT3  0x80       /* Pull-down SD_DAT3 */
-
-/* Bit masks for SDH_RD_WAIT_EN */
-
-#define                       RWR  0x1        /* Read Wait Request */
-
-/* Bit masks for ATAPI_CONTROL */
-
-#define                 PIO_START  0x1        /* Start PIO/Reg Op */
-#define               MULTI_START  0x2        /* Start Multi-DMA Op */
-#define               ULTRA_START  0x4        /* Start Ultra-DMA Op */
-#define                  XFER_DIR  0x8        /* Transfer Direction */
-#define                  IORDY_EN  0x10       /* IORDY Enable */
-#define                FIFO_FLUSH  0x20       /* Flush FIFOs */
-#define                  SOFT_RST  0x40       /* Soft Reset */
-#define                   DEV_RST  0x80       /* Device Reset */
-#define                TFRCNT_RST  0x100      /* Trans Count Reset */
-#define               END_ON_TERM  0x200      /* End/Terminate Select */
-#define               PIO_USE_DMA  0x400      /* PIO-DMA Enable */
-#define          UDMAIN_FIFO_THRS  0xf000     /* Ultra DMA-IN FIFO Threshold */
-
-/* Bit masks for ATAPI_STATUS */
-
-#define               PIO_XFER_ON  0x1        /* PIO transfer in progress */
-#define             MULTI_XFER_ON  0x2        /* Multi-word DMA transfer in progress */
-#define             ULTRA_XFER_ON  0x4        /* Ultra DMA transfer in progress */
-#define               ULTRA_IN_FL  0xf0       /* Ultra DMA Input FIFO Level */
-
-/* Bit masks for ATAPI_DEV_ADDR */
-
-#define                  DEV_ADDR  0x1f       /* Device Address */
-
-/* Bit masks for ATAPI_INT_MASK */
-
-#define        ATAPI_DEV_INT_MASK  0x1        /* Device interrupt mask */
-#define             PIO_DONE_MASK  0x2        /* PIO transfer done interrupt mask */
-#define           MULTI_DONE_MASK  0x4        /* Multi-DMA transfer done interrupt mask */
-#define          UDMAIN_DONE_MASK  0x8        /* Ultra-DMA in transfer done interrupt mask */
-#define         UDMAOUT_DONE_MASK  0x10       /* Ultra-DMA out transfer done interrupt mask */
-#define       HOST_TERM_XFER_MASK  0x20       /* Host terminate current transfer interrupt mask */
-#define           MULTI_TERM_MASK  0x40       /* Device terminate Multi-DMA transfer interrupt mask */
-#define          UDMAIN_TERM_MASK  0x80       /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define         UDMAOUT_TERM_MASK  0x100      /* Device terminate Ultra-DMA-out transfer interrupt mask */
-
-/* Bit masks for ATAPI_INT_STATUS */
-
-#define             ATAPI_DEV_INT  0x1        /* Device interrupt status */
-#define              PIO_DONE_INT  0x2        /* PIO transfer done interrupt status */
-#define            MULTI_DONE_INT  0x4        /* Multi-DMA transfer done interrupt status */
-#define           UDMAIN_DONE_INT  0x8        /* Ultra-DMA in transfer done interrupt status */
-#define          UDMAOUT_DONE_INT  0x10       /* Ultra-DMA out transfer done interrupt status */
-#define        HOST_TERM_XFER_INT  0x20       /* Host terminate current transfer interrupt status */
-#define            MULTI_TERM_INT  0x40       /* Device terminate Multi-DMA transfer interrupt status */
-#define           UDMAIN_TERM_INT  0x80       /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define          UDMAOUT_TERM_INT  0x100      /* Device terminate Ultra-DMA-out transfer interrupt status */
-
-/* Bit masks for ATAPI_LINE_STATUS */
-
-#define                ATAPI_INTR  0x1        /* Device interrupt to host line status */
-#define                ATAPI_DASP  0x2        /* Device dasp to host line status */
-#define                ATAPI_CS0N  0x4        /* ATAPI chip select 0 line status */
-#define                ATAPI_CS1N  0x8        /* ATAPI chip select 1 line status */
-#define                ATAPI_ADDR  0x70       /* ATAPI address line status */
-#define              ATAPI_DMAREQ  0x80       /* ATAPI DMA request line status */
-#define             ATAPI_DMAACKN  0x100      /* ATAPI DMA acknowledge line status */
-#define               ATAPI_DIOWN  0x200      /* ATAPI write line status */
-#define               ATAPI_DIORN  0x400      /* ATAPI read line status */
-#define               ATAPI_IORDY  0x800      /* ATAPI IORDY line status */
-
-/* Bit masks for ATAPI_SM_STATE */
-
-#define                PIO_CSTATE  0xf        /* PIO mode state machine current state */
-#define                DMA_CSTATE  0xf0       /* DMA mode state machine current state */
-#define             UDMAIN_CSTATE  0xf00      /* Ultra DMA-In mode state machine current state */
-#define            UDMAOUT_CSTATE  0xf000     /* ATAPI IORDY line status */
-
-/* Bit masks for ATAPI_TERMINATE */
-
-#define           ATAPI_HOST_TERM  0x1        /* Host terminationation */
-
-/* Bit masks for ATAPI_REG_TIM_0 */
-
-#define                    T2_REG  0xff       /* End of cycle time for register access transfers */
-#define                  TEOC_REG  0xff00     /* Selects DIOR/DIOW pulsewidth */
-
-/* Bit masks for ATAPI_PIO_TIM_0 */
-
-#define                    T1_REG  0xf        /* Time from address valid to DIOR/DIOW */
-#define                T2_REG_PIO  0xff0      /* DIOR/DIOW pulsewidth */
-#define                    T4_REG  0xf000     /* DIOW data hold */
-
-/* Bit masks for ATAPI_PIO_TIM_1 */
-
-#define              TEOC_REG_PIO  0xff       /* End of cycle time for PIO access transfers. */
-
-/* Bit masks for ATAPI_MULTI_TIM_0 */
-
-#define                        TD  0xff       /* DIOR/DIOW asserted pulsewidth */
-#define                        TM  0xff00     /* Time from address valid to DIOR/DIOW */
-
-/* Bit masks for ATAPI_MULTI_TIM_1 */
-
-#define                       TKW  0xff       /* Selects DIOW negated pulsewidth */
-#define                       TKR  0xff00     /* Selects DIOR negated pulsewidth */
-
-/* Bit masks for ATAPI_MULTI_TIM_2 */
-
-#define                        TH  0xff       /* Selects DIOW data hold */
-#define                      TEOC  0xff00     /* Selects end of cycle for DMA */
-
-/* Bit masks for ATAPI_ULTRA_TIM_0 */
-
-#define                      TACK  0xff       /* Selects setup and hold times for TACK */
-#define                      TENV  0xff00     /* Selects envelope time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_1 */
-
-#define                      TDVS  0xff       /* Selects data valid setup time */
-#define                 TCYC_TDVS  0xff00     /* Selects cycle time - TDVS time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_2 */
-
-#define                       TSS  0xff       /* Selects time from STROBE edge to negation of DMARQ or assertion of STOP */
-#define                      TMLI  0xff00     /* Selects interlock time */
-
-/* Bit masks for ATAPI_ULTRA_TIM_3 */
-
-#define                      TZAH  0xff       /* Selects minimum delay required for output */
-#define               READY_PAUSE  0xff00     /* Selects ready to pause */
-
-/* Bit masks for TIMER_ENABLE1 */
-
-#define                    TIMEN8  0x1        /* Timer 8 Enable */
-#define                    TIMEN9  0x2        /* Timer 9 Enable */
-#define                   TIMEN10  0x4        /* Timer 10 Enable */
-
-/* Bit masks for TIMER_DISABLE1 */
-
-#define                   TIMDIS8  0x1        /* Timer 8 Disable */
-#define                   TIMDIS9  0x2        /* Timer 9 Disable */
-#define                  TIMDIS10  0x4        /* Timer 10 Disable */
-
-/* Bit masks for TIMER_STATUS1 */
-
-#define                    TIMIL8  0x1        /* Timer 8 Interrupt */
-#define                    TIMIL9  0x2        /* Timer 9 Interrupt */
-#define                   TIMIL10  0x4        /* Timer 10 Interrupt */
-#define                 TOVF_ERR8  0x10       /* Timer 8 Counter Overflow */
-#define                 TOVF_ERR9  0x20       /* Timer 9 Counter Overflow */
-#define                TOVF_ERR10  0x40       /* Timer 10 Counter Overflow */
-#define                     TRUN8  0x1000     /* Timer 8 Slave Enable Status */
-#define                     TRUN9  0x2000     /* Timer 9 Slave Enable Status */
-#define                    TRUN10  0x4000     /* Timer 10 Slave Enable Status */
-
-/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
-
-/* Bit masks for USB_FADDR */
-
-#define          FUNCTION_ADDRESS  0x7f       /* Function address */
-
-/* Bit masks for USB_POWER */
-
-#define           ENABLE_SUSPENDM  0x1        /* enable SuspendM output */
-#define              SUSPEND_MODE  0x2        /* Suspend Mode indicator */
-#define               RESUME_MODE  0x4        /* DMA Mode */
-#define                     RESET  0x8        /* Reset indicator */
-#define                   HS_MODE  0x10       /* High Speed mode indicator */
-#define                 HS_ENABLE  0x20       /* high Speed Enable */
-#define                 SOFT_CONN  0x40       /* Soft connect */
-#define                ISO_UPDATE  0x80       /* Isochronous update */
-
-/* Bit masks for USB_INTRTX */
-
-#define                    EP0_TX  0x1        /* Tx Endpoint 0 interrupt */
-#define                    EP1_TX  0x2        /* Tx Endpoint 1 interrupt */
-#define                    EP2_TX  0x4        /* Tx Endpoint 2 interrupt */
-#define                    EP3_TX  0x8        /* Tx Endpoint 3 interrupt */
-#define                    EP4_TX  0x10       /* Tx Endpoint 4 interrupt */
-#define                    EP5_TX  0x20       /* Tx Endpoint 5 interrupt */
-#define                    EP6_TX  0x40       /* Tx Endpoint 6 interrupt */
-#define                    EP7_TX  0x80       /* Tx Endpoint 7 interrupt */
-
-/* Bit masks for USB_INTRRX */
-
-#define                    EP1_RX  0x2        /* Rx Endpoint 1 interrupt */
-#define                    EP2_RX  0x4        /* Rx Endpoint 2 interrupt */
-#define                    EP3_RX  0x8        /* Rx Endpoint 3 interrupt */
-#define                    EP4_RX  0x10       /* Rx Endpoint 4 interrupt */
-#define                    EP5_RX  0x20       /* Rx Endpoint 5 interrupt */
-#define                    EP6_RX  0x40       /* Rx Endpoint 6 interrupt */
-#define                    EP7_RX  0x80       /* Rx Endpoint 7 interrupt */
-
-/* Bit masks for USB_INTRTXE */
-
-#define                  EP0_TX_E  0x1        /* Endpoint 0 interrupt Enable */
-#define                  EP1_TX_E  0x2        /* Tx Endpoint 1 interrupt  Enable */
-#define                  EP2_TX_E  0x4        /* Tx Endpoint 2 interrupt  Enable */
-#define                  EP3_TX_E  0x8        /* Tx Endpoint 3 interrupt  Enable */
-#define                  EP4_TX_E  0x10       /* Tx Endpoint 4 interrupt  Enable */
-#define                  EP5_TX_E  0x20       /* Tx Endpoint 5 interrupt  Enable */
-#define                  EP6_TX_E  0x40       /* Tx Endpoint 6 interrupt  Enable */
-#define                  EP7_TX_E  0x80       /* Tx Endpoint 7 interrupt  Enable */
-
-/* Bit masks for USB_INTRRXE */
-
-#define                  EP1_RX_E  0x2        /* Rx Endpoint 1 interrupt  Enable */
-#define                  EP2_RX_E  0x4        /* Rx Endpoint 2 interrupt  Enable */
-#define                  EP3_RX_E  0x8        /* Rx Endpoint 3 interrupt  Enable */
-#define                  EP4_RX_E  0x10       /* Rx Endpoint 4 interrupt  Enable */
-#define                  EP5_RX_E  0x20       /* Rx Endpoint 5 interrupt  Enable */
-#define                  EP6_RX_E  0x40       /* Rx Endpoint 6 interrupt  Enable */
-#define                  EP7_RX_E  0x80       /* Rx Endpoint 7 interrupt  Enable */
-
-/* Bit masks for USB_INTRUSB */
-
-#define                 SUSPEND_B  0x1        /* Suspend indicator */
-#define                  RESUME_B  0x2        /* Resume indicator */
-#define          RESET_OR_BABLE_B  0x4        /* Reset/babble indicator */
-#define                     SOF_B  0x8        /* Start of frame */
-#define                    CONN_B  0x10       /* Connection indicator */
-#define                  DISCON_B  0x20       /* Disconnect indicator */
-#define             SESSION_REQ_B  0x40       /* Session Request */
-#define              VBUS_ERROR_B  0x80       /* Vbus threshold indicator */
-
-/* Bit masks for USB_INTRUSBE */
-
-#define                SUSPEND_BE  0x1        /* Suspend indicator int enable */
-#define                 RESUME_BE  0x2        /* Resume indicator int enable */
-#define         RESET_OR_BABLE_BE  0x4        /* Reset/babble indicator int enable */
-#define                    SOF_BE  0x8        /* Start of frame int enable */
-#define                   CONN_BE  0x10       /* Connection indicator int enable */
-#define                 DISCON_BE  0x20       /* Disconnect indicator int enable */
-#define            SESSION_REQ_BE  0x40       /* Session Request int enable */
-#define             VBUS_ERROR_BE  0x80       /* Vbus threshold indicator int enable */
-
-/* Bit masks for USB_FRAME */
-
-#define              FRAME_NUMBER  0x7ff      /* Frame number */
-
-/* Bit masks for USB_INDEX */
-
-#define         SELECTED_ENDPOINT  0xf        /* selected endpoint */
-
-/* Bit masks for USB_GLOBAL_CTL */
-
-#define                GLOBAL_ENA  0x1        /* enables USB module */
-#define                EP1_TX_ENA  0x2        /* Transmit endpoint 1 enable */
-#define                EP2_TX_ENA  0x4        /* Transmit endpoint 2 enable */
-#define                EP3_TX_ENA  0x8        /* Transmit endpoint 3 enable */
-#define                EP4_TX_ENA  0x10       /* Transmit endpoint 4 enable */
-#define                EP5_TX_ENA  0x20       /* Transmit endpoint 5 enable */
-#define                EP6_TX_ENA  0x40       /* Transmit endpoint 6 enable */
-#define                EP7_TX_ENA  0x80       /* Transmit endpoint 7 enable */
-#define                EP1_RX_ENA  0x100      /* Receive endpoint 1 enable */
-#define                EP2_RX_ENA  0x200      /* Receive endpoint 2 enable */
-#define                EP3_RX_ENA  0x400      /* Receive endpoint 3 enable */
-#define                EP4_RX_ENA  0x800      /* Receive endpoint 4 enable */
-#define                EP5_RX_ENA  0x1000     /* Receive endpoint 5 enable */
-#define                EP6_RX_ENA  0x2000     /* Receive endpoint 6 enable */
-#define                EP7_RX_ENA  0x4000     /* Receive endpoint 7 enable */
-
-/* Bit masks for USB_OTG_DEV_CTL */
-
-#define                   SESSION  0x1        /* session indicator */
-#define                  HOST_REQ  0x2        /* Host negotiation request */
-#define                 HOST_MODE  0x4        /* indicates USBDRC is a host */
-#define                     VBUS0  0x8        /* Vbus level indicator[0] */
-#define                     VBUS1  0x10       /* Vbus level indicator[1] */
-#define                     LSDEV  0x20       /* Low-speed indicator */
-#define                     FSDEV  0x40       /* Full or High-speed indicator */
-#define                  B_DEVICE  0x80       /* A' or 'B' device indicator */
-
-/* Bit masks for USB_OTG_VBUS_IRQ */
-
-#define             DRIVE_VBUS_ON  0x1        /* indicator to drive VBUS control circuit */
-#define            DRIVE_VBUS_OFF  0x2        /* indicator to shut off charge pump */
-#define           CHRG_VBUS_START  0x4        /* indicator for external circuit to start charging VBUS */
-#define             CHRG_VBUS_END  0x8        /* indicator for external circuit to end charging VBUS */
-#define        DISCHRG_VBUS_START  0x10       /* indicator to start discharging VBUS */
-#define          DISCHRG_VBUS_END  0x20       /* indicator to stop discharging VBUS */
-
-/* Bit masks for USB_OTG_VBUS_MASK */
-
-#define         DRIVE_VBUS_ON_ENA  0x1        /* enable DRIVE_VBUS_ON interrupt */
-#define        DRIVE_VBUS_OFF_ENA  0x2        /* enable DRIVE_VBUS_OFF interrupt */
-#define       CHRG_VBUS_START_ENA  0x4        /* enable CHRG_VBUS_START interrupt */
-#define         CHRG_VBUS_END_ENA  0x8        /* enable CHRG_VBUS_END interrupt */
-#define    DISCHRG_VBUS_START_ENA  0x10       /* enable DISCHRG_VBUS_START interrupt */
-#define      DISCHRG_VBUS_END_ENA  0x20       /* enable DISCHRG_VBUS_END interrupt */
-
-/* Bit masks for USB_CSR0 */
-
-#define                  RXPKTRDY  0x1        /* data packet receive indicator */
-#define                  TXPKTRDY  0x2        /* data packet in FIFO indicator */
-#define                STALL_SENT  0x4        /* STALL handshake sent */
-#define                   DATAEND  0x8        /* Data end indicator */
-#define                  SETUPEND  0x10       /* Setup end */
-#define                 SENDSTALL  0x20       /* Send STALL handshake */
-#define         SERVICED_RXPKTRDY  0x40       /* used to clear the RxPktRdy bit */
-#define         SERVICED_SETUPEND  0x80       /* used to clear the SetupEnd bit */
-#define                 FLUSHFIFO  0x100      /* flush endpoint FIFO */
-#define          STALL_RECEIVED_H  0x4        /* STALL handshake received host mode */
-#define                SETUPPKT_H  0x8        /* send Setup token host mode */
-#define                   ERROR_H  0x10       /* timeout error indicator host mode */
-#define                  REQPKT_H  0x20       /* Request an IN transaction host mode */
-#define               STATUSPKT_H  0x40       /* Status stage transaction host mode */
-#define             NAK_TIMEOUT_H  0x80       /* EP0 halted after a NAK host mode */
-
-/* Bit masks for USB_COUNT0 */
-
-#define              EP0_RX_COUNT  0x7f       /* number of received bytes in EP0 FIFO */
-
-/* Bit masks for USB_NAKLIMIT0 */
-
-#define             EP0_NAK_LIMIT  0x1f       /* number of frames/micro frames after which EP0 timeouts */
-
-/* Bit masks for USB_TX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_T  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_RX_MAX_PACKET */
-
-#define         MAX_PACKET_SIZE_R  0x7ff      /* maximum data pay load in a frame */
-
-/* Bit masks for USB_TXCSR */
-
-#define                TXPKTRDY_T  0x1        /* data packet in FIFO indicator */
-#define          FIFO_NOT_EMPTY_T  0x2        /* FIFO not empty */
-#define                UNDERRUN_T  0x4        /* TxPktRdy not set  for an IN token */
-#define               FLUSHFIFO_T  0x8        /* flush endpoint FIFO */
-#define              STALL_SEND_T  0x10       /* issue a Stall handshake */
-#define              STALL_SENT_T  0x20       /* Stall handshake transmitted */
-#define        CLEAR_DATATOGGLE_T  0x40       /* clear endpoint data toggle */
-#define                INCOMPTX_T  0x80       /* indicates that a large packet is split */
-#define              DMAREQMODE_T  0x400      /* DMA mode (0 or 1) selection */
-#define        FORCE_DATATOGGLE_T  0x800      /* Force data toggle */
-#define              DMAREQ_ENA_T  0x1000     /* Enable DMA request for Tx EP */
-#define                     ISO_T  0x4000     /* enable Isochronous transfers */
-#define                 AUTOSET_T  0x8000     /* allows TxPktRdy to be set automatically */
-#define                  ERROR_TH  0x4        /* error condition host mode */
-#define         STALL_RECEIVED_TH  0x20       /* Stall handshake received host mode */
-#define            NAK_TIMEOUT_TH  0x80       /* NAK timeout host mode */
-
-/* Bit masks for USB_TXCOUNT */
-
-#define                  TX_COUNT  0x1fff     /* Number of bytes to be written to the selected endpoint Tx FIFO */
-
-/* Bit masks for USB_RXCSR */
-
-#define                RXPKTRDY_R  0x1        /* data packet in FIFO indicator */
-#define               FIFO_FULL_R  0x2        /* FIFO not empty */
-#define                 OVERRUN_R  0x4        /* TxPktRdy not set  for an IN token */
-#define               DATAERROR_R  0x8        /* Out packet cannot be loaded into Rx  FIFO */
-#define               FLUSHFIFO_R  0x10       /* flush endpoint FIFO */
-#define              STALL_SEND_R  0x20       /* issue a Stall handshake */
-#define              STALL_SENT_R  0x40       /* Stall handshake transmitted */
-#define        CLEAR_DATATOGGLE_R  0x80       /* clear endpoint data toggle */
-#define                INCOMPRX_R  0x100      /* indicates that a large packet is split */
-#define              DMAREQMODE_R  0x800      /* DMA mode (0 or 1) selection */
-#define                 DISNYET_R  0x1000     /* disable Nyet handshakes */
-#define              DMAREQ_ENA_R  0x2000     /* Enable DMA request for Tx EP */
-#define                     ISO_R  0x4000     /* enable Isochronous transfers */
-#define               AUTOCLEAR_R  0x8000     /* allows TxPktRdy to be set automatically */
-#define                  ERROR_RH  0x4        /* TxPktRdy not set  for an IN token host mode */
-#define                 REQPKT_RH  0x20       /* request an IN transaction host mode */
-#define         STALL_RECEIVED_RH  0x40       /* Stall handshake received host mode */
-#define               INCOMPRX_RH  0x100      /* indicates that a large packet is split host mode */
-#define             DMAREQMODE_RH  0x800      /* DMA mode (0 or 1) selection host mode */
-#define                AUTOREQ_RH  0x4000     /* sets ReqPkt automatically host mode */
-
-/* Bit masks for USB_RXCOUNT */
-
-#define                  RX_COUNT  0x1fff     /* Number of received bytes in the packet in the Rx FIFO */
-
-/* Bit masks for USB_TXTYPE */
-
-#define            TARGET_EP_NO_T  0xf        /* EP number */
-#define                PROTOCOL_T  0xc        /* transfer type */
-
-/* Bit masks for USB_TXINTERVAL */
-
-#define          TX_POLL_INTERVAL  0xff       /* polling interval for selected Tx EP */
-
-/* Bit masks for USB_RXTYPE */
-
-#define            TARGET_EP_NO_R  0xf        /* EP number */
-#define                PROTOCOL_R  0xc        /* transfer type */
-
-/* Bit masks for USB_RXINTERVAL */
-
-#define          RX_POLL_INTERVAL  0xff       /* polling interval for selected Rx EP */
-
-/* Bit masks for USB_DMA_INTERRUPT */
-
-#define                  DMA0_INT  0x1        /* DMA0 pending interrupt */
-#define                  DMA1_INT  0x2        /* DMA1 pending interrupt */
-#define                  DMA2_INT  0x4        /* DMA2 pending interrupt */
-#define                  DMA3_INT  0x8        /* DMA3 pending interrupt */
-#define                  DMA4_INT  0x10       /* DMA4 pending interrupt */
-#define                  DMA5_INT  0x20       /* DMA5 pending interrupt */
-#define                  DMA6_INT  0x40       /* DMA6 pending interrupt */
-#define                  DMA7_INT  0x80       /* DMA7 pending interrupt */
-
-/* Bit masks for USB_DMAxCONTROL */
-
-#define                   DMA_ENA  0x1        /* DMA enable */
-#define                 DIRECTION  0x2        /* direction of DMA transfer */
-#define                      MODE  0x4        /* DMA Bus error */
-#define                   INT_ENA  0x8        /* Interrupt enable */
-#define                     EPNUM  0xf0       /* EP number */
-#define                  BUSERROR  0x100      /* DMA Bus error */
-
-/* Bit masks for USB_DMAxADDRHIGH */
-
-#define             DMA_ADDR_HIGH  0xffff     /* Upper 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxADDRLOW */
-
-#define              DMA_ADDR_LOW  0xffff     /* Lower 16-bits of memory source/destination address for the DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTHIGH */
-
-#define            DMA_COUNT_HIGH  0xffff     /* Upper 16-bits of byte count of DMA transfer for DMA master channel */
-
-/* Bit masks for USB_DMAxCOUNTLOW */
-
-#define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
-
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
-/* ************************ */
-/*   MXVR Address Offsets   */
-/* ************************ */
-
-/* Control Message Receive Buffer (CMRB) Address Offsets */
-
-#define CMRB_STRIDE       0x00000016lu
-
-#define CMRB_DST_OFFSET   0x00000000lu
-#define CMRB_SRC_OFFSET   0x00000002lu
-#define CMRB_DATA_OFFSET  0x00000005lu
-
-/* Control Message Transmit Buffer (CMTB) Address Offsets */
-
-#define CMTB_PRIO_OFFSET    0x00000000lu
-#define CMTB_DST_OFFSET     0x00000002lu
-#define CMTB_SRC_OFFSET     0x00000004lu
-#define CMTB_TYPE_OFFSET    0x00000006lu
-#define CMTB_DATA_OFFSET    0x00000007lu
-
-#define CMTB_ANSWER_OFFSET  0x0000000Alu
-
-#define CMTB_STAT_N_OFFSET  0x00000018lu
-#define CMTB_STAT_A_OFFSET  0x00000016lu
-#define CMTB_STAT_D_OFFSET  0x0000000Elu
-#define CMTB_STAT_R_OFFSET  0x00000014lu
-#define CMTB_STAT_W_OFFSET  0x00000014lu
-#define CMTB_STAT_G_OFFSET  0x00000014lu
-
-/* Asynchronous Packet Receive Buffer (APRB) Address Offsets */
-
-#define APRB_STRIDE       0x00000400lu
-
-#define APRB_DST_OFFSET   0x00000000lu
-#define APRB_LEN_OFFSET   0x00000002lu
-#define APRB_SRC_OFFSET   0x00000004lu
-#define APRB_DATA_OFFSET  0x00000006lu
-
-/* Asynchronous Packet Transmit Buffer (APTB) Address Offsets */
-
-#define APTB_PRIO_OFFSET  0x00000000lu
-#define APTB_DST_OFFSET   0x00000002lu
-#define APTB_LEN_OFFSET   0x00000004lu
-#define APTB_SRC_OFFSET   0x00000006lu
-#define APTB_DATA_OFFSET  0x00000008lu
-
-/* Remote Read Buffer (RRDB) Address Offsets */
-
-#define RRDB_WADDR_OFFSET 0x00000100lu
-#define RRDB_WLEN_OFFSET  0x00000101lu
-
-/* **************** */
-/*   MXVR Macros    */
-/* **************** */
-
-/* MXVR_CONFIG Macros */
-
-#define SET_MSB(x)       ( ( (x) & 0xF  ) << 9)
-
-/* MXVR_INT_STAT_1 Macros */
-
-#define DONEX(x)         (0x00000002 << (4 * (x)))
-#define HDONEX(x)        (0x00000001 << (4 * (x)))
-
-/* MXVR_INT_EN_1 Macros */
-
-#define DONEENX(x)       (0x00000002 << (4 * (x)))
-#define HDONEENX(x)      (0x00000001 << (4 * (x)))
-
-/* MXVR_CDRPLL_CTL Macros */
-
-#define SET_CDRSHPSEL(x) ( ( (x) & 0x3F ) << 16)
-
-/* MXVR_FMPLL_CTL Macros */
-
-#define SET_CDRCPSEL(x)  ( ( (x) & 0xFF ) << 24)
-#define SET_FMCPSEL(x)   ( ( (x) & 0xFF ) << 24)
-
 #endif /* _DEF_BF549_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
index 8590c8c..ab04d13 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF54x_base.h
@@ -1609,44 +1609,6 @@
 #define                 PINT2  0x40000000 /* Pin Interrupt 2 */
 #define                 PINT3  0x80000000 /* Pin Interrupt 3 */
 
-/* Bit masks for DMAx_CONFIG, MDMA_Sx_CONFIG, MDMA_Dx_CONFIG */
-
-#define                     DMAEN  0x1        /* DMA Channel Enable */
-#define                       WNR  0x2        /* DMA Direction */
-#define                  WDSIZE_8  0x0        /* Transfer Word Size = 8 */
-#define                 WDSIZE_16  0x4        /* Transfer Word Size = 16 */
-#define                 WDSIZE_32  0x8        /* Transfer Word Size = 32 */
-#define                     DMA2D  0x10       /* DMA Mode */
-#define                   RESTART  0x20       /* Work Unit Transitions */
-#define                    DI_SEL  0x40       /* Data Interrupt Timing Select */
-#define                     DI_EN  0x80       /* Data Interrupt Enable */
-
-#define                    NDSIZE  0xf00      /* Flex Descriptor Size */
-#define                  NDSIZE_0 0x0000      /* Next Descriptor Size = 0 (Stop/Autobuffer) */
-#define                  NDSIZE_1 0x0100      /* Next Descriptor Size = 1 */
-#define                  NDSIZE_2 0x0200      /* Next Descriptor Size = 2 */
-#define                  NDSIZE_3 0x0300      /* Next Descriptor Size = 3 */
-#define                  NDSIZE_4 0x0400      /* Next Descriptor Size = 4 */
-#define                  NDSIZE_5 0x0500      /* Next Descriptor Size = 5 */
-#define                  NDSIZE_6 0x0600      /* Next Descriptor Size = 6 */
-#define                  NDSIZE_7 0x0700      /* Next Descriptor Size = 7 */
-#define                  NDSIZE_8 0x0800      /* Next Descriptor Size = 8 */
-#define                  NDSIZE_9 0x0900      /* Next Descriptor Size = 9 */
-
-#define                   DMAFLOW  0xf000     /* Next Operation */
-#define              DMAFLOW_STOP  0x0000     /* Stop Mode */
-#define              DMAFLOW_AUTO  0x1000     /* Autobuffer Mode */
-#define             DMAFLOW_ARRAY  0x4000     /* Descriptor Array Mode */
-#define             DMAFLOW_SMALL  0x6000     /* Small Model Descriptor List Mode */
-#define             DMAFLOW_LARGE  0x7000     /* Large Model Descriptor List Mode */
-
-/* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
-
-#define                  DMA_DONE  0x1        /* DMA Completion Interrupt Status */
-#define                   DMA_ERR  0x2        /* DMA Error Interrupt Status */
-#define                    DFETCH  0x4        /* DMA Descriptor Fetch */
-#define                   DMA_RUN  0x8        /* DMA Channel Running */
-
 /* Bit masks for DMAx_PERIPHERAL_MAP, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
 
 #define                     CTYPE  0x40       /* DMA Channel Type */
@@ -1815,10 +1777,6 @@
 #define               DEB3_MERROR  0x40       /* DEB3 Error (2nd) */
 #define               CORE_MERROR  0x80       /* Core Error (2nd) */
 
-/* Bit masks for EBIU_ERRADD */
-
-#define             ERROR_ADDRESS  0xffffffff /* Error Address */
-
 /* Bit masks for EBIU_RSTCTL */
 
 #define                 DDRSRESET  0x1        /* DDR soft reset */
@@ -1827,98 +1785,6 @@
 #define                     SRACK  0x10       /* Self-refresh acknowledge */
 #define                MDDRENABLE  0x20       /* Mobile DDR enable */
 
-/* Bit masks for EBIU_DDRBRC0 */
-
-#define                      BRC0  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC1 */
-
-#define                      BRC1  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC2 */
-
-#define                      BRC2  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC3 */
-
-#define                      BRC3  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC4 */
-
-#define                      BRC4  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC5 */
-
-#define                      BRC5  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC6 */
-
-#define                      BRC6  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBRC7 */
-
-#define                      BRC7  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC0 */
-
-#define                      BWC0  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC1 */
-
-#define                      BWC1  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC2 */
-
-#define                      BWC2  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC3 */
-
-#define                      BWC3  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC4 */
-
-#define                      BWC4  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC5 */
-
-#define                      BWC5  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC6 */
-
-#define                      BWC6  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRBWC7 */
-
-#define                      BWC7  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRACCT */
-
-#define                      ACCT  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRTACT */
-
-#define                      TECT  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRARCT */
-
-#define                      ARCT  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRGC0 */
-
-#define                       GC0  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRGC1 */
-
-#define                       GC1  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRGC2 */
-
-#define                       GC2  0xffffffff /* Count */
-
-/* Bit masks for EBIU_DDRGC3 */
-
-#define                       GC3  0xffffffff /* Count */
-
 /* Bit masks for EBIU_DDRMCEN */
 
 #define                B0WCENABLE  0x1        /* Bank 0 write count enable */
@@ -2092,12 +1958,6 @@
 #define                     TRUN6  0x40000000 /* Timer 6 Slave Enable Status */
 #define                     TRUN7  0x80000000 /* Timer 7 Slave Enable Status */
 
-/* Bit masks for WDOG_CTL */
-
-#define                      WDEV  0x6        /* Watchdog Event */
-#define                      WDEN  0xff0      /* Watchdog Enable */
-#define                      WDRO  0x8000     /* Watchdog Rolled Over */
-
 /* Bit masks for CNT_CONFIG */
 
 #define                      CNTE  0x1        /* Counter Enable */
@@ -2149,81 +2009,6 @@
 
 #define                 DPRESCALE  0xf        /* Load Counter Register */
 
-/* Bit masks for RTC_STAT */
-
-#define                   SECONDS  0x3f       /* Seconds */
-#define                   MINUTES  0xfc0      /* Minutes */
-#define                     HOURS  0x1f000    /* Hours */
-#define               DAY_COUNTER  0xfffe0000 /* Day Counter */
-
-/* Bit masks for RTC_ICTL */
-
-#define STOPWATCH_INTERRUPT_ENABLE  0x1        /* Stopwatch Interrupt Enable */
-#define    ALARM_INTERRUPT_ENABLE  0x2        /* Alarm Interrupt Enable */
-#define  SECONDS_INTERRUPT_ENABLE  0x4        /* Seconds Interrupt Enable */
-#define  MINUTES_INTERRUPT_ENABLE  0x8        /* Minutes Interrupt Enable */
-#define    HOURS_INTERRUPT_ENABLE  0x10       /* Hours Interrupt Enable */
-#define TWENTY_FOUR_HOURS_INTERRUPT_ENABLE  0x20       /* 24 Hours Interrupt Enable */
-#define DAY_ALARM_INTERRUPT_ENABLE  0x40       /* Day Alarm Interrupt Enable */
-#define WRITE_COMPLETE_INTERRUPT_ENABLE  0x8000     /* Write Complete Interrupt Enable */
-
-/* Bit masks for RTC_ISTAT */
-
-#define      STOPWATCH_EVENT_FLAG  0x1        /* Stopwatch Event Flag */
-#define          ALARM_EVENT_FLAG  0x2        /* Alarm Event Flag */
-#define        SECONDS_EVENT_FLAG  0x4        /* Seconds Event Flag */
-#define        MINUTES_EVENT_FLAG  0x8        /* Minutes Event Flag */
-#define          HOURS_EVENT_FLAG  0x10       /* Hours Event Flag */
-#define TWENTY_FOUR_HOURS_EVENT_FLAG  0x20       /* 24 Hours Event Flag */
-#define      DAY_ALARM_EVENT_FLAG  0x40       /* Day Alarm Event Flag */
-#define     WRITE_PENDING__STATUS  0x4000     /* Write Pending  Status */
-#define            WRITE_COMPLETE  0x8000     /* Write Complete */
-
-/* Bit masks for RTC_SWCNT */
-
-#define           STOPWATCH_COUNT  0xffff     /* Stopwatch Count */
-
-/* Bit masks for RTC_ALARM */
-
-#define                   SECONDS  0x3f       /* Seconds */
-#define                   MINUTES  0xfc0      /* Minutes */
-#define                     HOURS  0x1f000    /* Hours */
-#define                       DAY  0xfffe0000 /* Day */
-
-/* Bit masks for RTC_PREN */
-
-#define                      PREN  0x1        /* Prescaler Enable */
-
-/* Bit masks for OTP_CONTROL */
-
-#define                FUSE_FADDR  0x1ff      /* OTP/Fuse Address */
-#define                      FIEN  0x800      /* OTP/Fuse Interrupt Enable */
-#define                  FTESTDEC  0x1000     /* OTP/Fuse Test Decoder */
-#define                   FWRTEST  0x2000     /* OTP/Fuse Write Test */
-#define                     FRDEN  0x4000     /* OTP/Fuse Read Enable */
-#define                     FWREN  0x8000     /* OTP/Fuse Write Enable */
-
-/* Bit masks for OTP_BEN */
-
-#define                      FBEN  0xffff     /* OTP/Fuse Byte Enable */
-
-/* Bit masks for OTP_STATUS */
-
-#define                     FCOMP  0x1        /* OTP/Fuse Access Complete */
-#define                    FERROR  0x2        /* OTP/Fuse Access Error */
-#define                  MMRGLOAD  0x10       /* Memory Mapped Register Gasket Load */
-#define                  MMRGLOCK  0x20       /* Memory Mapped Register Gasket Lock */
-#define                    FPGMEN  0x40       /* OTP/Fuse Program Enable */
-
-/* Bit masks for OTP_TIMING */
-
-#define                   USECDIV  0xff       /* Micro Second Divider */
-#define                   READACC  0x7f00     /* Read Access Time */
-#define                   CPUMPRL  0x38000    /* Charge Pump Release Time */
-#define                   CPUMPSU  0xc0000    /* Charge Pump Setup Time */
-#define                   CPUMPHD  0xf00000   /* Charge Pump Hold Time */
-#define                   PGMTIME  0xff000000 /* Program Time */
-
 /* Bit masks for SECURE_SYSSWT */
 
 #define                   EMUDABL  0x1        /* Emulation Disable. */
@@ -2252,26 +2037,6 @@
 #define                    AFEXIT  0x10       /* Authentication Firmware Exit */
 #define                   SECSTAT  0xe0       /* Secure Status */
 
-/* Bit masks for PLL_DIV */
-
-#define                      CSEL  0x30       /* Core Select */
-#define                      SSEL  0xf        /* System Select */
-#define			CSEL_DIV1	0x0000	/* CCLK = VCO / 1 */
-#define			CSEL_DIV2	0x0010	/* CCLK = VCO / 2 */
-#define			CSEL_DIV4	0x0020	/* CCLK = VCO / 4 */
-#define			CSEL_DIV8	0x0030	/* CCLK = VCO / 8 */
-
-/* Bit masks for PLL_CTL */
-
-#define                      MSEL  0x7e00     /* Multiplier Select */
-#define                    BYPASS  0x100      /* PLL Bypass Enable */
-#define              OUTPUT_DELAY  0x80       /* External Memory Output Delay Enable */
-#define               INPUT_DELAY  0x40       /* External Memory Input Delay Enable */
-#define                      PDWN  0x20       /* Power Down */
-#define                    STOPCK  0x8        /* Stop Clock */
-#define                   PLL_OFF  0x2        /* Disable PLL */
-#define                        DF  0x1        /* Divide Frequency */
-
 /* SWRST Masks */
 #define              SYSTEM_RESET 0x0007       /* Initiates A System Software Reset */
 #define              DOUBLE_FAULT 0x0008       /* Core Double Fault Causes Reset */
@@ -2279,52 +2044,6 @@
 #define                RESET_WDOG 0x4000       /* SW Reset Generated By Watchdog Timer */
 #define            RESET_SOFTWARE 0x8000       /* SW Reset Occurred Since Last Read Of SWRST */
 
-/* Bit masks for PLL_STAT */
-
-#define                PLL_LOCKED  0x20       /* PLL Locked Status */
-#define        ACTIVE_PLLDISABLED  0x4        /* Active Mode With PLL Disabled */
-#define                   FULL_ON  0x2        /* Full-On Mode */
-#define         ACTIVE_PLLENABLED  0x1        /* Active Mode With PLL Enabled */
-#define                     RTCWS  0x400      /* RTC/Reset Wake-Up Status */
-#define                     CANWS  0x800      /* CAN Wake-Up Status */
-#define                     USBWS  0x2000     /* USB Wake-Up Status */
-#define                    KPADWS  0x4000     /* Keypad Wake-Up Status */
-#define                     ROTWS  0x8000     /* Rotary Wake-Up Status */
-#define                      GPWS  0x1000     /* General-Purpose Wake-Up Status */
-
-/* Bit masks for VR_CTL */
-
-#define                      FREQ  0x3        /* Regulator Switching Frequency */
-#define                      GAIN  0xc        /* Voltage Output Level Gain */
-#define                      VLEV  0xf0       /* Internal Voltage Level */
-#define                   SCKELOW  0x8000     /* Drive SCKE Low During Reset Enable */
-#define                      WAKE  0x100      /* RTC/Reset Wake-Up Enable */
-#define                     CANWE  0x200      /* CAN0/1 Wake-Up Enable */
-#define                      GPWE  0x400      /* General-Purpose Wake-Up Enable */
-#define                     USBWE  0x800      /* USB Wake-Up Enable */
-#define                    KPADWE  0x1000     /* Keypad Wake-Up Enable */
-#define                     ROTWE  0x2000     /* Rotary Wake-Up Enable */
-
-#define	FREQ_333		0x0001	/* Switching Frequency Is 333 kHz */
-#define	FREQ_667		0x0002	/* Switching Frequency Is 667 kHz */
-#define	FREQ_1000		0x0003	/* Switching Frequency Is 1 MHz */
-
-#define	GAIN_5			0x0000	/* GAIN = 5*/
-#define	GAIN_10			0x0004	/* GAIN = 1*/
-#define	GAIN_20			0x0008	/* GAIN = 2*/
-#define	GAIN_50			0x000C	/* GAIN = 5*/
-
-#define	VLEV_085 		0x0060	/* VLEV = 0.85 V (-5% - +10% Accuracy) */
-#define	VLEV_090		0x0070	/* VLEV = 0.90 V (-5% - +10% Accuracy) */
-#define	VLEV_095		0x0080	/* VLEV = 0.95 V (-5% - +10% Accuracy) */
-#define	VLEV_100		0x0090	/* VLEV = 1.00 V (-5% - +10% Accuracy) */
-#define	VLEV_105		0x00A0	/* VLEV = 1.05 V (-5% - +10% Accuracy) */
-#define	VLEV_110		0x00B0	/* VLEV = 1.10 V (-5% - +10% Accuracy) */
-#define	VLEV_115		0x00C0	/* VLEV = 1.15 V (-5% - +10% Accuracy) */
-#define	VLEV_120		0x00D0	/* VLEV = 1.20 V (-5% - +10% Accuracy) */
-#define	VLEV_125		0x00E0	/* VLEV = 1.25 V (-5% - +10% Accuracy) */
-#define	VLEV_130		0x00F0	/* VLEV = 1.30 V (-5% - +10% Accuracy) */
-
 /* Bit masks for NFC_CTL */
 
 #define                    WR_DLY  0xf        /* Write Strobe Delay */
@@ -2489,14 +2208,6 @@
 #define                      UCCT  0x40       /* Universal Counter CAN Trigger */
 #define                       UCE  0x80       /* Universal Counter Enable */
 
-/* Bit masks for CAN0_UCCNT */
-
-#define                     UCCNT  0xffff     /* Universal Counter Count Value */
-
-/* Bit masks for CAN0_UCRC */
-
-#define                     UCVAL  0xffff     /* Universal Counter Reload/Capture Value */
-
 /* Bit masks for CAN0_CEC */
 
 #define                    RXECNT  0xff       /* Receive Error Counter */
diff --git a/arch/blackfin/mach-bf561/boards/Kconfig b/arch/blackfin/mach-bf561/boards/Kconfig
index e4bc6d7..1aa529b 100644
--- a/arch/blackfin/mach-bf561/boards/Kconfig
+++ b/arch/blackfin/mach-bf561/boards/Kconfig
@@ -19,4 +19,11 @@
 	help
 	  CM-BF561 support for EVAL- and DEV-Board.
 
+config BFIN561_ACVILON
+	bool "BF561-ACVILON"
+	help
+	  BF561-ACVILON System On Module support (SO-DIMM 144).
+	  For more information about Acvilon BF561 SoM
+	  please go to http://www.niistt.ru/
+
 endchoice
diff --git a/arch/blackfin/mach-bf561/boards/Makefile b/arch/blackfin/mach-bf561/boards/Makefile
index 3a15255..a5879f7 100644
--- a/arch/blackfin/mach-bf561/boards/Makefile
+++ b/arch/blackfin/mach-bf561/boards/Makefile
@@ -2,6 +2,7 @@
 # arch/blackfin/mach-bf561/boards/Makefile
 #
 
+obj-$(CONFIG_BFIN561_ACVILON)          += acvilon.o
 obj-$(CONFIG_BFIN561_BLUETECHNIX_CM)   += cm_bf561.o
 obj-$(CONFIG_BFIN561_EZKIT)            += ezkit.o
 obj-$(CONFIG_BFIN561_TEPLA)            += tepla.o
diff --git a/arch/blackfin/mach-bf561/boards/acvilon.c b/arch/blackfin/mach-bf561/boards/acvilon.c
new file mode 100644
index 0000000..07e8dc8
--- /dev/null
+++ b/arch/blackfin/mach-bf561/boards/acvilon.c
@@ -0,0 +1,551 @@
+/*
+ * File:         arch/blackfin/mach-bf561/acvilon.c
+ * Based on:     arch/blackfin/mach-bf561/ezkit.c
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ *               Copyright 2004-2006 Analog Devices Inc.
+ *               Copyright 2009 CJSC "NII STT"
+ *
+ * Bugs:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *
+ * For more information about Acvilon BF561 SoM please
+ * go to http://www.niistt.ru/
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-pca-platform.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+#include <asm/cacheflush.h>
+#include <linux/i2c.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "Acvilon board";
+
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
+	[0] = {
+	       .start = 0x20000000,
+	       .end = 0x20000000 + 0x000fffff,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = IRQ_PF15,
+	       .end = IRQ_PF15,
+	       .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	       },
+};
+
+static struct isp1760_platform_data isp1760_priv = {
+	.is_isp1761 = 0,
+	.port1_disable = 0,
+	.bus_width_16 = 1,
+	.port1_otg = 0,
+	.analog_oc = 0,
+	.dack_polarity_high = 0,
+	.dreq_polarity_high = 0,
+};
+
+static struct platform_device bfin_isp1760_device = {
+	.name = "isp1760-hcd",
+	.id = 0,
+	.dev = {
+		.platform_data = &isp1760_priv,
+		},
+	.num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+	.resource = bfin_isp1760_resources,
+};
+#endif
+
+static struct resource bfin_i2c_pca_resources[] = {
+	{
+	 .name = "pca9564-regs",
+	 .start = 0x2C000000,
+	 .end = 0x2C000000 + 16,
+	 .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+	 }, {
+
+	     .start = IRQ_PF8,
+	     .end = IRQ_PF8,
+	     .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	     },
+};
+
+struct i2c_pca9564_pf_platform_data pca9564_platform_data = {
+	.gpio = -1,
+	.i2c_clock_speed = 330000,
+	.timeout = 10000
+};
+
+/* PCA9564 I2C Bus driver */
+static struct platform_device bfin_i2c_pca_device = {
+	.name = "i2c-pca-platform",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_i2c_pca_resources),
+	.resource = bfin_i2c_pca_resources,
+	.dev = {
+		.platform_data = &pca9564_platform_data,
+		}
+};
+
+/* I2C devices fitted. */
+static struct i2c_board_info acvilon_i2c_devs[] __initdata = {
+	{
+	 I2C_BOARD_INFO("ds1339", 0x68),
+	 },
+	{
+	 I2C_BOARD_INFO("tcn75", 0x49),
+	 },
+};
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+static struct platdata_mtd_ram mtd_ram_data = {
+	.mapname = "rootfs(RAM)",
+	.bankwidth = 4,
+};
+
+static struct resource mtd_ram_resource = {
+	.start = 0x4000000,
+	.end = 0x5ffffff,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct platform_device mtd_ram_device = {
+	.name = "mtd-ram",
+	.id = 0,
+	.dev = {
+		.platform_data = &mtd_ram_data,
+		},
+	.num_resources = 1,
+	.resource = &mtd_ram_resource,
+};
+#endif
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+#include <linux/smsc911x.h>
+static struct resource smsc911x_resources[] = {
+	{
+	 .name = "smsc911x-memory",
+	 .start = 0x28000000,
+	 .end = 0x28000000 + 0xFF,
+	 .flags = IORESOURCE_MEM,
+	 },
+	{
+	 .start = IRQ_PF7,
+	 .end = IRQ_PF7,
+	 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
+	 },
+};
+
+static struct smsc911x_platform_config smsc911x_config = {
+	.flags = SMSC911X_USE_32BIT,
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+static struct platform_device smsc911x_device = {
+	.name = "smsc911x",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(smsc911x_resources),
+	.resource = smsc911x_resources,
+	.dev = {
+		.platform_data = &smsc911x_config,
+		},
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+static struct resource bfin_uart0_resources[] = {
+	{
+	 .start = BFIN_UART_THR,
+	 .end = BFIN_UART_GCTL + 2,
+	 .flags = IORESOURCE_MEM,
+	 },
+	{
+	 .start = IRQ_UART_RX,
+	 .end = IRQ_UART_RX + 1,
+	 .flags = IORESOURCE_IRQ,
+	 },
+	{
+	 .start = IRQ_UART_ERROR,
+	 .end = IRQ_UART_ERROR,
+	 .flags = IORESOURCE_IRQ,
+	 },
+	{
+	 .start = CH_UART_TX,
+	 .end = CH_UART_TX,
+	 .flags = IORESOURCE_DMA,
+	 },
+	{
+	 .start = CH_UART_RX,
+	 .end = CH_UART_RX,
+	 .flags = IORESOURCE_DMA,
+	 },
+};
+
+unsigned short bfin_uart0_peripherals[] = {
+	P_UART0_TX, P_UART0_RX, 0
+};
+
+static struct platform_device bfin_uart0_device = {
+	.name = "bfin-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_uart0_resources),
+	.resource = bfin_uart0_resources,
+	.dev = {
+		/* Passed to driver */
+		.platform_data = &bfin_uart0_peripherals,
+		},
+};
+#endif
+#endif
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition bfin_plat_nand_partitions[] = {
+	{
+	 .name = "params(nand)",
+	 .size = 32 * 1024 * 1024,
+	 .offset = 0,
+	 }, {
+	     .name = "userfs(nand)",
+	     .size = MTDPART_SIZ_FULL,
+	     .offset = MTDPART_OFS_APPEND,
+	     },
+};
+#endif
+
+#define BFIN_NAND_PLAT_CLE 2
+#define BFIN_NAND_PLAT_ALE 3
+
+static void bfin_plat_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				    unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_CLE));
+	else
+		writeb(cmd, this->IO_ADDR_W + (1 << BFIN_NAND_PLAT_ALE));
+}
+
+#define BFIN_NAND_PLAT_READY GPIO_PF10
+static int bfin_plat_nand_dev_ready(struct mtd_info *mtd)
+{
+	return gpio_get_value(BFIN_NAND_PLAT_READY);
+}
+
+static struct platform_nand_data bfin_plat_nand_data = {
+	.chip = {
+		 .chip_delay = 30,
+#ifdef CONFIG_MTD_PARTITIONS
+		 .part_probe_types = part_probes,
+		 .partitions = bfin_plat_nand_partitions,
+		 .nr_partitions = ARRAY_SIZE(bfin_plat_nand_partitions),
+#endif
+		 },
+	.ctrl = {
+		 .cmd_ctrl = bfin_plat_nand_cmd_ctrl,
+		 .dev_ready = bfin_plat_nand_dev_ready,
+		 },
+};
+
+#define MAX(x, y) (x > y ? x : y)
+static struct resource bfin_plat_nand_resources = {
+	.start = 0x24000000,
+	.end = 0x24000000 + (1 << MAX(BFIN_NAND_PLAT_CLE, BFIN_NAND_PLAT_ALE)),
+	.flags = IORESOURCE_IO,
+};
+
+static struct platform_device bfin_async_nand_device = {
+	.name = "gen_nand",
+	.id = -1,
+	.num_resources = 1,
+	.resource = &bfin_plat_nand_resources,
+	.dev = {
+		.platform_data = &bfin_plat_nand_data,
+		},
+};
+
+static void bfin_plat_nand_init(void)
+{
+	gpio_request(BFIN_NAND_PLAT_READY, "bfin_nand_plat");
+}
+#else
+static void bfin_plat_nand_init(void)
+{
+}
+#endif
+
+#if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
+static struct mtd_partition bfin_spi_dataflash_partitions[] = {
+	{
+	 .name = "bootloader",
+	 .size = 0x4200,
+	 .offset = 0,
+	 .mask_flags = MTD_CAP_ROM},
+	{
+	 .name = "u-boot",
+	 .size = 0x42000,
+	 .offset = MTDPART_OFS_APPEND,
+	 },
+	{
+	 .name = "u-boot(params)",
+	 .size = 0x4200,
+	 .offset = MTDPART_OFS_APPEND,
+	 },
+	{
+	 .name = "kernel",
+	 .size = 0x294000,
+	 .offset = MTDPART_OFS_APPEND,
+	 },
+	{
+	 .name = "params",
+	 .size = 0x42000,
+	 .offset = MTDPART_OFS_APPEND,
+	 },
+	{
+	 .name = "rootfs",
+	 .size = MTDPART_SIZ_FULL,
+	 .offset = MTDPART_OFS_APPEND,
+	 }
+};
+
+static struct flash_platform_data bfin_spi_dataflash_data = {
+	.name = "SPI Dataflash",
+	.parts = bfin_spi_dataflash_partitions,
+	.nr_parts = ARRAY_SIZE(bfin_spi_dataflash_partitions),
+};
+
+/* DataFlash chip */
+static struct bfin5xx_spi_chip data_flash_chip_info = {
+	.enable_dma = 0,	/* use dma transfer with this chip */
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+	.enable_dma = 0,
+	.bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+	[0] = {
+	       .start = SPI0_REGBASE,
+	       .end = SPI0_REGBASE + 0xFF,
+	       .flags = IORESOURCE_MEM,
+	       },
+	[1] = {
+	       .start = CH_SPI,
+	       .end = CH_SPI,
+	       .flags = IORESOURCE_DMA,
+	       },
+	[2] = {
+	       .start = IRQ_SPI,
+	       .end = IRQ_SPI,
+	       .flags = IORESOURCE_IRQ,
+	       },
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+	.num_chipselect = 8,
+	.enable_dma = 1,	/* master has the ability to do dma transfer */
+	.pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct platform_device bfin_spi0_device = {
+	.name = "bfin-spi",
+	.id = 0,		/* Bus number */
+	.num_resources = ARRAY_SIZE(bfin_spi0_resource),
+	.resource = bfin_spi0_resource,
+	.dev = {
+		.platform_data = &bfin_spi0_info,	/* Passed to driver */
+		},
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+	{
+	 .modalias = "spidev",
+	 .max_speed_hz = 3125000,	/* max spi clock (SCK) speed in HZ */
+	 .bus_num = 0,
+	 .chip_select = 3,
+	 .controller_data = &spidev_chip_info,
+	 },
+#endif
+#if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
+	{			/* DataFlash chip */
+	 .modalias = "mtd_dataflash",
+	 .max_speed_hz = 33250000,	/* max spi clock (SCK) speed in HZ */
+	 .bus_num = 0,		/* Framework bus number */
+	 .chip_select = 2,	/* Framework chip select */
+	 .platform_data = &bfin_spi_dataflash_data,
+	 .controller_data = &data_flash_chip_info,
+	 .mode = SPI_MODE_3,
+	 },
+#endif
+};
+
+static struct resource bfin_gpios_resources = {
+	.start = 31,
+/*      .end   = MAX_BLACKFIN_GPIOS - 1, */
+	.end = 32,
+	.flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+	.name = "simple-gpio",
+	.id = -1,
+	.num_resources = 1,
+	.resource = &bfin_gpios_resources,
+};
+
+static const unsigned int cclk_vlev_datasheet[] = {
+	VRPAIR(VLEV_085, 250000000),
+	VRPAIR(VLEV_090, 300000000),
+	VRPAIR(VLEV_095, 313000000),
+	VRPAIR(VLEV_100, 350000000),
+	VRPAIR(VLEV_105, 400000000),
+	VRPAIR(VLEV_110, 444000000),
+	VRPAIR(VLEV_115, 450000000),
+	VRPAIR(VLEV_120, 475000000),
+	VRPAIR(VLEV_125, 500000000),
+	VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+	.tuple_tab = cclk_vlev_datasheet,
+	.tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+	.vr_settling_time = 25 /* us */ ,
+};
+
+static struct platform_device bfin_dpmc = {
+	.name = "bfin dpmc",
+	.dev = {
+		.platform_data = &bfin_dmpc_vreg_data,
+		},
+};
+
+static struct platform_device *acvilon_devices[] __initdata = {
+	&bfin_dpmc,
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+	&bfin_spi0_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#endif
+
+	&bfin_gpios_device,
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+	&smsc911x_device,
+#endif
+
+	&bfin_i2c_pca_device,
+
+#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+	&bfin_async_nand_device,
+#endif
+
+#if defined(CONFIG_MTD_PLATRAM) || defined(CONFIG_MTD_PLATRAM_MODULE)
+	&mtd_ram_device,
+#endif
+
+};
+
+static int __init acvilon_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "%s(): registering device resources\n", __func__);
+
+	bfin_plat_nand_init();
+	ret =
+	    platform_add_devices(acvilon_devices, ARRAY_SIZE(acvilon_devices));
+	if (ret < 0)
+		return ret;
+
+	i2c_register_board_info(0, acvilon_i2c_devs,
+				ARRAY_SIZE(acvilon_i2c_devs));
+
+	bfin_write_FIO0_FLAG_C(1 << 14);
+	msleep(5);
+	bfin_write_FIO0_FLAG_S(1 << 14);
+
+	spi_register_board_info(bfin_spi_board_info,
+				ARRAY_SIZE(bfin_spi_board_info));
+	return 0;
+}
+
+arch_initcall(acvilon_init);
+
+static struct platform_device *acvilon_early_devices[] __initdata = {
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+#ifdef CONFIG_SERIAL_BFIN_UART0
+	&bfin_uart0_device,
+#endif
+#endif
+};
+
+void __init native_machine_early_platform_add_devices(void)
+{
+	printk(KERN_INFO "register early platform devices\n");
+	early_platform_add_devices(acvilon_early_devices,
+				   ARRAY_SIZE(acvilon_early_devices));
+}
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 9e2d8cf..ffd3e6a 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -49,7 +49,7 @@
 };
 
 static struct platform_device bfin_isp1760_device = {
-	.name           = "isp1760-hcd",
+	.name           = "isp1760",
 	.id             = 0,
 	.dev = {
 		.platform_data = &isp1760_priv,
@@ -159,28 +159,6 @@
 };
 #endif
 
-#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE)
-static struct resource ax88180_resources[] = {
-	[0] = {
-		.start	= 0x2c000000,
-		.end	= 0x2c000000 + 0x8000,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PF10,
-		.end	= IRQ_PF10,
-		.flags	= (IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL),
-	},
-};
-
-static struct platform_device ax88180_device = {
-	.name		= "ax88180",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(ax88180_resources),
-	.resource	= ax88180_resources,
-};
-#endif
-
 #if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
 static struct resource bfin_uart_resources[] = {
 	{
@@ -421,10 +399,6 @@
 	&smc91x_device,
 #endif
 
-#if defined(CONFIG_AX88180) || defined(CONFIG_AX88180_MODULE)
-	&ax88180_device,
-#endif
-
 #if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE)
 	&net2272_bfin_device,
 #endif
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index 1e60a92..deb2271 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -22,8 +22,8 @@
 #define CMD_COREB_STOP		3
 #define CMD_COREB_RESET		4
 
-static int
-coreb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+coreb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int ret = 0;
 
@@ -49,8 +49,8 @@
 }
 
 static const struct file_operations coreb_fops = {
-	.owner   = THIS_MODULE,
-	.ioctl   = coreb_ioctl,
+	.owner          = THIS_MODULE,
+	.unlocked_ioctl = coreb_ioctl,
 };
 
 static struct miscdevice coreb_dev = {
diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h
index a31e509..4c8e36b 100644
--- a/arch/blackfin/mach-bf561/include/mach/defBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h
@@ -884,65 +884,11 @@
 /* System MMR Register Bits */
 /******************************************************************************* */
 
-/* ********************* PLL AND RESET MASKS ************************ */
-
-/* PLL_CTL Masks */
-#define PLL_CLKIN              0x00000000	/* Pass CLKIN to PLL */
-#define PLL_CLKIN_DIV2         0x00000001	/* Pass CLKIN/2 to PLL */
-#define PLL_OFF                0x00000002	/* Shut off PLL clocks */
-#define STOPCK_OFF             0x00000008	/* Core clock off */
-#define PDWN                   0x00000020	/* Put the PLL in a Deep Sleep state */
-#define BYPASS                 0x00000100	/* Bypass the PLL */
-
 /* CHIPID Masks */
 #define CHIPID_VERSION         0xF0000000
 #define CHIPID_FAMILY          0x0FFFF000
 #define CHIPID_MANUFACTURE     0x00000FFE
 
-/* VR_CTL Masks																	*/
-#define	FREQ			0x0003	/* Switching Oscillator Frequency For Regulator	*/
-#define	HIBERNATE		0x0000	/* Powerdown/Bypass On-Board Regulation	*/
-#define	FREQ_333		0x0001	/* Switching Frequency Is 333 kHz */
-#define	FREQ_667		0x0002	/* Switching Frequency Is 667 kHz */
-#define	FREQ_1000		0x0003	/* Switching Frequency Is 1 MHz */
-
-#define	GAIN			0x000C	/* Voltage Level Gain	*/
-#define	GAIN_5			0x0000	/* GAIN = 5*/
-#define	GAIN_10			0x0004	/* GAIN = 1*/
-#define	GAIN_20			0x0008	/* GAIN = 2*/
-#define	GAIN_50			0x000C	/* GAIN = 5*/
-
-#define	VLEV			0x00F0	/* Internal Voltage Level */
-#define	VLEV_085 		0x0060	/* VLEV = 0.85 V (-5% - +10% Accuracy) */
-#define	VLEV_090		0x0070	/* VLEV = 0.90 V (-5% - +10% Accuracy) */
-#define	VLEV_095		0x0080	/* VLEV = 0.95 V (-5% - +10% Accuracy) */
-#define	VLEV_100		0x0090	/* VLEV = 1.00 V (-5% - +10% Accuracy) */
-#define	VLEV_105		0x00A0	/* VLEV = 1.05 V (-5% - +10% Accuracy) */
-#define	VLEV_110		0x00B0	/* VLEV = 1.10 V (-5% - +10% Accuracy) */
-#define	VLEV_115		0x00C0	/* VLEV = 1.15 V (-5% - +10% Accuracy) */
-#define	VLEV_120		0x00D0	/* VLEV = 1.20 V (-5% - +10% Accuracy) */
-#define	VLEV_125		0x00E0	/* VLEV = 1.25 V (-5% - +10% Accuracy) */
-#define	VLEV_130		0x00F0	/* VLEV = 1.30 V (-5% - +10% Accuracy) */
-
-#define	WAKE			0x0100	/* Enable RTC/Reset Wakeup From Hibernate */
-#define	SCKELOW			0x8000	/* Do Not Drive SCKE High During Reset After Hibernate */
-
-/* PLL_DIV Masks */
-#define SCLK_DIV(x)  (x)	/* SCLK = VCO / x */
-
-#define CSEL			0x30		/* Core Select */
-#define SSEL			0xf		/* System Select */
-#define CCLK_DIV1              0x00000000	/* CCLK = VCO / 1 */
-#define CCLK_DIV2              0x00000010	/* CCLK = VCO / 2 */
-#define CCLK_DIV4              0x00000020	/* CCLK = VCO / 4 */
-#define CCLK_DIV8              0x00000030	/* CCLK = VCO / 8 */
-
-/* PLL_STAT Masks																	*/
-#define ACTIVE_PLLENABLED	0x0001	/* Processor In Active Mode With PLL Enabled    */
-#define	FULL_ON				0x0002	/* Processor In Full On Mode                                    */
-#define ACTIVE_PLLDISABLED	0x0004	/* Processor In Active Mode With PLL Disabled   */
-#define	PLL_LOCKED			0x0020	/* PLL_LOCKCNT Has Been Reached                                 */
-
 /* SICA_SYSCR Masks */
 #define COREB_SRAM_INIT		0x0020
 
@@ -1150,53 +1096,6 @@
 
 /* **********  DMA CONTROLLER MASKS  *********************8 */
 
-/* DMAx_CONFIG, MDMA_yy_CONFIG, IMDMA_yy_CONFIG Masks */
-#define DMAEN	        0x00000001	/* Channel Enable */
-#define WNR	   	0x00000002	/* Channel Direction (W/R*) */
-#define WDSIZE_8	0x00000000	/* Word Size 8 bits */
-#define WDSIZE_16	0x00000004	/* Word Size 16 bits */
-#define WDSIZE_32	0x00000008	/* Word Size 32 bits */
-#define DMA2D	        0x00000010	/* 2D/1D* Mode */
-#define RESTART         0x00000020	/* Restart */
-#define DI_SEL	        0x00000040	/* Data Interrupt Select */
-#define DI_EN	        0x00000080	/* Data Interrupt Enable */
-#define NDSIZE_0		0x0000	/* Next Descriptor Size = 0 (Stop/Autobuffer)   */
-#define NDSIZE_1		0x0100	/* Next Descriptor Size = 1                                             */
-#define NDSIZE_2		0x0200	/* Next Descriptor Size = 2                                             */
-#define NDSIZE_3		0x0300	/* Next Descriptor Size = 3                                             */
-#define NDSIZE_4		0x0400	/* Next Descriptor Size = 4                                             */
-#define NDSIZE_5		0x0500	/* Next Descriptor Size = 5                                             */
-#define NDSIZE_6		0x0600	/* Next Descriptor Size = 6                                             */
-#define NDSIZE_7		0x0700	/* Next Descriptor Size = 7                                             */
-#define NDSIZE_8		0x0800	/* Next Descriptor Size = 8                                             */
-#define NDSIZE_9		0x0900	/* Next Descriptor Size = 9                                             */
-#define NDSIZE	        0x00000900	/* Next Descriptor Size */
-#define DMAFLOW	        0x00007000	/* Flow Control */
-#define DMAFLOW_STOP		0x0000	/* Stop Mode */
-#define DMAFLOW_AUTO		0x1000	/* Autobuffer Mode */
-#define DMAFLOW_ARRAY		0x4000	/* Descriptor Array Mode */
-#define DMAFLOW_SMALL		0x6000	/* Small Model Descriptor List Mode */
-#define DMAFLOW_LARGE		0x7000	/* Large Model Descriptor List Mode */
-
-#define DMAEN_P	            	0	/* Channel Enable */
-#define WNR_P	            	1	/* Channel Direction (W/R*) */
-#define DMA2D_P	        	4	/* 2D/1D* Mode */
-#define RESTART_P	      	5	/* Restart */
-#define DI_SEL_P	     	6	/* Data Interrupt Select */
-#define DI_EN_P	            	7	/* Data Interrupt Enable */
-
-/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS, IMDMA_yy_IRQ_STATUS Masks */
-
-#define DMA_DONE		0x00000001	/* DMA Done Indicator */
-#define DMA_ERR	        	0x00000002	/* DMA Error Indicator */
-#define DFETCH	            	0x00000004	/* Descriptor Fetch Indicator */
-#define DMA_RUN	            	0x00000008	/* DMA Running Indicator */
-
-#define DMA_DONE_P	    	0	/* DMA Done Indicator */
-#define DMA_ERR_P     		1	/* DMA Error Indicator */
-#define DFETCH_P     		2	/* Descriptor Fetch Indicator */
-#define DMA_RUN_P     		3	/* DMA Running Indicator */
-
 /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP, IMDMA_yy_PERIPHERAL_MAP Masks */
 
 #define CTYPE	            0x00000040	/* DMA Channel Type Indicator */
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 510f576..0192532 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -52,8 +52,6 @@
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-	local_irq_disable();
-
 	/* Clone setup for peripheral interrupt sources from CoreA. */
 	bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
 	bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
@@ -70,11 +68,6 @@
 	bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
 	SSYNC();
 
-	local_irq_enable();
-
-	/* Calibrate loops per jiffy value. */
-	calibrate_delay();
-
 	/* Store CPU-private information to the cpu_data array. */
 	bfin_setup_cpudata(cpu);
 
@@ -108,9 +101,13 @@
 		barrier();
 	}
 
-	spin_unlock(&boot_lock);
-
-	return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS;
+	if (cpu_isset(cpu, cpu_callin_map)) {
+		cpu_set(cpu, cpu_online_map);
+		/* release the lock and let coreb run */
+		spin_unlock(&boot_lock);
+		return 0;
+	} else
+		panic("CPU%u: processor failed to boot\n", cpu);
 }
 
 void __init platform_request_ipi(irq_handler_t handler)
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
index ef6870e..d5cfe61 100644
--- a/arch/blackfin/mach-common/clocks-init.c
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -13,6 +13,7 @@
 #include <asm/dma.h>
 #include <asm/clocks.h>
 #include <asm/mem_init.h>
+#include <asm/dpmc.h>
 
 #define SDGCTL_WIDTH (1 << 31)	/* SDRAM external data path width */
 #define PLL_CTL_VAL \
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index 0150650..7775828 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -13,7 +13,7 @@
 #include <linux/fs.h>
 #include <asm/blackfin.h>
 #include <asm/time.h>
-
+#include <asm/dpmc.h>
 
 /* this is the table of CCLK frequencies, in Hz */
 /* .index is the entry in the auxillary dpm_state_table[] */
@@ -138,7 +138,8 @@
 						 dpm_state_table[index].tscale);
 	}
 
-	policy->cpuinfo.transition_latency = (bfin_read_PLL_LOCKCNT() / (sclk / 1000000)) * 1000;
+	policy->cpuinfo.transition_latency = 50000; /* 50us assumed */
+
 	/*Now ,only support one cpu */
 	policy->cur = cclk;
 	cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index 8009a51..b037168 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -404,6 +404,21 @@
 	PM_SYS_PUSH(EBIU_FCTL)
 #endif
 
+#ifdef PORTCIO_FER
+	PM_SYS_PUSH16(PORTCIO_DIR)
+	PM_SYS_PUSH16(PORTCIO_INEN)
+	PM_SYS_PUSH16(PORTCIO)
+	PM_SYS_PUSH16(PORTCIO_FER)
+	PM_SYS_PUSH16(PORTDIO_DIR)
+	PM_SYS_PUSH16(PORTDIO_INEN)
+	PM_SYS_PUSH16(PORTDIO)
+	PM_SYS_PUSH16(PORTDIO_FER)
+	PM_SYS_PUSH16(PORTEIO_DIR)
+	PM_SYS_PUSH16(PORTEIO_INEN)
+	PM_SYS_PUSH16(PORTEIO)
+	PM_SYS_PUSH16(PORTEIO_FER)
+#endif
+
 	PM_SYS_PUSH16(SYSCR)
 
 	/* Save Core MMRs */
@@ -716,6 +731,21 @@
 	P0.L = lo(PLL_CTL);
 	PM_SYS_POP16(SYSCR)
 
+#ifdef PORTCIO_FER
+	PM_SYS_POP16(PORTEIO_FER)
+	PM_SYS_POP16(PORTEIO)
+	PM_SYS_POP16(PORTEIO_INEN)
+	PM_SYS_POP16(PORTEIO_DIR)
+	PM_SYS_POP16(PORTDIO_FER)
+	PM_SYS_POP16(PORTDIO)
+	PM_SYS_POP16(PORTDIO_INEN)
+	PM_SYS_POP16(PORTDIO_DIR)
+	PM_SYS_POP16(PORTCIO_FER)
+	PM_SYS_POP16(PORTCIO)
+	PM_SYS_POP16(PORTCIO_INEN)
+	PM_SYS_POP16(PORTCIO_DIR)
+#endif
+
 #ifdef EBIU_FCTL
 	PM_SYS_POP(EBIU_FCTL)
 	PM_SYS_POP(EBIU_MODE)
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index f3f8bb4..b0ed0b4 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -713,6 +713,8 @@
 	cc = BITTST(r7, TIF_RESTORE_SIGMASK);
 	if cc jump .Lsyscall_do_signals;
 	cc = BITTST(r7, TIF_SIGPENDING);
+	if cc jump .Lsyscall_do_signals;
+	cc = BITTST(r7, TIF_NOTIFY_RESUME);
 	if !cc jump .Lsyscall_really_exit;
 .Lsyscall_do_signals:
 	/* Reenable interrupts.  */
@@ -721,7 +723,7 @@
 
 	r0 = sp;
 	SP += -12;
-	call _do_signal;
+	call _do_notify_resume;
 	SP += 12;
 
 .Lsyscall_really_exit:
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 660ea1b..1873b2c 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -25,11 +25,20 @@
 #include <asm/blackfin.h>
 #include <asm/gpio.h>
 #include <asm/irq_handler.h>
+#include <asm/dpmc.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/bfin_sport.h>
 
 #define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))
 
 #ifdef BF537_FAMILY
 # define BF537_GENERIC_ERROR_INT_DEMUX
+# define SPI_ERR_MASK   (BIT_STAT_TXCOL | BIT_STAT_RBSY | BIT_STAT_MODF | BIT_STAT_TXE)	/* SPI_STAT */
+# define SPORT_ERR_MASK (ROVF | RUVF | TOVF | TUVF)	/* SPORT_STAT */
+# define PPI_ERR_MASK   (0xFFFF & ~FLD)	/* PPI_STATUS */
+# define EMAC_ERR_MASK  (PHYINT | MMCINT | RXFSINT | TXFSINT | WAKEDET | RXDMAERR | TXDMAERR | STMDONE)	/* EMAC_SYSTAT */
+# define UART_ERR_MASK  (0x6)	/* UART_IIR */
+# define CAN_ERR_MASK   (EWTIF | EWRIF | EPIF | BOIF | WUIF | UIAIF | AAIF | RMLIF | UCEIF | EXTIF | ADIF)	/* CAN_GIF */
 #else
 # undef BF537_GENERIC_ERROR_INT_DEMUX
 #endif
@@ -324,11 +333,9 @@
 		irq = IRQ_CAN_ERROR;
 	else if (bfin_read_SPI_STAT() & SPI_ERR_MASK)
 		irq = IRQ_SPI_ERROR;
-	else if ((bfin_read_UART0_IIR() & UART_ERR_MASK_STAT1) &&
-		 (bfin_read_UART0_IIR() & UART_ERR_MASK_STAT0))
+	else if ((bfin_read_UART0_IIR() & UART_ERR_MASK) == UART_ERR_MASK)
 		irq = IRQ_UART0_ERROR;
-	else if ((bfin_read_UART1_IIR() & UART_ERR_MASK_STAT1) &&
-		 (bfin_read_UART1_IIR() & UART_ERR_MASK_STAT0))
+	else if ((bfin_read_UART1_IIR() & UART_ERR_MASK) == UART_ERR_MASK)
 		irq = IRQ_UART1_ERROR;
 
 	if (irq) {
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index d92b168..369e687 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -336,13 +336,6 @@
 
 	ret = platform_boot_secondary(cpu, idle);
 
-	if (ret) {
-		cpu_clear(cpu, cpu_present_map);
-		printk(KERN_CRIT "CPU%u: processor failed to boot (%d)\n", cpu, ret);
-		free_task(idle);
-	} else
-		cpu_set(cpu, cpu_online_map);
-
 	secondary_stack = NULL;
 
 	return ret;
@@ -418,9 +411,16 @@
 
 	setup_secondary(cpu);
 
+	platform_secondary_init(cpu);
+
 	local_irq_enable();
 
-	platform_secondary_init(cpu);
+	/*
+	 * Calibrate loops per jiffy value.
+	 * IRQs need to be enabled here - D-cache can be invalidated
+	 * in timer irq handler, so core B can read correct jiffies.
+	 */
+	calibrate_delay();
 
 	cpu_idle();
 }
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 3db478e..76266f8 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -10,7 +10,6 @@
  * The macros found in mmu_defs_asm.h uses the ## concatenation operator, so
  * -traditional must not be used when assembling this file.
  */
-#include <linux/autoconf.h>
 #include <arch/memmap.h>
 #include <hwregs/reg_rdwr.h>
 #include <hwregs/intr_vect.h>
diff --git a/arch/cris/include/asm/asm-offsets.h b/arch/cris/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/cris/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/cris/include/asm/elf.h b/arch/cris/include/asm/elf.h
index 0f51b10..8a3d8e2 100644
--- a/arch/cris/include/asm/elf.h
+++ b/arch/cris/include/asm/elf.h
@@ -64,8 +64,6 @@
 #define EF_CRIS_VARIANT_COMMON_V10_V32	0x00000004
 /* End of excerpt from {binutils}/include/elf/cris.h.  */
 
-#define USE_ELF_CORE_DUMP
-
 #define ELF_EXEC_PAGESIZE	8192
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/cris/kernel/asm-offsets.c b/arch/cris/kernel/asm-offsets.c
index ddd6fbb..dd7b8e9 100644
--- a/arch/cris/kernel/asm-offsets.c
+++ b/arch/cris/kernel/asm-offsets.c
@@ -1,6 +1,5 @@
 #include <linux/sched.h>
 #include <asm/thread_info.h>
-#include <linux/autoconf.h>
 
 /*
  * Generate definitions needed by assembly language modules.
diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S
index bbfda67..d49d17d2 100644
--- a/arch/cris/kernel/vmlinux.lds.S
+++ b/arch/cris/kernel/vmlinux.lds.S
@@ -8,7 +8,6 @@
  * the kernel has booted.
  */
 
-#include <linux/autoconf.h>
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/page.h>
 
diff --git a/arch/frv/include/asm/asm-offsets.h b/arch/frv/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/frv/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/frv/include/asm/elf.h b/arch/frv/include/asm/elf.h
index 7bbf6e4..c381980 100644
--- a/arch/frv/include/asm/elf.h
+++ b/arch/frv/include/asm/elf.h
@@ -115,7 +115,6 @@
 	__kernel_frame0_ptr->gr29	= 0;						\
 } while(0)
 
-#define USE_ELF_CORE_DUMP
 #define CORE_DUMP_USE_REGSET
 #define ELF_FDPIC_CORE_EFLAGS	EF_FRV_FDPIC
 #define ELF_EXEC_PAGESIZE	16384
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 55e4fab..75cf7f4 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -10,7 +10,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 9420648..53cc669 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -10,6 +10,10 @@
 	default y
 	select HAVE_IDE
 
+config SYMBOL_PREFIX
+	string
+	default "_"
+
 config MMU
 	bool
 	default n
diff --git a/arch/h8300/include/asm/asm-offsets.h b/arch/h8300/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/h8300/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h
index 94e2284..c24fa25 100644
--- a/arch/h8300/include/asm/elf.h
+++ b/arch/h8300/include/asm/elf.h
@@ -34,7 +34,6 @@
 
 #define ELF_PLAT_INIT(_r)	_r->er1 = 0
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h
index de23231..8e46724 100644
--- a/arch/h8300/include/asm/module.h
+++ b/arch/h8300/include/asm/module.h
@@ -8,6 +8,4 @@
 #define Elf_Sym Elf32_Sym
 #define Elf_Ehdr Elf32_Ehdr
 
-#define MODULE_SYMBOL_PREFIX "_"
-
 #endif /* _ASM_H8/300_MODULE_H */
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index b9e24907..03d356d 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -1,4 +1,3 @@
-#define VMLINUX_SYMBOL(_sym_) _##_sym_
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/page.h>
 
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index e7cbaa0..475e272 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -103,4 +103,4 @@
 PHONY += make_nr_irqs_h FORCE
 
 make_nr_irqs_h: FORCE
-	$(Q)$(MAKE) $(build)=arch/ia64/kernel include/asm-ia64/nr-irqs.h
+	$(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index f332e3f..e14c492 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -677,12 +677,19 @@
 			spin_unlock_irqrestore(&ioc->saved_lock, flags);
 
 			pide = sba_search_bitmap(ioc, dev, pages_needed, 0);
-			if (unlikely(pide >= (ioc->res_size << 3)))
-				panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
-				      ioc->ioc_hpa);
+			if (unlikely(pide >= (ioc->res_size << 3))) {
+				printk(KERN_WARNING "%s: I/O MMU @ %p is"
+				       "out of mapping resources, %u %u %lx\n",
+				       __func__, ioc->ioc_hpa, ioc->res_size,
+				       pages_needed, dma_get_seg_boundary(dev));
+				return -1;
+			}
 #else
-			panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n",
-			      ioc->ioc_hpa);
+			printk(KERN_WARNING "%s: I/O MMU @ %p is"
+			       "out of mapping resources, %u %u %lx\n",
+			       __func__, ioc->ioc_hpa, ioc->res_size,
+			       pages_needed, dma_get_seg_boundary(dev));
+			return -1;
 #endif
 		}
 	}
@@ -965,6 +972,8 @@
 #endif
 
 	pide = sba_alloc_range(ioc, dev, size);
+	if (pide < 0)
+		return 0;
 
 	iovp = (dma_addr_t) pide << iovp_shift;
 
@@ -1320,6 +1329,7 @@
 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	int n_mappings = 0;
 	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+	int idx;
 
 	while (nents > 0) {
 		unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
@@ -1418,16 +1428,22 @@
 		vcontig_sg->dma_length = vcontig_len;
 		dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask;
 		ASSERT(dma_len <= DMA_CHUNK_SIZE);
-		dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG
-			| (sba_alloc_range(ioc, dev, dma_len) << iovp_shift)
-			| dma_offset);
+		idx = sba_alloc_range(ioc, dev, dma_len);
+		if (idx < 0) {
+			dma_sg->dma_length = 0;
+			return -1;
+		}
+		dma_sg->dma_address = (dma_addr_t)(PIDE_FLAG | (idx << iovp_shift)
+						   | dma_offset);
 		n_mappings++;
 	}
 
 	return n_mappings;
 }
 
-
+static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
+			       int nents, enum dma_data_direction dir,
+			       struct dma_attrs *attrs);
 /**
  * sba_map_sg - map Scatter/Gather list
  * @dev: instance of PCI owned by the driver that's asking.
@@ -1493,6 +1509,10 @@
 	** Access to the virtual address is what forces a two pass algorithm.
 	*/
 	coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
+	if (coalesced < 0) {
+		sba_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
+		return 0;
+	}
 
 	/*
 	** Program the I/O Pdir
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index 9a3abf58..6577257 100644
--- a/arch/ia64/ia32/elfcore32.h
+++ b/arch/ia64/ia32/elfcore32.h
@@ -11,8 +11,6 @@
 #include <asm/intrinsics.h>
 #include <asm/uaccess.h>
 
-#define USE_ELF_CORE_DUMP 1
-
 /* Override elfcore.h */
 #define _LINUX_ELFCORE_H 1
 typedef unsigned int elf_greg_t;
diff --git a/arch/ia64/include/asm/asm-offsets.h b/arch/ia64/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/ia64/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index 8d3c79c..7d09a09 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -73,7 +73,7 @@
 	if (!dev->dma_mask)
 		return 0;
 
-	return addr + size <= *dev->dma_mask;
+	return addr + size - 1 <= *dev->dma_mask;
 }
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h
index 86eddee..e14108b 100644
--- a/arch/ia64/include/asm/elf.h
+++ b/arch/ia64/include/asm/elf.h
@@ -25,7 +25,6 @@
 #define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_IA_64
 
-#define USE_ELF_CORE_DUMP
 #define CORE_DUMP_USE_REGSET
 
 /* Least-significant four bits of ELF header's e_flags are OS-specific.  The bits are
diff --git a/arch/ia64/include/asm/hw_irq.h b/arch/ia64/include/asm/hw_irq.h
index 91619b3..bf2e374 100644
--- a/arch/ia64/include/asm/hw_irq.h
+++ b/arch/ia64/include/asm/hw_irq.h
@@ -59,7 +59,13 @@
 extern int ia64_first_device_vector;
 extern int ia64_last_device_vector;
 
+#if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined (CONFIG_IA64_DIG))
+/* Reserve the lower priority vector than device vectors for "move IRQ" IPI */
+#define IA64_IRQ_MOVE_VECTOR		0x30	/* "move IRQ" IPI */
+#define IA64_DEF_FIRST_DEVICE_VECTOR	0x31
+#else
 #define IA64_DEF_FIRST_DEVICE_VECTOR	0x30
+#endif
 #define IA64_DEF_LAST_DEVICE_VECTOR	0xe7
 #define IA64_FIRST_DEVICE_VECTOR	ia64_first_device_vector
 #define IA64_LAST_DEVICE_VECTOR		ia64_last_device_vector
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index 0d9d16e..cc8335e 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -424,6 +424,8 @@
 extern void __iomem * ioremap(unsigned long offset, unsigned long size);
 extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
 extern void iounmap (volatile void __iomem *addr);
+extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
+extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
 
 /*
  * String version of IO memory access ops:
diff --git a/arch/ia64/include/asm/irq.h b/arch/ia64/include/asm/irq.h
index 5282546..91b920fd 100644
--- a/arch/ia64/include/asm/irq.h
+++ b/arch/ia64/include/asm/irq.h
@@ -13,7 +13,7 @@
 
 #include <linux/types.h>
 #include <linux/cpumask.h>
-#include <asm-ia64/nr-irqs.h>
+#include <generated/nr-irqs.h>
 
 static __inline__ int
 irq_canonicalize (int irq)
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
index c171cdf..43f96ab 100644
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -106,6 +106,11 @@
 	unsigned long		os_status;		/* OS status to SAL, enum below */
 	unsigned long		context;		/* 0 if return to same context
 							   1 if return to new context */
+
+	/* I-resources */
+	unsigned long		iip;
+	unsigned long		ipsr;
+	unsigned long		ifs;
 };
 
 enum {
diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h
index fbee74b..e876268 100644
--- a/arch/ia64/include/asm/rwsem.h
+++ b/arch/ia64/include/asm/rwsem.h
@@ -47,7 +47,7 @@
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
 #define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
 	  LIST_HEAD_INIT((name).wait_list) }
 
 #define DECLARE_RWSEM(name) \
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 6b7edca..2a75e93 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -81,17 +81,14 @@
 endef
 
 # We use internal kbuild rules to avoid the "is up to date" message from make
-arch/$(SRCARCH)/kernel/nr-irqs.s: $(srctree)/arch/$(SRCARCH)/kernel/nr-irqs.c \
-				$(wildcard $(srctree)/include/asm-ia64/*/irq.h)
+arch/$(SRCARCH)/kernel/nr-irqs.s: arch/$(SRCARCH)/kernel/nr-irqs.c
 	$(Q)mkdir -p $(dir $@)
 	$(call if_changed_dep,cc_s_c)
 
-include/asm-ia64/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
+include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
 	$(Q)mkdir -p $(dir $@)
 	$(call cmd,nr_irqs)
 
-clean-files += $(objtree)/include/asm-ia64/nr-irqs.h
-
 #
 # native ivt.S, entry.S and fsys.S
 #
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 70e4bad..d4093a1 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -260,7 +260,6 @@
 }
 
 #if defined(CONFIG_SMP) && (defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG))
-#define IA64_IRQ_MOVE_VECTOR	IA64_DEF_FIRST_DEVICE_VECTOR
 
 static enum vector_domain_type {
 	VECTOR_DOMAIN_NONE,
@@ -659,11 +658,8 @@
 	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
 #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_DIG)
-	if (vector_domain_type != VECTOR_DOMAIN_NONE) {
-		BUG_ON(IA64_FIRST_DEVICE_VECTOR != IA64_IRQ_MOVE_VECTOR);
-		IA64_FIRST_DEVICE_VECTOR++;
+	if (vector_domain_type != VECTOR_DOMAIN_NONE)
 		register_percpu_irq(IA64_IRQ_MOVE_VECTOR, &irq_move_irqaction);
-	}
 #endif
 #endif
 #ifdef CONFIG_PERFMON
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 496ac7a..32f2639 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -888,9 +888,10 @@
 }
 
 static void
-finish_pt_regs(struct pt_regs *regs, const pal_min_state_area_t *ms,
+finish_pt_regs(struct pt_regs *regs, struct ia64_sal_os_state *sos,
 		unsigned long *nat)
 {
+	const pal_min_state_area_t *ms = sos->pal_min_state;
 	const u64 *bank;
 
 	/* If ipsr.ic then use pmsa_{iip,ipsr,ifs}, else use
@@ -904,6 +905,10 @@
 		regs->cr_iip = ms->pmsa_xip;
 		regs->cr_ipsr = ms->pmsa_xpsr;
 		regs->cr_ifs = ms->pmsa_xfs;
+
+		sos->iip = ms->pmsa_iip;
+		sos->ipsr = ms->pmsa_ipsr;
+		sos->ifs = ms->pmsa_ifs;
 	}
 	regs->pr = ms->pmsa_pr;
 	regs->b0 = ms->pmsa_br0;
@@ -1079,7 +1084,7 @@
 	memcpy(old_regs, regs, sizeof(*regs));
 	old_regs->loadrs = loadrs;
 	old_unat = old_regs->ar_unat;
-	finish_pt_regs(old_regs, ms, &old_unat);
+	finish_pt_regs(old_regs, sos, &old_unat);
 
 	/* Next stack a struct switch_stack.  mca_asm.S built a partial
 	 * switch_stack, copy it and fill in the blanks using pt_regs and
@@ -1150,7 +1155,7 @@
 	mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n",
 			smp_processor_id(), type, msg);
 	old_unat = regs->ar_unat;
-	finish_pt_regs(regs, ms, &old_unat);
+	finish_pt_regs(regs, sos, &old_unat);
 	return previous_current;
 }
 
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 599b233..5246285 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2200,7 +2200,7 @@
 {
 	struct file *file;
 	struct inode *inode;
-	struct dentry *dentry;
+	struct path path;
 	char name[32];
 	struct qstr this;
 
@@ -2225,18 +2225,19 @@
 	/*
 	 * allocate a new dcache entry
 	 */
-	dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
-	if (!dentry) {
+	path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this);
+	if (!path.dentry) {
 		iput(inode);
 		return ERR_PTR(-ENOMEM);
 	}
+	path.mnt = mntget(pfmfs_mnt);
 
-	dentry->d_op = &pfmfs_dentry_operations;
-	d_add(dentry, inode);
+	path.dentry->d_op = &pfmfs_dentry_operations;
+	d_add(path.dentry, inode);
 
-	file = alloc_file(pfmfs_mnt, dentry, FMODE_READ, &pfm_file_ops);
+	file = alloc_file(&path, FMODE_READ, &pfm_file_ops);
 	if (!file) {
-		dput(dentry);
+		path_put(&path);
 		return ERR_PTR(-ENFILE);
 	}
 
diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c
index 0c3564a..9324c87 100644
--- a/arch/ia64/kvm/asm-offsets.c
+++ b/arch/ia64/kvm/asm-offsets.c
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/autoconf.h>
 #include <linux/kvm_host.h>
 #include <linux/kbuild.h>
 
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 2a14062..3dccdd8 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -22,6 +22,12 @@
 }
 
 void __iomem *
+early_ioremap (unsigned long phys_addr, unsigned long size)
+{
+	return __ioremap(phys_addr);
+}
+
+void __iomem *
 ioremap (unsigned long phys_addr, unsigned long size)
 {
 	void __iomem *addr;
@@ -102,6 +108,11 @@
 EXPORT_SYMBOL(ioremap_nocache);
 
 void
+early_iounmap (volatile void __iomem *addr, unsigned long size)
+{
+}
+
+void
 iounmap (volatile void __iomem *addr)
 {
 	if (REGION_NUMBER(addr) == RGN_GATE)
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 35b2a27..efb4545 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -9,6 +9,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/bitmap.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
@@ -369,7 +370,7 @@
 static dma_addr_t
 tioca_dma_mapped(struct pci_dev *pdev, unsigned long paddr, size_t req_size)
 {
-	int i, ps, ps_shift, entry, entries, mapsize, last_entry;
+	int ps, ps_shift, entry, entries, mapsize;
 	u64 xio_addr, end_xio_addr;
 	struct tioca_common *tioca_common;
 	struct tioca_kernel *tioca_kern;
@@ -410,23 +411,13 @@
 	map = tioca_kern->ca_pcigart_pagemap;
 	mapsize = tioca_kern->ca_pcigart_entries;
 
-	entry = find_first_zero_bit(map, mapsize);
-	while (entry < mapsize) {
-		last_entry = find_next_bit(map, mapsize, entry);
-
-		if (last_entry - entry >= entries)
-			break;
-
-		entry = find_next_zero_bit(map, mapsize, last_entry);
-	}
-
-	if (entry > mapsize) {
+	entry = bitmap_find_next_zero_area(map, mapsize, 0, entries, 0);
+	if (entry >= mapsize) {
 		kfree(ca_dmamap);
 		goto map_return;
 	}
 
-	for (i = 0; i < entries; i++)
-		set_bit(entry + i, map);
+	bitmap_set(map, entry, entries);
 
 	bus_addr = tioca_kern->ca_pciap_base + (entry * ps);
 
diff --git a/arch/m32r/include/asm/elf.h b/arch/m32r/include/asm/elf.h
index 0cc34c9..2f85412 100644
--- a/arch/m32r/include/asm/elf.h
+++ b/arch/m32r/include/asm/elf.h
@@ -102,7 +102,6 @@
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->r0 = 0
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /*
diff --git a/arch/m68k/include/asm/asm-offsets.h b/arch/m68k/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/m68k/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/m68k/include/asm/elf.h b/arch/m68k/include/asm/elf.h
index 0b0f49e..01c193d 100644
--- a/arch/m68k/include/asm/elf.h
+++ b/arch/m68k/include/asm/elf.h
@@ -59,7 +59,6 @@
    is actually used on ASV.  */
 #define ELF_PLAT_INIT(_r, load_addr)	_r->a1 = 0
 
-#define USE_ELF_CORE_DUMP
 #ifndef CONFIG_SUN3
 #define ELF_EXEC_PAGESIZE	4096
 #else
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 86edb5f..ef54128 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -196,7 +196,7 @@
  * for them and trying to understand what they mean.
  *
  * CONFIG_xxx:	These are the obvious machine configuration defines created
- * during configuration.  These are defined in include/linux/autoconf.h.
+ * during configuration.  These are defined in autoconf.h.
  *
  * CONSOLE:	There is support for head.S console in this file.  This
  * console can talk to a Mac frame buffer, but could easily be extrapolated
diff --git a/arch/microblaze/include/asm/asm-offsets.h b/arch/microblaze/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/microblaze/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
index f92fc0d..7d4acf2 100644
--- a/arch/microblaze/include/asm/elf.h
+++ b/arch/microblaze/include/asm/elf.h
@@ -77,7 +77,6 @@
 #define ELF_DATA	ELFDATA2MSB
 #endif
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fd7620f..9541171 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -5,9 +5,12 @@
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB
-	# Horrible source of confusion.  Die, die, die ...
-	select EMBEDDED
-	select RTC_LIB if !LEMOTE_FULOONG2E
+	select HAVE_FUNCTION_TRACER
+	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+	select HAVE_DYNAMIC_FTRACE
+	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_GRAPH_TRACER
+	select RTC_LIB if !MACH_LOONGSON
 
 mainmenu "Linux/MIPS Kernel Configuration"
 
@@ -22,6 +25,7 @@
 
 config MACH_ALCHEMY
 	bool "Alchemy processor based machines"
+	select SYS_SUPPORTS_ZBOOT
 
 config AR7
 	bool "Texas Instruments AR7"
@@ -36,6 +40,7 @@
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_ZBOOT_UART16550
 	select GENERIC_GPIO
 	select GCD
 	select VLYNQ
@@ -43,23 +48,6 @@
 	  Support for the Texas Instruments AR7 System-on-a-Chip
 	  family: TNETD7100, 7200 and 7300.
 
-config BASLER_EXCITE
-	bool "Basler eXcite smart camera"
-	select CEVT_R4K
-	select CSRC_R4K
-	select DMA_COHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_CPU_RM9K
-	select MIPS_RM9122
-	select SYS_HAS_CPU_RM9000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	help
-	  The eXcite is a smart camera platform manufactured by
-	  Basler Vision Technologies AG.
-
 config BCM47XX
 	bool "BCM47XX based boards"
 	select CEVT_R4K
@@ -192,6 +180,7 @@
 
 config MACH_LOONGSON
 	bool "Loongson family of machines"
+	select SYS_SUPPORTS_ZBOOT_UART16550
 	help
 	  This enables the support of Loongson family of machines.
 
@@ -233,6 +222,7 @@
 	select SYS_SUPPORTS_MIPS_CMP
 	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_SMARTMIPS
+	select SYS_SUPPORTS_ZBOOT
 	help
 	  This enables support for the MIPS Technologies Malta evaluation
 	  board.
@@ -334,6 +324,24 @@
 	  Yosemite is an evaluation board for the RM9000x2 processor
 	  manufactured by PMC-Sierra.
 
+config POWERTV
+	bool "Cisco PowerTV"
+	select BOOT_ELF32
+	select CEVT_R4K
+	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_IRQ_EI
+	select CSRC_POWERTV
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select USB_OHCI_LITTLE_ENDIAN
+	help
+	  This enables support for the Cisco PowerTV Platform.
+
 config SGI_IP22
 	bool "SGI IP22 (Indy/Indigo2)"
 	select ARC
@@ -674,11 +682,11 @@
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
-source "arch/mips/basler/excite/Kconfig"
 source "arch/mips/bcm63xx/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/lasat/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
+source "arch/mips/powertv/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
 source "arch/mips/txx9/Kconfig"
@@ -778,6 +786,9 @@
 config CSRC_IOASIC
 	bool
 
+config CSRC_POWERTV
+	bool
+
 config CSRC_R4K_LIB
 	bool
 
@@ -806,20 +817,6 @@
 config DMA_NEED_PCI_MAP_STATE
 	bool
 
-config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED && DEBUG_KERNEL
-	depends on SYS_HAS_EARLY_PRINTK
-	default y
-	help
-	  This option enables special console drivers which allow the kernel
-	  to print messages very early in the bootup process.
-
-	  This is useful for kernel debugging when your machine crashes very
-	  early before the console code is initialized. For normal operation,
-	  it is not recommended because it looks ugly on some machines and
-	  doesn't cooperate with an X server. You should normally say N here,
-	  unless you want to debug such a crash.
-
 config SYS_HAS_EARLY_PRINTK
 	bool
 
@@ -1069,6 +1066,21 @@
 	  The Loongson 2E processor implements the MIPS III instruction set
 	  with many extensions.
 
+	  It has an internal FPGA northbridge, which is compatiable to
+	  bonito64.
+
+config CPU_LOONGSON2F
+	bool "Loongson 2F"
+	depends on SYS_HAS_CPU_LOONGSON2F
+	select CPU_LOONGSON2
+	help
+	  The Loongson 2F processor implements the MIPS III instruction set
+	  with many extensions.
+
+	  Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller
+	  have a similar programming interface with FPGA northbridge used in
+	  Loongson2E.
+
 config CPU_MIPS32_R1
 	bool "MIPS32 Release 1"
 	depends on SYS_HAS_CPU_MIPS32_R1
@@ -1294,6 +1306,16 @@
 
 endchoice
 
+config SYS_SUPPORTS_ZBOOT
+	bool
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZMA
+
+config SYS_SUPPORTS_ZBOOT_UART16550
+	bool
+	select SYS_SUPPORTS_ZBOOT
+
 config CPU_LOONGSON2
 	bool
 	select CPU_SUPPORTS_32BIT_KERNEL
@@ -1303,6 +1325,12 @@
 config SYS_HAS_CPU_LOONGSON2E
 	bool
 
+config SYS_HAS_CPU_LOONGSON2F
+	bool
+	select CPU_SUPPORTS_CPUFREQ
+	select CPU_SUPPORTS_ADDRWINCFG if 64BIT
+	select CPU_SUPPORTS_UNCACHED_ACCELERATED
+
 config SYS_HAS_CPU_MIPS32_R1
 	bool
 
@@ -1411,8 +1439,17 @@
 	bool
 config CPU_SUPPORTS_64BIT_KERNEL
 	bool
+config CPU_SUPPORTS_CPUFREQ
+	bool
+config CPU_SUPPORTS_ADDRWINCFG
+	bool
 config CPU_SUPPORTS_HUGEPAGES
 	bool
+config CPU_SUPPORTS_UNCACHED_ACCELERATED
+	bool
+config MIPS_PGD_C0_CONTEXT
+	bool
+	default y if 64BIT && CPU_MIPSR2
 
 #
 # Set to y for ptrace access to watch registers.
@@ -2024,15 +2061,6 @@
 
 source "init/Kconfig"
 
-config PROBE_INITRD_HEADER
-	bool "Probe initrd header created by addinitrd"
-	depends on BLK_DEV_INITRD
-	help
-	  Probe initrd header at the last page of kernel image.
-	  Say Y here if you are using arch/mips/boot/addinitrd.c to
-	  add initrd or initramfs image to the kernel image.
-	  Otherwise, say N.
-
 source "kernel/Kconfig.freezer"
 
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
@@ -2104,6 +2132,7 @@
 
 config I8253
 	bool
+	select MIPS_EXTERNAL_TIMER
 
 config ZONE_DMA32
 	bool
@@ -2180,6 +2209,8 @@
 
 endmenu
 
+source "arch/mips/kernel/cpufreq/Kconfig"
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 364ca89..d2b88a0 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -6,15 +6,66 @@
 
 source "lib/Kconfig.debug"
 
+config EARLY_PRINTK
+	bool "Early printk" if EMBEDDED
+	depends on SYS_HAS_EARLY_PRINTK
+	default y
+	help
+	  This option enables special console drivers which allow the kernel
+	  to print messages very early in the bootup process.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation,
+	  it is not recommended because it looks ugly on some machines and
+	  doesn't cooperate with an X server. You should normally say N here,
+	  unless you want to debug such a crash.
+
+config CMDLINE_BOOL
+	bool "Built-in kernel command line"
+	default n
+	help
+	  For most systems, it is firmware or second stage bootloader that
+	  by default specifies the kernel command line options.  However,
+	  it might be necessary or advantageous to either override the
+	  default kernel command line or add a few extra options to it.
+	  For such cases, this option allows you to hardcode your own
+	  command line options directly into the kernel.  For that, you
+	  should choose 'Y' here, and fill in the extra boot arguments
+	  in CONFIG_CMDLINE.
+
+	  The built-in options will be concatenated to the default command
+	  line if CMDLINE_OVERRIDE is set to 'N'. Otherwise, the default
+	  command line will be ignored and replaced by the built-in string.
+
+	  Most MIPS systems will normally expect 'N' here and rely upon
+	  the command line from the firmware or the second-stage bootloader.
+
 config CMDLINE
 	string "Default kernel command string"
+	depends on CMDLINE_BOOL
 	default ""
 	help
 	  On some platforms, there is currently no way for the boot loader to
-	  pass arguments to the kernel. For these platforms, you can supply
-	  some command-line options at build time by entering them here.  In
-	  other cases you can specify kernel args so that you don't have
-	  to set them up in board prom initialization routines.
+	  pass arguments to the kernel.  For these platforms, and for the cases
+	  when you want to add some extra options to the command line or ignore
+	  the default command line, you can supply some command-line options at
+	  build time by entering them here.  In other cases you can specify
+	  kernel args so that you don't have to set them up in board prom
+	  initialization routines.
+
+	  For more information, see the CMDLINE_BOOL and CMDLINE_OVERRIDE
+	  options.
+
+config CMDLINE_OVERRIDE
+	bool "Built-in command line overrides firware arguments"
+	default n
+	depends on CMDLINE_BOOL
+	help
+	  By setting this option to 'Y' you will have your kernel ignore
+	  command line arguments from firmware or second stage bootloader.
+	  Instead, the built-in command line will be used exclusively.
+
+	  Normally, you will choose 'N' here.
 
 config DEBUG_STACK_USAGE
 	bool "Enable stack utilization instrumentation"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 77f5021..1893efd 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -48,7 +48,16 @@
   endif
 endif
 
+ifndef CONFIG_FUNCTION_TRACER
 cflags-y := -ffunction-sections
+endif
+ifdef CONFIG_FUNCTION_GRAPH_TRACER
+  ifndef KBUILD_MCOUNT_RA_ADDRESS
+    ifeq ($(call cc-option-yn,-mmcount-ra-address), y)
+      cflags-y += -mmcount-ra-address -DKBUILD_MCOUNT_RA_ADDRESS
+    endif
+  endif
+endif
 cflags-y += $(call cc-option, -mno-check-zero-division)
 
 ifdef CONFIG_32BIT
@@ -69,6 +78,7 @@
 
 all-$(CONFIG_BOOT_ELF32)	:= $(vmlinux-32)
 all-$(CONFIG_BOOT_ELF64)	:= $(vmlinux-64)
+all-$(CONFIG_SYS_SUPPORTS_ZBOOT)+= vmlinuz
 
 #
 # GCC uses -G 0 -mabicalls -fpic as default.  We don't want PIC in the kernel
@@ -124,6 +134,8 @@
 cflags-$(CONFIG_CPU_LOONGSON2)	+= -Wa,--trap
 cflags-$(CONFIG_CPU_LOONGSON2E) += \
 	$(call cc-option,-march=loongson2e,-march=r4600)
+cflags-$(CONFIG_CPU_LOONGSON2F) += \
+	$(call cc-option,-march=loongson2f,-march=r4600)
 
 cflags-$(CONFIG_CPU_MIPS32_R1)	+= $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
 			-Wa,-mips32 -Wa,--trap
@@ -324,6 +336,7 @@
 cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson \
                     -mno-branch-likely
 load-$(CONFIG_LEMOTE_FULOONG2E) +=0xffffffff80100000
+load-$(CONFIG_LEMOTE_MACH2F) +=0xffffffff80200000
 
 #
 # MIPS Malta board
@@ -331,7 +344,7 @@
 core-$(CONFIG_MIPS_MALTA)	+= arch/mips/mti-malta/
 cflags-$(CONFIG_MIPS_MALTA)	+= -I$(srctree)/arch/mips/include/asm/mach-malta
 load-$(CONFIG_MIPS_MALTA)	+= 0xffffffff80100000
-all-$(CONFIG_MIPS_MALTA)	:= vmlinux.bin
+all-$(CONFIG_MIPS_MALTA)	:= vmlinuz.bin
 
 #
 # MIPS SIM
@@ -356,13 +369,6 @@
 load-$(CONFIG_PMC_YOSEMITE)	+= 0xffffffff80100000
 
 #
-# Basler eXcite
-#
-core-$(CONFIG_BASLER_EXCITE)	+= arch/mips/basler/excite/
-cflags-$(CONFIG_BASLER_EXCITE)	+= -I$(srctree)/arch/mips/include/asm/mach-excite
-load-$(CONFIG_BASLER_EXCITE)	+= 0x80100000
-
-#
 # LASAT platforms
 #
 core-$(CONFIG_LASAT)		+= arch/mips/lasat/
@@ -441,6 +447,13 @@
 load-$(CONFIG_NEC_MARKEINS)	+= 0xffffffff88100000
 
 #
+# Cisco PowerTV Platform
+#
+core-$(CONFIG_POWERTV)		+= arch/mips/powertv/
+cflags-$(CONFIG_POWERTV)        += -I$(srctree)/arch/mips/include/asm/mach-powertv
+load-$(CONFIG_POWERTV)		+= 0xffffffff90800000
+
+#
 # SGI IP22 (Indy/Indigo2)
 #
 # Set the load address to >= 0xffffffff88069000 if you want to leave space for
@@ -581,7 +594,7 @@
 else
 load-$(CONFIG_SNI_RM)		+= 0xffffffff80030000
 endif
-all-$(CONFIG_SNI_RM)		:= vmlinux.ecoff
+all-$(CONFIG_SNI_RM)		:= vmlinuz.ecoff
 
 #
 # Common TXx9
@@ -699,9 +712,23 @@
 	$(OBJCOPY) -O $(64bit-bfd) $(OBJCOPYFLAGS) $< $@
 
 makeboot =$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) $(1)
+makezboot =$(Q)$(MAKE) $(build)=arch/mips/boot/compressed \
+	   VMLINUX_LOAD_ADDRESS=$(load-y) 32bit-bfd=$(32bit-bfd) $(1)
 
 all:	$(all-y)
 
+vmlinuz: vmlinux FORCE
+	+@$(call makezboot,$@)
+
+vmlinuz.bin: vmlinux
+	+@$(call makezboot,$@)
+
+vmlinuz.ecoff: vmlinux
+	+@$(call makezboot,$@)
+
+vmlinuz.srec: vmlinux
+	+@$(call makezboot,$@)
+
 vmlinux.bin: $(vmlinux-32)
 	+@$(call makeboot,$@)
 
@@ -726,11 +753,13 @@
 
 install:
 	$(Q)install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+	$(Q)install -D -m 755 vmlinuz $(INSTALL_PATH)/vmlinuz-$(KERNELRELEASE)
 	$(Q)install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
 	$(Q)install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
 
 archclean:
 	@$(MAKE) $(clean)=arch/mips/boot
+	@$(MAKE) $(clean)=arch/mips/boot/compressed
 	@$(MAKE) $(clean)=arch/mips/lasat
 
 define archhelp
@@ -738,10 +767,18 @@
 	echo '  vmlinux.ecoff        - ECOFF boot image'
 	echo '  vmlinux.bin          - Raw binary boot image'
 	echo '  vmlinux.srec         - SREC boot image'
+	echo '  vmlinuz              - Compressed boot(zboot) image'
+	echo '  vmlinuz.ecoff        - ECOFF zboot image'
+	echo '  vmlinuz.bin          - Raw binary zboot image'
+	echo '  vmlinuz.srec         - SREC zboot image'
 	echo
 	echo '  These will be default as apropriate for a configured platform.'
 endef
 
 CLEAN_FILES += vmlinux.32 \
 	       vmlinux.64 \
-	       vmlinux.ecoff
+	       vmlinux.ecoff \
+	       vmlinuz \
+	       vmlinuz.ecoff \
+	       vmlinuz.bin \
+	       vmlinuz.srec
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 835f3f0..85169c0 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -505,7 +505,7 @@
 	int res;
 	u32 *bootcr, val;
 #ifdef CONFIG_SERIAL_8250
-	static struct uart_port uart_port[2];
+	static struct uart_port uart_port[2] __initdata;
 
 	memset(uart_port, 0, sizeof(struct uart_port) * 2);
 
diff --git a/arch/mips/basler/excite/Kconfig b/arch/mips/basler/excite/Kconfig
deleted file mode 100644
index ba50607..0000000
--- a/arch/mips/basler/excite/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config BASLER_EXCITE_PROTOTYPE
-	bool "Support for pre-release units"
-	depends on BASLER_EXCITE
-	default n
-	help
-	  Pre-series (prototype) units are different from later ones in
-	  some ways. Select this option if you have one of these. Please
-	  note that a kernel built with this option selected will not be
-	  able to run on normal units.
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile
deleted file mode 100644
index cff29cf..0000000
--- a/arch/mips/basler/excite/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Basler eXcite
-#
-
-obj-$(CONFIG_BASLER_EXCITE)	+= excite_irq.o excite_prom.o excite_setup.o \
-				   excite_device.o excite_procfs.o
-
-obj-m				+= excite_iodev.o
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
deleted file mode 100644
index e00bc2d..0000000
--- a/arch/mips/basler/excite/excite_device.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/platform_device.h>
-#include <linux/ioport.h>
-#include <linux/err.h>
-#include <linux/jiffies.h>
-#include <linux/sched.h>
-#include <asm/types.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-#include <rm9k_eth.h>
-#include <rm9k_wdt.h>
-#include <rm9k_xicap.h>
-#include <excite_nandflash.h>
-
-#include "excite_iodev.h"
-
-#define RM9K_GE_UNIT	0
-#define XICAP_UNIT	0
-#define NAND_UNIT	0
-
-#define DLL_TIMEOUT	3		/* seconds */
-
-
-#define RINIT(__start__, __end__, __name__, __parent__) {	\
-	.name	= __name__ "_0",				\
-	.start	= (__start__),					\
-	.end	= (__end__),					\
-	.flags	= 0,						\
-	.parent	= (__parent__)					\
-}
-
-#define RINIT_IRQ(__irq__, __name__) {	\
-	.name	= __name__ "_0",	\
-	.start	= (__irq__),		\
-	.end	= (__irq__),		\
-	.flags	= IORESOURCE_IRQ,	\
-	.parent	= NULL			\
-}
-
-
-
-enum {
-	slice_xicap,
-	slice_eth
-};
-
-
-
-static struct resource
-	excite_ctr_resource __maybe_unused = {
-		.name		= "GPI counters",
-		.start		= 0,
-		.end		= 5,
-		.flags		= 0,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_gpislice_resource __maybe_unused = {
-		.name		= "GPI slices",
-		.start		= 0,
-		.end		= 1,
-		.flags		= 0,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_mdio_channel_resource __maybe_unused = {
-		.name		= "MDIO channels",
-		.start		= 0,
-		.end		= 1,
-		.flags		= 0,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_fifomem_resource __maybe_unused = {
-		.name		= "FIFO memory",
-		.start		= 0,
-		.end		= 767,
-		.flags		= 0,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_scram_resource __maybe_unused = {
-		.name		= "Scratch RAM",
-		.start		= EXCITE_PHYS_SCRAM,
-		.end		= EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
-		.flags		= IORESOURCE_MEM,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_fpga_resource __maybe_unused = {
-		.name		= "System FPGA",
-		.start		= EXCITE_PHYS_FPGA,
-		.end		= EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
-		.flags		= IORESOURCE_MEM,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_nand_resource __maybe_unused = {
-		.name		= "NAND flash control",
-		.start		= EXCITE_PHYS_NAND,
-		.end		= EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
-		.flags		= IORESOURCE_MEM,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	},
-	excite_titan_resource __maybe_unused = {
-		.name		= "TITAN registers",
-		.start		= EXCITE_PHYS_TITAN,
-		.end		= EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
-		.flags		= IORESOURCE_MEM,
-		.parent		= NULL,
-		.sibling	= NULL,
-		.child		= NULL
-	};
-
-
-
-static void adjust_resources(struct resource *res, unsigned int n)
-{
-	struct resource *p;
-	const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
-				   | IORESOURCE_IRQ | IORESOURCE_DMA;
-
-	for (p = res; p < res + n; p++) {
-		const struct resource * const parent = p->parent;
-		if (parent) {
-			p->start += parent->start;
-			p->end   += parent->start;
-			p->flags =  parent->flags & mask;
-		}
-	}
-}
-
-
-
-#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
-static struct resource xicap_rsrc[] = {
-	RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
-	RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
-	RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
-	RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
-	RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
-	RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
-	RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
-	RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
-	RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
-};
-
-static struct platform_device xicap_pdev = {
-	.name		= XICAP_NAME,
-	.id		= XICAP_UNIT,
-	.num_resources	= ARRAY_SIZE(xicap_rsrc),
-	.resource	= xicap_rsrc
-};
-
-/*
- * Create a platform device for the GPI port that receives the
- * image data from the embedded camera.
- */
-static int __init xicap_devinit(void)
-{
-	unsigned long tend;
-	u32 reg;
-	int retval;
-
-	adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
-
-	/* Power up the slice and configure it. */
-	reg = titan_readl(CPTC1R);
-	reg &= ~(0x11100 << slice_xicap);
-	titan_writel(reg, CPTC1R);
-
-	/* Enable slice & DLL. */
-	reg= titan_readl(CPRR);
-	reg &= ~(0x00030003 << (slice_xicap * 2));
-	titan_writel(reg, CPRR);
-
-	/* Wait for DLLs to lock */
-	tend = jiffies + DLL_TIMEOUT * HZ;
-	while (time_before(jiffies, tend)) {
-		if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
-			break;
-		yield();
-	}
-
-	if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
-		printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
-		       xicap_pdev.name, DLL_TIMEOUT);
-		retval = -ETIME;
-	} else {
-		/* Register platform device */
-		retval = platform_device_register(&xicap_pdev);
-	}
-
-	return retval;
-}
-
-device_initcall(xicap_devinit);
-#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
-
-
-
-#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
-static struct resource wdt_rsrc[] = {
-	RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
-	RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
-	RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
-};
-
-static struct platform_device wdt_pdev = {
-	.name		= WDT_NAME,
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(wdt_rsrc),
-	.resource	= wdt_rsrc
-};
-
-/*
- * Create a platform device for the GPI port that receives the
- * image data from the embedded camera.
- */
-static int __init wdt_devinit(void)
-{
-	adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
-	return platform_device_register(&wdt_pdev);
-}
-
-device_initcall(wdt_devinit);
-#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
-
-
-
-static struct resource excite_nandflash_rsrc[] = {
- 	RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
-};
-
-static struct platform_device excite_nandflash_pdev = {
-	.name		= "excite_nand",
-	.id		= NAND_UNIT,
-	.num_resources	= ARRAY_SIZE(excite_nandflash_rsrc),
-	.resource	= excite_nandflash_rsrc
-};
-
-/*
- * Create a platform device for the access to the nand-flash
- * port
- */
-static int __init excite_nandflash_devinit(void)
-{
-	adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
-
-        /* nothing to be done here */
-
-        /* Register platform device */
-	return platform_device_register(&excite_nandflash_pdev);
-}
-
-device_initcall(excite_nandflash_devinit);
-
-
-
-static struct resource iodev_rsrc[] = {
-	RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
-};
-
-static struct platform_device io_pdev = {
-	.name		= IODEV_NAME,
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(iodev_rsrc),
-	.resource	= iodev_rsrc
-};
-
-/*
- * Create a platform device for the external I/O ports.
- */
-static int __init io_devinit(void)
-{
-	adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
-	return platform_device_register(&io_pdev);
-}
-
-device_initcall(io_devinit);
-
-
-
-
-#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
-static struct resource rm9k_ge_rsrc[] = {
-	RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
-	RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
-	RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
-	RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
-	RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
-	RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
-	RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
-	RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
-	RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
-	RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
-	RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
-	RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
-	RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
-	RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
-	RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
-};
-
-static struct platform_device rm9k_ge_pdev = {
-	.name		= RM9K_GE_NAME,
-	.id		= RM9K_GE_UNIT,
-	.num_resources	= ARRAY_SIZE(rm9k_ge_rsrc),
-	.resource	= rm9k_ge_rsrc
-};
-
-
-
-/*
- * Create a platform device for the Ethernet port.
- */
-static int __init rm9k_ge_devinit(void)
-{
-	u32 reg;
-
-	adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
-
-	/* Power up the slice and configure it. */
-	reg = titan_readl(CPTC1R);
-	reg &= ~(0x11000 << slice_eth);
-	reg |= 0x100 << slice_eth;
-	titan_writel(reg, CPTC1R);
-
-	/* Take the MAC out of reset, reset the DLLs. */
-	reg = titan_readl(CPRR);
-	reg &= ~(0x00030000 << (slice_eth * 2));
-	reg |= 0x3 << (slice_eth * 2);
-	titan_writel(reg, CPRR);
-
-	return platform_device_register(&rm9k_ge_pdev);
-}
-
-device_initcall(rm9k_ge_devinit);
-#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
-
-
-
-static int __init excite_setup_devs(void)
-{
-	int res;
-	u32 reg;
-
-	/* Enable xdma and fifo interrupts */
-	reg = titan_readl(0x0050);
-	titan_writel(reg | 0x18000000, 0x0050);
-
-	res = request_resource(&iomem_resource, &excite_titan_resource);
-	if (res)
-		return res;
-	res = request_resource(&iomem_resource, &excite_scram_resource);
-	if (res)
-		return res;
-	res = request_resource(&iomem_resource, &excite_fpga_resource);
-	if (res)
-		return res;
-	res = request_resource(&iomem_resource, &excite_nand_resource);
-	if (res)
-		return res;
-	excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
-				   ( IORESOURCE_IO | IORESOURCE_MEM
-				   | IORESOURCE_IRQ | IORESOURCE_DMA);
-	excite_nand_resource.flags = excite_nand_resource.parent->flags &
-				   ( IORESOURCE_IO | IORESOURCE_MEM
-				   | IORESOURCE_IRQ | IORESOURCE_DMA);
-
-	return 0;
-}
-
-arch_initcall(excite_setup_devs);
-
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
deleted file mode 100644
index 938b1d0..0000000
--- a/arch/mips/basler/excite/excite_iodev.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- *  Copyright (C) 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/compiler.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-
-#include "excite_iodev.h"
-
-
-
-static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
-static int __init iodev_probe(struct platform_device *);
-static int __exit iodev_remove(struct platform_device *);
-static int iodev_open(struct inode *, struct file *);
-static int iodev_release(struct inode *, struct file *);
-static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
-static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
-static irqreturn_t iodev_irqhdl(int, void *);
-
-
-
-static const char iodev_name[] = "iodev";
-static unsigned int iodev_irq;
-static DECLARE_WAIT_QUEUE_HEAD(wq);
-
-
-
-static const struct file_operations fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= iodev_open,
-	.release	= iodev_release,
-	.read		= iodev_read,
-	.poll		= iodev_poll
-};
-
-static struct miscdevice miscdev =
-{
-	.minor		= MISC_DYNAMIC_MINOR,
-	.name		= iodev_name,
-	.fops		= &fops
-};
-
-static struct platform_driver iodev_driver = {
-	.driver = {
-		.name		= iodev_name,
-		.owner		= THIS_MODULE,
-	},
-	.probe		= iodev_probe,
-	.remove		= __devexit_p(iodev_remove),
-};
-
-
-
-static const struct resource *
-iodev_get_resource(struct platform_device *pdv, const char *name,
-		     unsigned int type)
-{
-	char buf[80];
-	if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
-		return NULL;
-	return platform_get_resource_byname(pdv, type, buf);
-}
-
-
-
-/* No hotplugging on the platform bus - use __init */
-static int __init iodev_probe(struct platform_device *dev)
-{
-	const struct resource * const ri =
-		iodev_get_resource(dev, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
-
-	if (unlikely(!ri))
-		return -ENXIO;
-
-	iodev_irq = ri->start;
-	return misc_register(&miscdev);
-}
-
-
-
-static int __exit iodev_remove(struct platform_device *dev)
-{
-	return misc_deregister(&miscdev);
-}
-
-static int iodev_open(struct inode *i, struct file *f)
-{
-	int ret;
-
-	ret = request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
-			   iodev_name, &miscdev);
-
-	return ret;
-}
-
-static int iodev_release(struct inode *i, struct file *f)
-{
-	free_irq(iodev_irq, &miscdev);
-	return 0;
-}
-
-
-
-
-static ssize_t
-iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
-{
-	ssize_t ret;
-	DEFINE_WAIT(w);
-
-	prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
-	if (!signal_pending(current))
-		schedule();
-	ret = signal_pending(current) ? -ERESTARTSYS : 0;
-	finish_wait(&wq, &w);
-	return ret;
-}
-
-
-static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
-{
-	poll_wait(f, &wq, p);
-	return POLLOUT | POLLWRNORM;
-}
-
-static irqreturn_t iodev_irqhdl(int irq, void *ctxt)
-{
-	wake_up(&wq);
-
-	return IRQ_HANDLED;
-}
-
-static int __init iodev_init_module(void)
-{
-	return platform_driver_register(&iodev_driver);
-}
-
-
-
-static void __exit iodev_cleanup_module(void)
-{
-	platform_driver_unregister(&iodev_driver);
-}
-
-module_init(iodev_init_module);
-module_exit(iodev_cleanup_module);
-
-
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
-MODULE_VERSION("0.0");
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h
deleted file mode 100644
index cbfbb5d..0000000
--- a/arch/mips/basler/excite/excite_iodev.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __EXCITE_IODEV_H__
-#define __EXCITE_IODEV_H__
-
-/* Device name */
-#define IODEV_NAME		"iodev"
-
-/* Resource names */
-#define IODEV_RESOURCE_IRQ	"excite_iodev_irq"
-
-#endif /* __EXCITE_IODEV_H__ */
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
deleted file mode 100644
index 934e0a6..0000000
--- a/arch/mips/basler/excite/excite_irq.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  Copyright (C) by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslereb.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/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-extern asmlinkage void excite_handle_int(void);
-
-/*
- * Initialize the interrupt handler
- */
-void __init arch_init_irq(void)
-{
-	mips_cpu_irq_init();
-	rm7k_cpu_irq_init();
-	rm9k_cpu_irq_init();
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	const u32
-		interrupts = read_c0_cause() >> 8,
-		mask = ((read_c0_status() >> 8) & 0x000000ff) |
-		       (read_c0_intcontrol() & 0x0000ff00),
-		pending = interrupts & mask;
-	u32 msgintflags, msgintmask, msgint;
-
-	/* process timer interrupt */
-	if (pending & (1 << TIMER_IRQ)) {
-		do_IRQ(TIMER_IRQ);
-		return;
-	}
-
-	/* Process PCI interrupts */
-#if USB_IRQ < 10
-	msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10));
-	msgintmask  = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10));
-	msgint	    = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20));
-	if ((pending & (1 << USB_IRQ)) && msgint) {
-#else
-	if (pending & (1 << USB_IRQ)) {
-#endif
-		do_IRQ(USB_IRQ);
-		return;
-	}
-
-	/* Process TITAN interrupts */
-	msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10));
-	msgintmask  = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10));
-	msgint	    = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
-	if ((pending & (1 << TITAN_IRQ)) && msgint) {
-		ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
-		do_IRQ(TITAN_IRQ);
-		return;
-	}
-
-	/* Process FPGA line #0 interrupts */
-	msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10));
-	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
-	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
-	if ((pending & (1 << FPGA0_IRQ)) && msgint) {
-		do_IRQ(FPGA0_IRQ);
-		return;
-	}
-
-	/* Process FPGA line #1 interrupts */
-	msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10));
-	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
-	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
-	if ((pending & (1 << FPGA1_IRQ)) && msgint) {
-		do_IRQ(FPGA1_IRQ);
-		return;
-	}
-
-	/* Process PHY interrupts */
-	msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10));
-	msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
-	msgint	    = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
-	if ((pending & (1 << PHY_IRQ)) && msgint) {
-		do_IRQ(PHY_IRQ);
-		return;
-	}
-
-	/* Process spurious interrupts */
-	spurious_interrupt();
-}
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
deleted file mode 100644
index 08923e6..0000000
--- a/arch/mips/basler/excite/excite_procfs.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *
- *  Procfs support for Basler eXcite
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/stat.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-static int excite_unit_id_proc_show(struct seq_file *m, void *v)
-{
-	seq_printf(m, "%06x", unit_id);
-	return 0;
-}
-
-static int excite_unit_id_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, excite_unit_id_proc_show, NULL);
-}
-
-static const struct file_operations excite_unit_id_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= excite_unit_id_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int
-excite_bootrom_read(char *page, char **start, off_t off, int count,
-		  int *eof, void *data)
-{
-	void __iomem * src;
-
-	if (off >= EXCITE_SIZE_BOOTROM) {
-		*eof = 1;
-		return 0;
-	}
-
-	if ((off + count) > EXCITE_SIZE_BOOTROM)
-		count = EXCITE_SIZE_BOOTROM - off;
-
-	src = ioremap(EXCITE_PHYS_BOOTROM + off, count);
-	if (src) {
-		memcpy_fromio(page, src, count);
-		iounmap(src);
-		*start = page;
-	} else {
-		count = -ENOMEM;
-	}
-
-	return count;
-}
-
-void excite_procfs_init(void)
-{
-	/* Create & populate /proc/excite */
-	struct proc_dir_entry * const pdir = proc_mkdir("excite", NULL);
-	if (pdir) {
-		struct proc_dir_entry * e;
-
-		e = proc_create("unit_id", S_IRUGO, pdir,
-				&excite_unit_id_proc_fops);
-		if (e) e->size = 6;
-
-		e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
-					   excite_bootrom_read, NULL);
-		if (e) e->size = EXCITE_SIZE_BOOTROM;
-	}
-}
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c
deleted file mode 100644
index 68d8bc5..0000000
--- a/arch/mips/basler/excite/excite_prom.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
- *  Manish Lachwani.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/smp.h>
-#include <linux/module.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/bootinfo.h>
-#include <asm/string.h>
-
-#include <excite.h>
-
-/* This struct is used by Redboot to pass arguments to the kernel */
-typedef struct
-{
-	char *name;
-	char *val;
-} t_env_var;
-
-struct parmblock {
-	t_env_var memsize;
-	t_env_var modetty0;
-	t_env_var ethaddr;
-	t_env_var env_end;
-	char *argv[2];
-	char text[0];
-};
-
-static unsigned int prom_argc;
-static const char ** prom_argv;
-static const t_env_var * prom_env;
-
-static void prom_halt(void) __attribute__((noreturn));
-static void prom_exit(void) __attribute__((noreturn));
-
-
-
-const char *get_system_type(void)
-{
-	return "Basler eXcite";
-}
-
-/*
- * Halt the system
- */
-static void prom_halt(void)
-{
-	printk(KERN_NOTICE "\n** System halted.\n");
-	while (1)
-		asm volatile (
-			"\t.set\tmips3\n"
-			"\twait\n"
-			"\t.set\tmips0\n"
-		);
-}
-
-/*
- * Reset the CPU and re-enter Redboot
- */
-static void prom_exit(void)
-{
-	unsigned int i;
-	volatile unsigned char * const flg =
-		(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);
-
-	/* Clear the watchdog reset flag, set the reboot flag */
-	*flg &= ~0x01;
-	*flg |= 0x80;
-
-	for (i = 0; i < 10; i++) {
-		*(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
-		iob();
-		mdelay(1000);
-	}
-
-	printk(KERN_NOTICE "Reset failed\n");
-	prom_halt();
-}
-
-static const char __init *prom_getenv(char *name)
-{
-	const t_env_var * p;
-	for (p = prom_env; p->name != NULL; p++)
-		if(strcmp(name, p->name) == 0)
-			break;
-	return p->val;
-}
-
-/*
- * Init routine which accepts the variables from Redboot
- */
-void __init prom_init(void)
-{
-	const struct parmblock * const pb = (struct parmblock *) fw_arg2;
-
-	prom_argc = fw_arg0;
-	prom_argv = (const char **) fw_arg1;
-	prom_env = &pb->memsize;
-
-	/* Callbacks for halt, restart */
-	_machine_restart = (void (*)(char *)) prom_exit;
-	_machine_halt = prom_halt;
-
-#ifdef CONFIG_32BIT
-	/* copy command line */
-	strcpy(arcs_cmdline, prom_argv[1]);
-	memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
-	strcpy(modetty, prom_getenv("modetty0"));
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-#	error 64 bit support not implemented
-#endif /* CONFIG_64BIT */
-}
-
-/* This is called from free_initmem(), so we need to provide it */
-void __init prom_free_prom_memory(void)
-{
-	/* Nothing to do */
-}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
deleted file mode 100644
index d66b3b8..0000000
--- a/arch/mips/basler/excite/excite_setup.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
- *  Manish Lachwani.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/pgtable-32.h>
-#include <asm/io.h>
-#include <asm/time.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite.h>
-
-#define TITAN_UART_CLK	25000000
-
-#if 1
-/* normal serial port assignment */
-#define REGBASE_SER0	0x0208
-#define REGBASE_SER1	0x0238
-#define MASK_SER0	0x1
-#define MASK_SER1	0x2
-#else
-/* serial ports swapped */
-#define REGBASE_SER0	0x0238
-#define REGBASE_SER1	0x0208
-#define MASK_SER0	0x2
-#define MASK_SER1	0x1
-#endif
-
-unsigned long memsize;
-char modetty[30];
-unsigned int titan_irq = TITAN_IRQ;
-static void __iomem * ctl_regs;
-u32 unit_id;
-
-volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD);
-volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN);
-
-/* Protect access to shared GPI registers */
-DEFINE_SPINLOCK(titan_lock);
-int titan_irqflags;
-
-
-/*
- * The eXcite platform uses the alternate timer interrupt
- *
- * Fixme: At the time of this writing cevt-r4k.c doesn't yet know about how
- * to handle the alternate timer interrupt of the RM9000.
- */
-void __init plat_time_init(void)
-{
-	const u32 modebit5 = ocd_readl(0x00e4);
-	unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2;
-	unsigned int div = ((modebit5 >> 16) & 0x1f) + 2;
-
-	if (div == 33)
-		div = 1;
-	mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
-}
-
-static int __init excite_init_console(void)
-{
-#if defined(CONFIG_SERIAL_8250)
-	static __initdata char serr[] =
-		KERN_ERR "Serial port #%u setup failed\n";
-	struct uart_port up;
-
-	/* Take the DUART out of reset */
-	titan_writel(0x00ff1cff, CPRR);
-
-#if (CONFIG_SERIAL_8250_NR_UARTS > 1)
-	/* Enable both ports */
-	titan_writel(MASK_SER0 | MASK_SER1, UACFG);
-#else
-	/* Enable port #0 only */
-	titan_writel(MASK_SER0, UACFG);
-#endif
-
- 	/*
-	 * Set up serial port #0. Do not use autodetection; the result is
-	 * not what we want.
- 	 */
-	memset(&up, 0, sizeof(up));
-	up.membase	= (char *) titan_addr(REGBASE_SER0);
-	up.irq		= TITAN_IRQ;
-	up.uartclk	= TITAN_UART_CLK;
-	up.regshift	= 0;
-	up.iotype	= UPIO_RM9000;
-	up.type		= PORT_RM9000;
-	up.flags	= UPF_SHARE_IRQ;
-	up.line		= 0;
-	if (early_serial_setup(&up))
-		printk(serr, up.line);
-
-#if CONFIG_SERIAL_8250_NR_UARTS > 1
-	/* And now for port #1. */
-	up.membase	= (char *) titan_addr(REGBASE_SER1);
-	up.line		= 1;
- 	if (early_serial_setup(&up))
-		printk(serr, up.line);
-#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */
-#else
-	/* Leave the DUART in reset */
-	titan_writel(0x00ff3cff, CPRR);
-#endif  /* defined(CONFIG_SERIAL_8250) */
-
-	return 0;
-}
-
-static int __init excite_platform_init(void)
-{
-	unsigned int i;
-	unsigned char buf[3];
-	u8 reg;
-	void __iomem * dpr;
-
-	/* BIU buffer allocations */
-	ocd_writel(8, CPURSLMT);	/* CPU */
-	titan_writel(4, CPGRWL);	/* GPI / Ethernet */
-
-	/* Map control registers located in FPGA */
-	ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16);
-	if (!ctl_regs)
-		panic("eXcite: failed to map platform control registers\n");
-	memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf));
-	unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16);
-
-	/* Clear the reboot flag */
-	dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1);
-	reg = __raw_readb(dpr);
-	__raw_writeb(reg & 0x7f, dpr);
-	iounmap(dpr);
-
-	/* Interrupt controller setup */
-	for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) {
-		ocd_writel(0x00000000, i + 0x04);
-		ocd_writel(0xffffffff, i + 0x0c);
-	}
-	ocd_writel(0x2, NMICONFIG);
-
-	ocd_writel(0x1 << (TITAN_MSGINT % 0x20),
-		   INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20)));
-	ocd_writel((0x1 << (FPGA0_MSGINT % 0x20))
-		   | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))),
-		   INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20)));
-	ocd_writel((0x1 << (FPGA1_MSGINT % 0x20))
-		   | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))),
-		   INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20)));
-	ocd_writel((0x1 << (PHY_MSGINT % 0x20))
-		   | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))),
-		   INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20)));
-#if USB_IRQ < 10
-	ocd_writel((0x1 << (USB_MSGINT % 0x20))
-		   | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))),
-		   INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20)));
-#endif
-	/* Enable the packet FIFO, XDMA and XDMA arbiter */
-	titan_writel(0x00ff18ff, CPRR);
-
-	/*
-	 * Set up the PADMUX. Power down all ethernet slices,
-	 * they will be powered up and configured at device startup.
-	 */
-	titan_writel(0x00878206, CPTC1R);
-	titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */
-
-	/* Reset and enable the FIFO block */
-	titan_writel(0x00000001, SDRXFCIE);
-	titan_writel(0x00000001, SDTXFCIE);
-	titan_writel(0x00000100, SDRXFCIE);
-	titan_writel(0x00000000, SDTXFCIE);
-
-	/*
-	 * Initialize the common interrupt shared by all components of
-	 * the GPI/Ethernet subsystem.
-	 */
-	titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0);
-	titan_writel(TITAN_MSGINT, CPCFG1);
-
-	/*
-	 * XDMA configuration.
-	 * In order for the XDMA to be sharable among multiple drivers,
-	 * the setup must be done here in the platform. The reason is that
-	 * this setup can only be done while the XDMA is in reset. If this
-	 * were done in a driver, it would interrupt all other drivers
-	 * using the XDMA.
-	 */
-	titan_writel(0x80021dff, GXCFG);	/* XDMA reset */
-	titan_writel(0x00000000, CPXCISRA);
-	titan_writel(0x00000000, CPXCISRB);	/* clear pending interrupts */
-#if defined(CONFIG_HIGHMEM)
-#	error change for HIGHMEM support!
-#else
-	titan_writel(0x00000000, GXDMADRPFX);	/* buffer address prefix */
-#endif
-	titan_writel(0, GXDMA_DESCADR);
-
-	for (i = 0x5040; i <= 0x5300; i += 0x0040)
-		titan_writel(0x80080000, i);	/* reset channel */
-
-	titan_writel((0x1 << 29)			/* no sparse tx descr. */
-		     | (0x1 << 28)			/* no sparse rx descr. */
-		     | (0x1 << 23) | (0x1 << 24)	/* descriptor coherency */
-		     | (0x1 << 21) | (0x1 << 22)	/* data coherency */
-		     | (0x1 << 17)
-		     | 0x1dff,
-		     GXCFG);
-
-#if defined(CONFIG_SMP)
-#	error No SMP support
-#else
-	/* All interrupts go to core #0 only. */
-	titan_writel(0x1f007fff, CPDST0A);
-	titan_writel(0x00000000, CPDST0B);
-	titan_writel(0x0000ff3f, CPDST1A);
-	titan_writel(0x00000000, CPDST1B);
-	titan_writel(0x00ffffff, CPXDSTA);
-	titan_writel(0x00000000, CPXDSTB);
-#endif
-
-	/* Enable DUART interrupts, disable everything else. */
-	titan_writel(0x04000000, CPGIG0ER);
-	titan_writel(0x000000c0, CPGIG1ER);
-
-	excite_procfs_init();
-	return 0;
-}
-
-void __init plat_mem_setup(void)
-{
-	volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000;
-
-	/* Announce RAM to system */
-	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
-
-	/* Set up the peripheral address map */
-	*(boot_ocd_base + (LKB9 / sizeof(u32))) = 0;
-	*(boot_ocd_base + (LKB10 / sizeof(u32))) = 0;
-	*(boot_ocd_base + (LKB11 / sizeof(u32))) = 0;
-	*(boot_ocd_base + (LKB12 / sizeof(u32))) = 0;
-	wmb();
-	*(boot_ocd_base + (LKB0 / sizeof(u32))) = EXCITE_PHYS_OCD >> 4;
-	wmb();
-
-	ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5);
-	ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5);
-	ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13);
-	ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13);
-
-	/* Local bus slot #0 */
-	ocd_writel(0x00040510, LDP0);
-	ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9);
-	ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9);
-
-	/* Local bus slot #2 */
-	ocd_writel(0x00000330, LDP2);
-	ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11);
-	ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11);
-
-	/* Local bus slot #3 */
-	ocd_writel(0x00123413, LDP3);
-	ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12);
-	ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12);
-}
-
-
-
-console_initcall(excite_init_console);
-arch_initcall(excite_platform_init);
-
-EXPORT_SYMBOL(titan_lock);
-EXPORT_SYMBOL(titan_irqflags);
-EXPORT_SYMBOL(titan_irq);
-EXPORT_SYMBOL(ocd_base);
-EXPORT_SYMBOL(titan_base);
diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c
index fb284c3..c51405e 100644
--- a/arch/mips/bcm47xx/prom.c
+++ b/arch/mips/bcm47xx/prom.c
@@ -100,11 +100,11 @@
 
 static __init void prom_init_cmdline(void)
 {
-	static char buf[CL_SIZE] __initdata;
+	static char buf[COMMAND_LINE_SIZE] __initdata;
 
 	/* Get the kernel command line from CFE */
-	if (cfe_getenv("LINUX_CMDLINE", buf, CL_SIZE) >= 0) {
-		buf[CL_SIZE-1] = 0;
+	if (cfe_getenv("LINUX_CMDLINE", buf, COMMAND_LINE_SIZE) >= 0) {
+		buf[COMMAND_LINE_SIZE - 1] = 0;
 		strcpy(arcs_cmdline, buf);
 	}
 
@@ -112,13 +112,13 @@
 	 * as CFE is not available anymore later in the boot process. */
 	if ((strstr(arcs_cmdline, "console=")) == NULL) {
 		/* Try to read the default serial port used by CFE */
-		if ((cfe_getenv("BOOT_CONSOLE", buf, CL_SIZE) < 0)
+		if ((cfe_getenv("BOOT_CONSOLE", buf, COMMAND_LINE_SIZE) < 0)
 		    || (strncmp("uart", buf, 4)))
 			/* Default to uart0 */
 			strcpy(buf, "uart0");
 
 		/* Compute the new command line */
-		snprintf(arcs_cmdline, CL_SIZE, "%s console=ttyS%c,115200",
+		snprintf(arcs_cmdline, COMMAND_LINE_SIZE, "%s console=ttyS%c,115200",
 			 arcs_cmdline, buf[4]);
 	}
 }
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index 2a209d7..094bc84 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -25,7 +25,7 @@
 
 VMLINUX = vmlinux
 
-all: vmlinux.ecoff vmlinux.srec addinitrd
+all: vmlinux.ecoff vmlinux.srec
 
 vmlinux.ecoff: $(obj)/elf2ecoff $(VMLINUX)
 	$(obj)/elf2ecoff $(VMLINUX) vmlinux.ecoff $(E2EFLAGS)
@@ -39,11 +39,7 @@
 vmlinux.srec: $(VMLINUX)
 	$(OBJCOPY) -S -O srec $(strip-flags) $(VMLINUX) $(obj)/vmlinux.srec
 
-$(obj)/addinitrd: $(obj)/addinitrd.c
-	$(HOSTCC) -o $@ $^
-
-clean-files += addinitrd \
-	       elf2ecoff \
+clean-files += elf2ecoff \
 	       vmlinux.bin \
 	       vmlinux.ecoff \
 	       vmlinux.srec
diff --git a/arch/mips/boot/addinitrd.c b/arch/mips/boot/addinitrd.c
deleted file mode 100644
index b5b3feb..0000000
--- a/arch/mips/boot/addinitrd.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * addinitrd - program to add a initrd image to an ecoff kernel
- *
- * (C) 1999 Thomas Bogendoerfer
- * minor modifications, cleanup: Guido Guenther <agx@sigxcpu.org>
- * further cleanup: Maciej W. Rozycki
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <netinet/in.h>
-
-#include "ecoff.h"
-
-#define MIPS_PAGE_SIZE	4096
-#define MIPS_PAGE_MASK	(MIPS_PAGE_SIZE-1)
-
-#define swab16(x) \
-        ((unsigned short)( \
-                (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
-                (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
-
-#define swab32(x) \
-        ((unsigned int)( \
-                (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
-                (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
-                (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
-                (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
-
-#define SWAB(a)	(swab ? swab32(a) : (a))
-
-void die(char *s)
-{
-	perror(s);
-	exit(1);
-}
-
-int main(int argc, char *argv[])
-{
-	int fd_vmlinux, fd_initrd, fd_outfile;
-	FILHDR efile;
-	AOUTHDR eaout;
-	SCNHDR esecs[3];
-	struct stat st;
-	char buf[1024];
-	unsigned long loadaddr;
-	unsigned long initrd_header[2];
-	int i, cnt;
-	int swab = 0;
-
-	if (argc != 4) {
-		printf("Usage: %s <vmlinux> <initrd> <outfile>\n", argv[0]);
-		exit(1);
-	}
-
-	if ((fd_vmlinux = open (argv[1], O_RDONLY)) < 0)
-		 die("open vmlinux");
-	if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile)
-		die("read file header");
-	if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout)
-		die("read aout header");
-	if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs)
-		die("read section headers");
-	/*
-	 * check whether the file is good for us
-	 */
-	/* TBD */
-
-	/*
-	 * check, if we have to swab words
-	 */
-	if (ntohs(0xaa55) == 0xaa55) {
-		if (efile.f_magic == swab16(MIPSELMAGIC))
-			swab = 1;
-	} else {
-		if (efile.f_magic == swab16(MIPSEBMAGIC))
-			swab = 1;
-	}
-
-	/* make sure we have an empty data segment for the initrd */
-	if (eaout.dsize || esecs[1].s_size) {
-		fprintf(stderr, "Data segment not empty. Giving up!\n");
-		exit(1);
-	}
-	if ((fd_initrd = open (argv[2], O_RDONLY)) < 0)
-		die("open initrd");
-	if (fstat (fd_initrd, &st) < 0)
-		die("fstat initrd");
-	loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)
-			+ MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8;
-	if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)))
-		loadaddr += MIPS_PAGE_SIZE;
-	initrd_header[0] = SWAB(0x494E5244);
-	initrd_header[1] = SWAB(st.st_size);
-	eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8);
-	eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr);
-
-	if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
-		die("open outfile");
-	if (write (fd_outfile, &efile, sizeof efile) != sizeof efile)
-		die("write file header");
-	if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout)
-		die("write aout header");
-	if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs)
-		die("write section headers");
-	/* skip padding */
-	if(lseek(fd_vmlinux, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
-		die("lseek vmlinux");
-	if(lseek(fd_outfile, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1)
-		die("lseek outfile");
-	/* copy text segment */
-	cnt = SWAB(eaout.tsize);
-	while (cnt) {
-		if ((i = read (fd_vmlinux, buf, sizeof buf)) <= 0)
-			die("read vmlinux");
-		if (write (fd_outfile, buf, i) != i)
-			die("write vmlinux");
-		cnt -= i;
-	}
-	if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header)
-		die("write initrd header");
-	while ((i = read (fd_initrd, buf, sizeof buf)) > 0)
-		if (write (fd_outfile, buf, i) != i)
-			die("write initrd");
-	close(fd_vmlinux);
-	close(fd_initrd);
-	return 0;
-}
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
new file mode 100644
index 0000000..e27f40b
--- /dev/null
+++ b/arch/mips/boot/compressed/Makefile
@@ -0,0 +1,100 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.
+#
+# Adapted for MIPS Pete Popov, Dan Malek
+#
+# Copyright (C) 1994 by Linus Torvalds
+# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
+#
+# Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University
+# Author: Wu Zhangjin <wuzj@lemote.com>
+#
+
+# compressed kernel load addr: VMLINUZ_LOAD_ADDRESS > VMLINUX_LOAD_ADDRESS + VMLINUX_SIZE
+VMLINUX_SIZE := $(shell wc -c $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | cut -d' ' -f1)
+VMLINUX_SIZE := $(shell [ -n "$(VMLINUX_SIZE)" ] && echo $$(($(VMLINUX_SIZE) + (65536 - $(VMLINUX_SIZE) % 65536))))
+VMLINUZ_LOAD_ADDRESS := 0x$(shell [ -n "$(VMLINUX_SIZE)" ] && printf %x $$(($(VMLINUX_LOAD_ADDRESS) + $(VMLINUX_SIZE))))
+
+# set the default size of the mallocing area for decompressing
+BOOT_HEAP_SIZE := 0x400000
+
+# Disable Function Tracer
+KBUILD_CFLAGS := $(shell echo $(KBUILD_CFLAGS) | sed -e "s/-pg//")
+
+KBUILD_CFLAGS := $(LINUXINCLUDE) $(KBUILD_CFLAGS) -D__KERNEL__ \
+	-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \
+
+KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
+	-DKERNEL_ENTRY=0x$(shell $(NM) $(objtree)/$(KBUILD_IMAGE) 2>/dev/null | grep " kernel_entry" | cut -f1 -d \ ) \
+	-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE)
+
+obj-y := $(obj)/head.o $(obj)/decompress.o $(obj)/dbg.o
+
+obj-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
+
+OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
+$(obj)/vmlinux.bin: $(KBUILD_IMAGE)
+	$(call if_changed,objcopy)
+
+suffix_$(CONFIG_KERNEL_GZIP)  = gz
+suffix_$(CONFIG_KERNEL_BZIP2) = bz2
+suffix_$(CONFIG_KERNEL_LZMA)  = lzma
+tool_$(CONFIG_KERNEL_GZIP)    = gzip
+tool_$(CONFIG_KERNEL_BZIP2)   = bzip2
+tool_$(CONFIG_KERNEL_LZMA)    = lzma
+$(obj)/vmlinux.$(suffix_y): $(obj)/vmlinux.bin
+	$(call if_changed,$(tool_y))
+
+$(obj)/piggy.o: $(obj)/vmlinux.$(suffix_y) $(obj)/dummy.o
+	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) \
+		--add-section=.image=$< \
+		--set-section-flags=.image=contents,alloc,load,readonly,data \
+		$(obj)/dummy.o $@
+
+LDFLAGS_vmlinuz := $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T
+vmlinuz: $(src)/ld.script $(obj-y) $(obj)/piggy.o
+	$(call if_changed,ld)
+	$(Q)$(OBJCOPY) $(OBJCOPYFLAGS) -R .comment -R .stab -R .stabstr -R .initrd -R .sysmap $@
+
+#
+# Some DECstations need all possible sections of an ECOFF executable
+#
+ifdef CONFIG_MACH_DECSTATION
+  E2EFLAGS = -a
+else
+  E2EFLAGS =
+endif
+
+# elf2ecoff can only handle 32bit image
+
+ifdef CONFIG_32BIT
+	VMLINUZ = vmlinuz
+else
+	VMLINUZ = vmlinuz.32
+endif
+
+vmlinuz.32: vmlinuz
+	$(Q)$(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
+
+vmlinuz.ecoff: $(obj)/../elf2ecoff $(VMLINUZ)
+	$(Q)$(obj)/../elf2ecoff $(VMLINUZ) vmlinuz.ecoff $(E2EFLAGS)
+
+$(obj)/../elf2ecoff: $(src)/../elf2ecoff.c
+	$(Q)$(HOSTCC) -o $@ $^
+
+drop-sections	= .reginfo .mdebug .comment .note .pdr .options .MIPS.options
+strip-flags	= $(addprefix --remove-section=,$(drop-sections))
+
+OBJCOPYFLAGS_vmlinuz.bin := $(OBJCOPYFLAGS) -O binary $(strip-flags)
+vmlinuz.bin: vmlinuz
+	$(call if_changed,objcopy)
+
+OBJCOPYFLAGS_vmlinuz.srec := $(OBJCOPYFLAGS) -S -O srec $(strip-flags)
+vmlinuz.srec: vmlinuz
+	$(call if_changed,objcopy)
+
+clean:
+clean-files += *.o \
+	       vmlinu*
diff --git a/arch/mips/boot/compressed/dbg.c b/arch/mips/boot/compressed/dbg.c
new file mode 100644
index 0000000..ff4dc7a
--- /dev/null
+++ b/arch/mips/boot/compressed/dbg.c
@@ -0,0 +1,37 @@
+/*
+ * MIPS-specific debug support for pre-boot environment
+ *
+ * NOTE: putc() is board specific, if your board have a 16550 compatible uart,
+ * please select SYS_SUPPORTS_ZBOOT_UART16550 for your machine. othewise, you
+ * need to implement your own putc().
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+
+void __attribute__ ((weak)) putc(char c)
+{
+}
+
+void puts(const char *s)
+{
+	char c;
+	while ((c = *s++) != '\0') {
+		putc(c);
+		if (c == '\n')
+			putc('\r');
+	}
+}
+
+void puthex(unsigned long long val)
+{
+
+	unsigned char buf[10];
+	int i;
+	for (i = 7; i >= 0; i--) {
+		buf[i] = "0123456789ABCDEF"[val & 0x0F];
+		val >>= 4;
+	}
+	buf[8] = '\0';
+	puts(buf);
+}
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
new file mode 100644
index 0000000..67330c2
--- /dev/null
+++ b/arch/mips/boot/compressed/decompress.c
@@ -0,0 +1,126 @@
+/*
+ * Misc. bootloader code for many machines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Matt Porter <mporter@mvista.com> Derived from
+ * arch/ppc/boot/prep/misc.c
+ *
+ * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Author: Wu Zhangjin <wuzj@lemote.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/types.h>
+#include <linux/kernel.h>
+
+#include <asm/addrspace.h>
+
+/* These two variables specify the free mem region
+ * that can be used for temporary malloc area
+ */
+unsigned long free_mem_ptr;
+unsigned long free_mem_end_ptr;
+char *zimage_start;
+
+/* The linker tells us where the image is. */
+extern unsigned char __image_begin, __image_end;
+extern unsigned char __ramdisk_begin, __ramdisk_end;
+unsigned long initrd_size;
+
+/* debug interfaces  */
+extern void puts(const char *s);
+extern void puthex(unsigned long long val);
+
+void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while (1)
+		;	/* Halt */
+}
+
+/* activate the code for pre-boot environment */
+#define STATIC static
+
+#ifdef CONFIG_KERNEL_GZIP
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	int i;
+	const char *s = src;
+	char *d = dest;
+
+	for (i = 0; i < n; i++)
+		d[i] = s[i];
+	return dest;
+}
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+void *memset(void *s, int c, size_t n)
+{
+	int i;
+	char *ss = s;
+
+	for (i = 0; i < n; i++)
+		ss[i] = c;
+	return s;
+}
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+void decompress_kernel(unsigned long boot_heap_start)
+{
+	int zimage_size;
+
+	/*
+	 * We link ourself to an arbitrary low address.  When we run, we
+	 * relocate outself to that address.  __image_beign points to
+	 * the part of the image where the zImage is. -- Tom
+	 */
+	zimage_start = (char *)(unsigned long)(&__image_begin);
+	zimage_size = (unsigned long)(&__image_end) -
+	    (unsigned long)(&__image_begin);
+
+	/*
+	 * The zImage and initrd will be between start and _end, so they've
+	 * already been moved once.  We're good to go now. -- Tom
+	 */
+	puts("zimage at:     ");
+	puthex((unsigned long)zimage_start);
+	puts(" ");
+	puthex((unsigned long)(zimage_size + zimage_start));
+	puts("\n");
+
+	if (initrd_size) {
+		puts("initrd at:     ");
+		puthex((unsigned long)(&__ramdisk_begin));
+		puts(" ");
+		puthex((unsigned long)(&__ramdisk_end));
+		puts("\n");
+	}
+
+	/* this area are prepared for mallocing when decompressing */
+	free_mem_ptr = boot_heap_start;
+	free_mem_end_ptr = boot_heap_start + BOOT_HEAP_SIZE;
+
+	/* Display standard Linux/MIPS boot prompt for kernel args */
+	puts("Uncompressing Linux at load address ");
+	puthex(VMLINUX_LOAD_ADDRESS_ULL);
+	puts("\n");
+	/* Decompress the kernel with according algorithm */
+	decompress(zimage_start, zimage_size, 0, 0,
+		   (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);
+	/* FIXME: is there a need to flush cache here? */
+	puts("Now, booting the kernel...\n");
+}
diff --git a/arch/mips/boot/compressed/dummy.c b/arch/mips/boot/compressed/dummy.c
new file mode 100644
index 0000000..31dbf45
--- /dev/null
+++ b/arch/mips/boot/compressed/dummy.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+	return 0;
+}
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
new file mode 100644
index 0000000..4e65a84
--- /dev/null
+++ b/arch/mips/boot/compressed/head.S
@@ -0,0 +1,56 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995 Waldorf Electronics
+ * Written by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1995 - 1999 Ralf Baechle
+ * Copyright (C) 1996 Paul M. Antoine
+ * Modified for DECStation and hence R3000 support by Paul M. Antoine
+ * Further modifications by David S. Miller and Harald Koerfgen
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+	.set noreorder
+	.cprestore
+	LEAF(start)
+start:
+	/* Save boot rom start args */
+	move	s0, a0
+	move	s1, a1
+	move	s2, a2
+	move	s3, a3
+
+	/* Clear BSS */
+	PTR_LA	a0, _edata
+	PTR_LA	a2, _end
+1:	sw	zero, 0(a0)
+	bne	a2, a0, 1b
+	 addiu	a0, a0, 4
+
+	PTR_LA	a0, (.heap)          /* heap address */
+	PTR_LA  sp, (.stack + 8192)  /* stack address */
+
+	PTR_LA	ra, 2f
+	PTR_LA	k0, decompress_kernel
+	jr	k0
+	 nop
+2:
+	move	a0, s0
+	move	a1, s1
+	move	a2, s2
+	move	a3, s3
+	PTR_LI	k0, KERNEL_ENTRY
+	jr	k0
+	 nop
+3:
+	b	3b
+	 nop
+	END(start)
+
+	.comm .heap,BOOT_HEAP_SIZE,4
+	.comm .stack,4096*2,4
diff --git a/arch/mips/boot/compressed/ld.script b/arch/mips/boot/compressed/ld.script
new file mode 100644
index 0000000..29e9f4c
--- /dev/null
+++ b/arch/mips/boot/compressed/ld.script
@@ -0,0 +1,150 @@
+OUTPUT_ARCH(mips)
+ENTRY(start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___dbe_table = .;	/* Exception table for data bus errors */
+  __dbe_table : { *(__dbe_table) }
+  __stop___dbe_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;
+
+  . = ALIGN(8192);
+  .data.init_task : { *(.data.init_task) }
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+
+   /* Put the compressed image here, so bss is on the end. */
+   __image_begin = .;
+   *(.image)
+   __image_end = .;
+   /* Align the initial ramdisk image (INITRD) on page boundaries. */
+   . = ALIGN(4096);
+   __ramdisk_begin = .;
+   *(.initrd)
+   __ramdisk_end = .;
+   . = ALIGN(4096);
+
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __bss_start = .;
+  _fbss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   .  = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+  }
+
+  /* Sections to be discarded */
+  /DISCARD/ :
+  {
+        *(.text.exit)
+        *(.data.exit)
+        *(.exitcall.exit)
+  }
+
+  /* This is the MIPS specific mdebug section.  */
+  .mdebug : { *(.mdebug) }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+  .comment : { *(.comment) }
+  .note : { *(.note) }
+}
diff --git a/arch/mips/boot/compressed/uart-16550.c b/arch/mips/boot/compressed/uart-16550.c
new file mode 100644
index 0000000..c9caaf4
--- /dev/null
+++ b/arch/mips/boot/compressed/uart-16550.c
@@ -0,0 +1,43 @@
+/*
+ * 16550 compatible uart based serial debug support for zboot
+ */
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+#include <linux/init.h>
+
+#include <asm/addrspace.h>
+
+#if defined(CONFIG_MACH_LOONGSON) || defined(CONFIG_MIPS_MALTA)
+#define UART_BASE 0x1fd003f8
+#define PORT(offset) (CKSEG1ADDR(UART_BASE) + (offset))
+#endif
+
+#ifdef CONFIG_AR7
+#include <ar7.h>
+#define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
+#endif
+
+#ifndef PORT
+#error please define the serial port address for your own machine
+#endif
+
+static inline unsigned int serial_in(int offset)
+{
+	return *((char *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+	*((char *)PORT(offset)) = value;
+}
+
+void putc(char c)
+{
+	int timeout = 1024;
+
+	while (((serial_in(UART_LSR) & UART_LSR_THRE) == 0) && (timeout-- > 0))
+		;
+
+	serial_out(UART_TX, c);
+}
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 1394362..3e98763 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -9,7 +9,7 @@
 # Copyright (C) 2005-2009 Cavium Networks
 #
 
-obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
+obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
 obj-y += dma-octeon.o flash_setup.o
 obj-y += octeon-memcpy.o
 
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c
new file mode 100644
index 0000000..b6df538
--- /dev/null
+++ b/arch/mips/cavium-octeon/cpu.c
@@ -0,0 +1,52 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <linux/init.h>
+#include <linux/irqflags.h>
+#include <linux/notifier.h>
+#include <linux/prefetch.h>
+#include <linux/sched.h>
+
+#include <asm/cop2.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/octeon/octeon.h>
+
+static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action,
+	void *data)
+{
+	unsigned long flags;
+	unsigned int status;
+
+	switch (action) {
+	case CU2_EXCEPTION:
+		prefetch(&current->thread.cp2);
+		local_irq_save(flags);
+		KSTK_STATUS(current) |= ST0_CU2;
+		status = read_c0_status();
+		write_c0_status(status | ST0_CU2);
+		octeon_cop2_restore(&(current->thread.cp2));
+		write_c0_status(status & ~ST0_CU2);
+		local_irq_restore(flags);
+
+		return NOTIFY_BAD;	/* Don't call default notifier */
+	}
+
+	return NOTIFY_OK;		/* Let default notifier send signals */
+}
+
+static struct notifier_block cnmips_cu2_notifier = {
+	.notifier_call = cnmips_cu2_call,
+};
+
+static int cnmips_cu2_setup(void)
+{
+	return register_cu2_notifier(&cnmips_cu2_notifier);
+}
+early_initcall(cnmips_cu2_setup);
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index be711dd..cfdb4c2 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -159,6 +159,94 @@
 }
 device_initcall(octeon_rng_device_init);
 
+/* Octeon SMI/MDIO interface.  */
+static int __init octeon_mdiobus_device_init(void)
+{
+	struct platform_device *pd;
+	int ret = 0;
+
+	if (octeon_is_simulation())
+		return 0; /* No mdio in the simulator. */
+
+	/* The bus number is the platform_device id.  */
+	pd = platform_device_alloc("mdio-octeon", 0);
+	if (!pd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = platform_device_add(pd);
+	if (ret)
+		goto fail;
+
+	return ret;
+fail:
+	platform_device_put(pd);
+
+out:
+	return ret;
+
+}
+device_initcall(octeon_mdiobus_device_init);
+
+/* Octeon mgmt port Ethernet interface.  */
+static int __init octeon_mgmt_device_init(void)
+{
+	struct platform_device *pd;
+	int ret = 0;
+	int port, num_ports;
+
+	struct resource mgmt_port_resource = {
+		.flags	= IORESOURCE_IRQ,
+		.start	= -1,
+		.end	= -1
+	};
+
+	if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
+		return 0;
+
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+		num_ports = 1;
+	else
+		num_ports = 2;
+
+	for (port = 0; port < num_ports; port++) {
+		pd = platform_device_alloc("octeon_mgmt", port);
+		if (!pd) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		switch (port) {
+		case 0:
+			mgmt_port_resource.start = OCTEON_IRQ_MII0;
+			break;
+		case 1:
+			mgmt_port_resource.start = OCTEON_IRQ_MII1;
+			break;
+		default:
+			BUG();
+		}
+		mgmt_port_resource.end = mgmt_port_resource.start;
+
+		ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
+
+		if (ret)
+			goto fail;
+
+		ret = platform_device_add(pd);
+		if (ret)
+			goto fail;
+	}
+	return ret;
+fail:
+	platform_device_put(pd);
+
+out:
+	return ret;
+
+}
+device_initcall(octeon_mgmt_device_init);
+
 MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Platform driver for Octeon SOC");
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
index 3564830..5a5b6ba 100644
--- a/arch/mips/configs/ar7_defconfig
+++ b/arch/mips/configs/ar7_defconfig
@@ -10,7 +10,6 @@
 #
 # CONFIG_MACH_ALCHEMY is not set
 CONFIG_AR7=y
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -265,7 +264,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
-CONFIG_PROBE_INITRD_HEADER=y
 # CONFIG_FREEZER is not set
 
 #
@@ -1053,7 +1051,9 @@
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index 94b7d57..267bd46 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 CONFIG_BCM47XX=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1853,7 +1852,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/bcm63xx_defconfig b/arch/mips/configs/bcm63xx_defconfig
index ea00c18..7fee027 100644
--- a/arch/mips/configs/bcm63xx_defconfig
+++ b/arch/mips/configs/bcm63xx_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 CONFIG_BCM63XX=y
 # CONFIG_MIPS_COBALT is not set
@@ -942,7 +941,9 @@
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 13d9eb4..c2f06e3 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1237,7 +1236,7 @@
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_SB1XXX_CORELIS is not set
 # CONFIG_RUNTIME_DEBUG is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 185df23..72b7e45 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -783,7 +782,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,38400"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/cavium-octeon_defconfig b/arch/mips/configs/cavium-octeon_defconfig
index 7afaa28..c8507bc 100644
--- a/arch/mips/configs/cavium-octeon_defconfig
+++ b/arch/mips/configs/cavium-octeon_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -269,7 +268,6 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 CONFIG_CLASSIC_RCU=y
-# CONFIG_PROBE_INITRD_HEADER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -822,7 +820,7 @@
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 6c8cca8..49e6131 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
@@ -1126,7 +1125,7 @@
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index dbdf3bb..68e90cd 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1090,7 +1089,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index fa68144..9081283 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1090,7 +1089,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index d73f1de..dabf030 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 CONFIG_MIPS_DB1200=y
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1172,7 +1171,9 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=48M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index ec3e028a..a151313 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1390,7 +1389,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7631dae..6b64339 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -23,7 +23,6 @@
 CONFIG_MIPS_DB1550=y
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1207,7 +1206,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 9e65e6a..cbb4d86 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MACH_JAZZ is not set
@@ -882,7 +881,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 1bd84d4..52968c4 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -561,7 +560,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
deleted file mode 100644
index 1995d43..0000000
--- a/arch/mips/configs/excite_defconfig
+++ /dev/null
@@ -1,1335 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:31 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-CONFIG_BASLER_EXCITE=y
-# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_COHERENT=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_CPU_RM9K=y
-CONFIG_MIPS_RM9122=y
-CONFIG_SERIAL_RM9000=y
-CONFIG_GPI_RM9000=y
-CONFIG_WDT_RM9000=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-# CONFIG_PREEMPT_NONE is not set
-# CONFIG_PREEMPT_VOLUNTARY is not set
-CONFIG_PREEMPT=y
-CONFIG_PREEMPT_BKL=y
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-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 is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-# CONFIG_RELAY is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=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_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# 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=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP 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=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-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=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# 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
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# 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_IEEE80211 is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_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
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND_IDS=y
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_BASLER_EXCITE is not set
-# CONFIG_MTD_NAND_CAFE is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND 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=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
-# CONFIG_BLK_DEV_RAM 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_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=m
-# CONFIG_SCSI_NETLINK is not set
-# CONFIG_SCSI_PROC_FS is not set
-
-#
-# 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=y
-
-#
-# 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=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG 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=m
-# CONFIG_AIC94XX_DEBUG 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_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
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
-# CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET 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_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=m
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_RSA is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_WDT_RM9K_GPI=m
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_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
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# 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_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=m
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND 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=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-CONFIG_USB_EHCI_HCD=y
-# CONFIG_USB_EHCI_SPLIT_ISO is not set
-# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
-# CONFIG_USB_ISP116X_HCD is not set
-CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
-# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# may also be needed; see USB_STORAGE Help for more information
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=m
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
-
-#
-# USB port drivers
-#
-
-#
-# USB Serial Converter support
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# 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_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_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=y
-# CONFIG_HUGETLB_PAGE is not set
-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_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-# 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=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# 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_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=m
-CONFIG_CRYPTO_MANAGER=m
-# CONFIG_CRYPTO_HMAC is not set
-CONFIG_CRYPTO_XCBC=m
-# 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=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-# CONFIG_CRYPTO_DES is not set
-CONFIG_CRYPTO_FCRYPT=m
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
-CONFIG_CRYPTO_CAMELLIA=m
-# 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_CRC32=y
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig
index 0197f0d..a09dd03 100644
--- a/arch/mips/configs/fuloong2e_defconfig
+++ b/arch/mips/configs/fuloong2e_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.31-rc1
-# Thu Jul  2 22:37:00 2009
+# Linux kernel version: 2.6.32-rc4
+# Fri Oct 16 13:18:01 2009
 #
 CONFIG_MIPS=y
 
@@ -10,8 +10,8 @@
 #
 # CONFIG_MACH_ALCHEMY is not set
 # CONFIG_AR7 is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -105,6 +105,8 @@
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
 # CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
 CONFIG_CPU_LOONGSON2=y
 CONFIG_SYS_HAS_CPU_LOONGSON2E=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
@@ -135,12 +137,16 @@
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 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_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
 CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_PHYS_ADDR_T_64BIT=y
@@ -148,6 +154,7 @@
 CONFIG_VIRT_TO_BUS=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_TICK_ONESHOT=y
 CONFIG_NO_HZ=y
@@ -180,6 +187,12 @@
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION="-fuloong2e"
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
@@ -193,11 +206,12 @@
 #
 # RCU Subsystem
 #
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=64
+# CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -235,18 +249,16 @@
 CONFIG_AIO=y
 
 #
-# Performance Counters
+# Kernel Performance Events And Counters
 #
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_SYSCALL_WRAPPERS=y
@@ -255,8 +267,8 @@
 # GCOV-based kernel profiling
 #
 # CONFIG_GCOV_KERNEL is not set
-# CONFIG_SLOW_WORK is not set
-# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLOW_WORK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
@@ -283,7 +295,7 @@
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_FREEZER is not set
+CONFIG_FREEZER=y
 
 #
 # Bus options (PCI, PCMCIA, EISA, ISA, TC)
@@ -321,9 +333,14 @@
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_PM=y
 # CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
 # CONFIG_SUSPEND is not set
-# CONFIG_HIBERNATION is not set
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/hda3"
+# CONFIG_PM_RUNTIME is not set
 CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
 
 #
 # Networking options
@@ -442,6 +459,7 @@
 CONFIG_IP_NF_ARP_MANGLE=m
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -473,6 +491,7 @@
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
 # CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
 CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
@@ -481,7 +500,6 @@
 #
 # CFG80211 needs to be enabled for MAC80211
 #
-CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 CONFIG_NET_9P=m
@@ -495,6 +513,7 @@
 # Generic Driver Options
 #
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
@@ -504,9 +523,9 @@
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=m
 # CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_CONCAT is not set
 # CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_TESTS is not set
 
 #
 # User Modules And Translation Layers
@@ -820,6 +839,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -867,10 +887,7 @@
 # CONFIG_SFC is not set
 # CONFIG_BE2NET is not set
 # CONFIG_TR is not set
-
-#
-# Wireless LAN
-#
+CONFIG_WLAN=y
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
 
@@ -886,6 +903,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_USB_CDC_PHONET is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -933,12 +951,16 @@
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
 CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -946,6 +968,7 @@
 CONFIG_MOUSE_PS2_SYNAPTICS=y
 CONFIG_MOUSE_PS2_TRACKPOINT=y
 # CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
 # CONFIG_MOUSE_PS2_TOUCHKIT is not set
 CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_APPLETOUCH is not set
@@ -1015,6 +1038,7 @@
 CONFIG_DEVPORT=y
 CONFIG_I2C=m
 CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
 CONFIG_I2C_CHARDEV=m
 CONFIG_I2C_HELPER_AUTO=y
 
@@ -1070,9 +1094,6 @@
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -1088,7 +1109,6 @@
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
-# CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_SSB_POSSIBLE=y
 
@@ -1105,6 +1125,7 @@
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
 # CONFIG_AB3100_CORE is not set
@@ -1114,6 +1135,7 @@
 #
 # Graphics support
 #
+CONFIG_VGA_ARB=y
 # CONFIG_DRM is not set
 # CONFIG_VGASTATE is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=m
@@ -1198,6 +1220,7 @@
 # CONFIG_LOGO is not set
 CONFIG_SOUND=y
 CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
@@ -1304,7 +1327,6 @@
 CONFIG_AC97_BUS=m
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
 CONFIG_HIDRAW=y
 
 #
@@ -1356,6 +1378,7 @@
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_ISP1760_HCD=m
+# CONFIG_USB_ISP1362_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1453,6 +1476,7 @@
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_AEC is not set
 # CONFIG_UIO_SERCOS3 is not set
+# CONFIG_UIO_PCI_GENERIC is not set
 
 #
 # TI VLYNQ
@@ -1469,10 +1493,10 @@
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=m
-CONFIG_EXT4DEV_COMPAT=y
 CONFIG_EXT4_FS_XATTR=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+# CONFIG_EXT4_DEBUG is not set
 CONFIG_FS_XIP=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
@@ -1489,6 +1513,7 @@
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_FILE_LOCKING=y
 CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
@@ -1557,7 +1582,6 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
 CONFIG_NFS_V3=y
@@ -1666,6 +1690,7 @@
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=2048
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
@@ -1678,13 +1703,14 @@
 CONFIG_RING_BUFFER=y
 CONFIG_EVENT_TRACING=y
 CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
 # CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
@@ -1742,11 +1768,13 @@
 #
 CONFIG_CRYPTO_HMAC=y
 # CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
 
 #
 # Digest
 #
 # CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_GHASH=m
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index f14d38b..222d7ec 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1188,7 +1187,7 @@
 CONFIG_DYNAMIC_PRINTK_DEBUG=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 1fc73aa..ed84b4c 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -940,7 +939,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/ip28_defconfig b/arch/mips/configs/ip28_defconfig
index 539dccb..dab2e5a 100644
--- a/arch/mips/configs/ip28_defconfig
+++ b/arch/mips/configs/ip28_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -816,7 +815,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index d934bde..1841c88 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1126,7 +1125,7 @@
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index d22df61..14c2ab3 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MACH_JAZZ=y
@@ -1374,7 +1373,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 5380f1f..4d66c44 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -835,7 +834,7 @@
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig
index 044074d..08d481e 100644
--- a/arch/mips/configs/lasat_defconfig
+++ b/arch/mips/configs/lasat_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -798,7 +797,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
new file mode 100644
index 0000000..b71a0a4
--- /dev/null
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -0,0 +1,1835 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc6
+# Mon Nov  9 23:42:42 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+CONFIG_MACH_LOONGSON=y
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+# CONFIG_LEMOTE_FULOONG2E is not set
+CONFIG_LEMOTE_MACH2F=y
+CONFIG_CS5536=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2E is not set
+CONFIG_CPU_LOONGSON2F=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
+CONFIG_CPU_LOONGSON2=y
+CONFIG_SYS_HAS_CPU_LOONGSON2F=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=64
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_SYSCALL_WRAPPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION_NVS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/hda3"
+# CONFIG_PM_RUNTIME is not set
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+CONFIG_DEFAULT_BIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="bic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+# CONFIG_NET_EMATCH_CMP is not set
+# CONFIG_NET_EMATCH_NBYTE is not set
+# CONFIG_NET_EMATCH_U32 is not set
+# CONFIG_NET_EMATCH_META is not set
+# CONFIG_NET_EMATCH_TEXT is not set
+CONFIG_NET_CLS_ACT=y
+# CONFIG_NET_ACT_POLICE is not set
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=m
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+# CONFIG_PNP is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+
+#
+# Other IDE chipsets support
+#
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+# CONFIG_BLK_DEV_4DRIVES is not set
+# CONFIG_BLK_DEV_ALI14XX is not set
+# CONFIG_BLK_DEV_DTC2278 is not set
+# CONFIG_BLK_DEV_HT6560B is not set
+# CONFIG_BLK_DEV_QD65XX is not set
+# CONFIG_BLK_DEV_UMC8672 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=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=m
+# 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
+CONFIG_SCSI_MULTI_LUN=y
+# 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
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_TR is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_PRE80211=y
+# CONFIG_STRIP is not set
+# CONFIG_WAVELAN is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_ATMEL is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_PS2_ALPS is not set
+# CONFIG_MOUSE_PS2_LOGIPS2PP is not set
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+# CONFIG_MOUSE_PS2_TRACKPOINT is not set
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_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=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_STALDRV is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_FOURPORT=y
+# CONFIG_SERIAL_8250_ACCENT is not set
+# CONFIG_SERIAL_8250_BOCA is not set
+# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
+# CONFIG_SERIAL_8250_HUB6 is not set
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_THERMAL=y
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_STRADIS is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE 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_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# 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=y
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_VIA 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_CARMINE is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_7x14=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+CONFIG_FONT_MINI_4x6=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+CONFIG_FONT_10x18=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+CONFIG_SND_CS5535AUDIO=m
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_MIPS is not set
+# CONFIG_SND_USB is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_OTG_WHITELIST=y
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_ET131X is not set
+# CONFIG_USB_IP_COMMON is not set
+# CONFIG_PRISM2_USB is not set
+# CONFIG_ECHO is not set
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_ALTERA_PCIE_CHDMA is not set
+# CONFIG_RTL8187SE is not set
+# CONFIG_RTL8192SU is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+
+#
+# Qualcomm MSM Camera And Video
+#
+
+#
+# Camera Sensor Selection
+#
+# CONFIG_INPUT_GPIO is not set
+# CONFIG_DST is not set
+# CONFIG_POHMELFS is not set
+# CONFIG_B3DFG is not set
+# CONFIG_PLAN9AUTH is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_VME_BUS is not set
+
+#
+# RAR Register Driver
+#
+# CONFIG_RAR_REGISTER is not set
+# CONFIG_IIO is not set
+CONFIG_FB_SM7XX=y
+CONFIG_FB_SM7XX_ACCEL=y
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+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_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=m
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 3f01870..d3c6012 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -10,7 +10,6 @@
 #
 CONFIG_ZONE_DMA=y
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1591,7 +1590,7 @@
 # CONFIG_DYNAMIC_PRINTK_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index d001f7e8..6a325c0 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1366,7 +1365,9 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index 7358454..f77a34e 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -635,7 +634,9 @@
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 8c720e5..1720305 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -817,7 +816,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
index ecbc030..000d185 100644
--- a/arch/mips/configs/msp71xx_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1412,7 +1411,7 @@
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 # CONFIG_MIPS_UNCACHED is not set
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 9477f04..144b94d 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 CONFIG_MACH_ALCHEMY=y
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -3018,7 +3017,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index be8091e..ddf67f6 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1083,7 +1082,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index e74ba79..5ec6083 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1200,7 +1199,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 1d896fd..6647642 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -23,7 +23,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1193,7 +1192,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/pnx8335-stb225_defconfig b/arch/mips/configs/pnx8335-stb225_defconfig
index fef4d31..848344d5 100644
--- a/arch/mips/configs/pnx8335-stb225_defconfig
+++ b/arch/mips/configs/pnx8335-stb225_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1034,7 +1033,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
 # CONFIG_KERNEL_TESTS is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index e10c711..9d721fd 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1215,7 +1214,9 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index 5ed3c8d..ab07ec0 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1205,7 +1204,9 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS1,38400n8 root=/dev/nfs ip=bootp"
+# CONFIG_CMDLINE_OVERRIDE is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/configs/powertv_defconfig b/arch/mips/configs/powertv_defconfig
new file mode 100644
index 0000000..7291633
--- /dev/null
+++ b/arch/mips/configs/powertv_defconfig
@@ -0,0 +1,1550 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.31-rc5
+# Fri Aug 28 14:49:33 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+CONFIG_POWERTV=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+# CONFIG_MIN_RUNTIME_RESOURCES is not set
+# CONFIG_BOOTLOADER_DRIVER is not set
+CONFIG_BOOTLOADER_FAMILY="R2"
+CONFIG_CSRC_POWERTV=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_KEXEC is not set
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+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_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+CONFIG_TIMERFD=y
+# CONFIG_EVENTFD is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_PCI_QUIRKS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY 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"
+# CONFIG_PROBE_INITRD_HEADER is not set
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES 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 is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# 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=y
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=y
+# CONFIG_IP_NF_TARGET_REJECT is not set
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+# CONFIG_IP_NF_ARP_MANGLE is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=y
+# CONFIG_IP6_NF_MATCH_AH is not set
+# CONFIG_IP6_NF_MATCH_EUI64 is not set
+# CONFIG_IP6_NF_MATCH_FRAG is not set
+# CONFIG_IP6_NF_MATCH_OPTS is not set
+# CONFIG_IP6_NF_MATCH_HL is not set
+# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
+# CONFIG_IP6_NF_MATCH_MH is not set
+# CONFIG_IP6_NF_MATCH_RT is not set
+# CONFIG_IP6_NF_TARGET_HL is not set
+# CONFIG_IP6_NF_TARGET_LOG is not set
+CONFIG_IP6_NF_FILTER=y
+# CONFIG_IP6_NF_TARGET_REJECT is not set
+# CONFIG_IP6_NF_MANGLE is not set
+# CONFIG_IP6_NF_RAW 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_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+CONFIG_NET_SCH_TBF=y
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_INTEL_VR_NOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# 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
+# 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_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_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_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_ARCNET is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF 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_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_BE2NET is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_RTL8150=y
+# CONFIG_USB_USBNET 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_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=y
+CONFIG_USB_SERIAL_CONSOLE=y
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP210X=y
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# 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_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE 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_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS 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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_BOOT_TRACER is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="rw dhash_entries=1024 ihash_entries=1024 ip=10.0.1.3:10.0.1.1:10.0.1.1:255.255.255.0:zeus:eth0: root=/dev/nfs nfsroot=/nfsroot/cramfs,wsize=512,rsize=512,tcp nokgdb console=ttyUSB0,115200 memsize=252M"
+# CONFIG_CMDLINE_OVERRIDE is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_RUNTIME_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig
index f40c3a0..57a5048 100644
--- a/arch/mips/configs/rb532_defconfig
+++ b/arch/mips/configs/rb532_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1204,7 +1203,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig
index 6c6a19a..21c2022 100644
--- a/arch/mips/configs/rbtx49xx_defconfig
+++ b/arch/mips/configs/rbtx49xx_defconfig
@@ -10,7 +10,6 @@
 #
 # CONFIG_MACH_ALCHEMY is not set
 # CONFIG_AR7 is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_BCM63XX is not set
 # CONFIG_MIPS_COBALT is not set
@@ -284,7 +283,6 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_PROBE_INITRD_HEADER is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -1063,7 +1061,7 @@
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index e53b8d0..7903628 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1694,7 +1693,7 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 7f38c0b..7f07bf0 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -961,7 +960,7 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_SB1XXX_CORELIS is not set
 
 #
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index b505988..c54d112 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -892,7 +891,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b06a716..e7c5cd3 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -895,7 +894,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=32M console=ttyVR0,115200"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 46512cf..b50032b 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
@@ -1077,7 +1076,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 # CONFIG_SAMPLES is not set
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="cca=3 mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index b437eb7..c02ba08 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -9,7 +9,6 @@
 # Machine selection
 #
 # CONFIG_MACH_ALCHEMY is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -755,7 +754,9 @@
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 06acc74..a35bc41 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -887,7 +886,9 @@
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyS0,115200n8"
+# CONFIG_CMDLINE_OVERRIDE is not set
 
 #
 # Security options
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 69feaf8..e3d68d6 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -22,7 +22,6 @@
 # CONFIG_MIPS_DB1550 is not set
 # CONFIG_MIPS_DB1200 is not set
 # CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
@@ -824,7 +823,7 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_BOOL is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_RUNTIME_DEBUG is not set
 
diff --git a/arch/mips/fw/arc/cmdline.c b/arch/mips/fw/arc/cmdline.c
index 4ca4eef..5c8603c8 100644
--- a/arch/mips/fw/arc/cmdline.c
+++ b/arch/mips/fw/arc/cmdline.c
@@ -16,11 +16,6 @@
 
 #undef DEBUG_CMDLINE
 
-char * __init prom_getcmdline(void)
-{
-	return arcs_cmdline;
-}
-
 static char *ignored[] = {
 	"ConsoleIn=",
 	"ConsoleOut=",
diff --git a/arch/mips/include/asm/asm-offsets.h b/arch/mips/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/mips/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index f5dfaf6..09eee09 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -67,9 +67,9 @@
 #define MACH_LEMOTE_ML2F7      3
 #define MACH_LEMOTE_YL2F89     4
 #define MACH_DEXXON_GDIUM2F10  5
-#define MACH_LOONGSON_END      6
-
-#define CL_SIZE			COMMAND_LINE_SIZE
+#define MACH_LEMOTE_NAS        6
+#define MACH_LEMOTE_LL2F       7
+#define MACH_LOONGSON_END      8
 
 extern char *system_type;
 const char *get_system_type(void);
@@ -107,7 +107,7 @@
 /*
  * Initial kernel command line, usually setup by prom_init()
  */
-extern char arcs_cmdline[CL_SIZE];
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
 
 /*
  * Registers a0, a1, a3 and a4 as passed to the kernel entry by firmware
diff --git a/arch/mips/include/asm/clock.h b/arch/mips/include/asm/clock.h
new file mode 100644
index 0000000..83894aa
--- /dev/null
+++ b/arch/mips/include/asm/clock.h
@@ -0,0 +1,64 @@
+#ifndef __ASM_MIPS_CLOCK_H
+#define __ASM_MIPS_CLOCK_H
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/clk.h>
+
+extern void (*cpu_wait) (void);
+
+struct clk;
+
+struct clk_ops {
+	void (*init) (struct clk *clk);
+	void (*enable) (struct clk *clk);
+	void (*disable) (struct clk *clk);
+	void (*recalc) (struct clk *clk);
+	int (*set_rate) (struct clk *clk, unsigned long rate, int algo_id);
+	long (*round_rate) (struct clk *clk, unsigned long rate);
+};
+
+struct clk {
+	struct list_head node;
+	const char *name;
+	int id;
+	struct module *owner;
+
+	struct clk *parent;
+	struct clk_ops *ops;
+
+	struct kref kref;
+
+	unsigned long rate;
+	unsigned long flags;
+};
+
+#define CLK_ALWAYS_ENABLED	(1 << 0)
+#define CLK_RATE_PROPAGATES	(1 << 1)
+
+/* Should be defined by processor-specific code */
+void arch_init_clk_ops(struct clk_ops **, int type);
+
+int clk_init(void);
+
+int __clk_enable(struct clk *);
+void __clk_disable(struct clk *);
+
+void clk_recalc_rate(struct clk *);
+
+int clk_register(struct clk *);
+void clk_unregister(struct clk *);
+
+/* the exported API, in addition to clk_set_rate */
+/**
+ * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ * @algo_id: algorithm id to be passed down to ops->set_rate
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id);
+
+#endif				/* __ASM_MIPS_CLOCK_H */
diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h
new file mode 100644
index 0000000..6b04c98
--- /dev/null
+++ b/arch/mips/include/asm/cop2.h
@@ -0,0 +1,23 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Wind River Systems,
+ *   written by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_COP2_H
+#define __ASM_COP2_H
+
+enum cu2_ops {
+	CU2_EXCEPTION,
+	CU2_LWC2_OP,
+	CU2_LDC2_OP,
+	CU2_SWC2_OP,
+	CU2_SDC2_OP,
+};
+
+extern int register_cu2_notifier(struct notifier_block *nb);
+extern int cu2_notifier_call_chain(unsigned long val, void *v);
+
+#endif /* __ASM_COP2_H */
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 4b96d1a..cf373a9 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -154,6 +154,8 @@
 #define PRID_REV_VR4181A	0x0070	/* Same as VR4122 */
 #define PRID_REV_VR4130		0x0080
 #define PRID_REV_34K_V1_0_2	0x0022
+#define PRID_REV_LOONGSON2E	0x0002
+#define PRID_REV_LOONGSON2F	0x0003
 
 /*
  * Older processors used to encode processor version and revision in two
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 7990694..7a6a35d 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -326,7 +326,6 @@
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
 	dump_task_fpu(tsk, elf_fpregs)
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /* This yields a mask that user programs can use to figure out what
diff --git a/arch/mips/include/asm/fcntl.h b/arch/mips/include/asm/fcntl.h
index 7c6681a..e482fe9 100644
--- a/arch/mips/include/asm/fcntl.h
+++ b/arch/mips/include/asm/fcntl.h
@@ -19,7 +19,7 @@
 #define FASYNC		0x1000	/* fcntl, for BSD compatibility */
 #define O_LARGEFILE	0x2000	/* allow large file opens */
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 8a3ef24..7fcef8e 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -28,15 +28,7 @@
 struct sigcontext;
 struct sigcontext32;
 
-extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
-extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
-extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
 extern void fpu_emulator_init_fpu(void);
-extern int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern int fpu_emulator_restore_context(struct sigcontext __user *sc);
 extern void _init_fpu(void);
 extern void _save_fp(struct task_struct *);
 extern void _restore_fp(struct task_struct *);
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index e518957..aecada6 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -25,17 +25,27 @@
 
 #include <asm/break.h>
 #include <asm/inst.h>
+#include <asm/local.h>
+
+#ifdef CONFIG_DEBUG_FS
 
 struct mips_fpu_emulator_stats {
-	unsigned int emulated;
-	unsigned int loads;
-	unsigned int stores;
-	unsigned int cp1ops;
-	unsigned int cp1xops;
-	unsigned int errors;
+	local_t emulated;
+	local_t loads;
+	local_t stores;
+	local_t cp1ops;
+	local_t cp1xops;
+	local_t errors;
 };
 
-extern struct mips_fpu_emulator_stats fpuemustats;
+DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+
+#define MIPS_FPU_EMU_INC_STATS(M)					\
+	cpu_local_wrap(__local_inc(&__get_cpu_var(fpuemustats).M))
+
+#else
+#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)
+#endif /* CONFIG_DEBUG_FS */
 
 extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
 	unsigned long cpc);
diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h
index 40a8c17..3986cd8 100644
--- a/arch/mips/include/asm/ftrace.h
+++ b/arch/mips/include/asm/ftrace.h
@@ -1 +1,90 @@
-/* empty */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef _ASM_MIPS_FTRACE_H
+#define _ASM_MIPS_FTRACE_H
+
+#ifdef CONFIG_FUNCTION_TRACER
+
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+#define MCOUNT_INSN_SIZE 4		/* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+extern void _mcount(void);
+#define mcount _mcount
+
+#define safe_load(load, src, dst, error)		\
+do {							\
+	asm volatile (					\
+		"1: " load " %[" STR(dst) "], 0(%[" STR(src) "])\n"\
+		"   li %[" STR(error) "], 0\n"		\
+		"2:\n"					\
+							\
+		".section .fixup, \"ax\"\n"		\
+		"3: li %[" STR(error) "], 1\n"		\
+		"   j 2b\n"				\
+		".previous\n"				\
+							\
+		".section\t__ex_table,\"a\"\n\t"	\
+		STR(PTR) "\t1b, 3b\n\t"			\
+		".previous\n"				\
+							\
+		: [dst] "=&r" (dst), [error] "=r" (error)\
+		: [src] "r" (src)			\
+		: "memory"				\
+	);						\
+} while (0)
+
+#define safe_store(store, src, dst, error)	\
+do {						\
+	asm volatile (				\
+		"1: " store " %[" STR(src) "], 0(%[" STR(dst) "])\n"\
+		"   li %[" STR(error) "], 0\n"	\
+		"2:\n"				\
+						\
+		".section .fixup, \"ax\"\n"	\
+		"3: li %[" STR(error) "], 1\n"	\
+		"   j 2b\n"			\
+		".previous\n"			\
+						\
+		".section\t__ex_table,\"a\"\n\t"\
+		STR(PTR) "\t1b, 3b\n\t"		\
+		".previous\n"			\
+						\
+		: [error] "=r" (error)		\
+		: [dst] "r" (dst), [src] "r" (src)\
+		: "memory"			\
+	);					\
+} while (0)
+
+#define safe_load_code(dst, src, error) \
+	safe_load(STR(lw), src, dst, error)
+#define safe_store_code(src, dst, error) \
+	safe_store(STR(sw), src, dst, error)
+
+#define safe_load_stack(dst, src, error) \
+	safe_load(STR(PTR_L), src, dst, error)
+
+#define safe_store_stack(src, dst, error) \
+	safe_store(STR(PTR_S), src, dst, error)
+
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+	return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+
+#endif /*  CONFIG_DYNAMIC_FTRACE */
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_FUNCTION_TRACER */
+#endif /* _ASM_MIPS_FTRACE_H */
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index 09b08d0..0696036 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -113,36 +113,11 @@
 
 #endif
 
-/*
- * do_IRQ handles all normal device IRQ's (the special
- * SMP cross-CPU interrupts have their own specific
- * handlers).
- *
- * Ideally there should be away to get this into kernel/irq/handle.c to
- * avoid the overhead of a call for just a tiny function ...
- */
-#define do_IRQ(irq)							\
-do {									\
-	irq_enter();							\
-	__DO_IRQ_SMTC_HOOK(irq);					\
-	generic_handle_irq(irq);					\
-	irq_exit();							\
-} while (0)
+extern void do_IRQ(unsigned int irq);
 
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-/*
- * To avoid inefficient and in some cases pathological re-checking of
- * IRQ affinity, we have this variant that skips the affinity check.
- */
 
-
-#define do_IRQ_no_affinity(irq)						\
-do {									\
-	irq_enter();							\
-	__NO_AFFINITY_IRQ_SMTC_HOOK(irq);				\
-	generic_handle_irq(irq);					\
-	irq_exit();							\
-} while (0)
+extern void do_IRQ_no_affinity(unsigned int irq);
 
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 
diff --git a/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h b/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h
deleted file mode 100644
index 107104c..0000000
--- a/arch/mips/include/asm/mach-excite/cpu-feature-overrides.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Thomas Koeller <thomas.koeller@baslerweb.com>
- * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
- */
-#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Basler eXcite has an RM9122 processor.
- */
-#define cpu_has_watch		1
-#define cpu_has_mips16		0
-#define cpu_has_divec		0
-#define cpu_has_vce		0
-#define cpu_has_cache_cdex_p	0
-#define cpu_has_cache_cdex_s	0
-#define cpu_has_prefetch	1
-#define cpu_has_mcheck		0
-#define cpu_has_ejtag		0
-
-#define cpu_has_llsc		1
-#define cpu_has_vtag_icache	0
-#define cpu_has_dc_aliases	0
-#define cpu_has_ic_fills_f_dc	0
-#define cpu_has_dsp		0
-#define cpu_icache_snoops_remote_store	0
-#define cpu_has_mipsmt		0
-#define cpu_has_userlocal	0
-
-#define cpu_has_nofpuex		0
-#define cpu_has_64bits		1
-
-#define cpu_has_mips32r1	0
-#define cpu_has_mips32r2	0
-#define cpu_has_mips64r1	0
-#define cpu_has_mips64r2	0
-
-#define cpu_has_inclusive_pcaches	0
-
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	32
-
-#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-excite/excite.h b/arch/mips/include/asm/mach-excite/excite.h
deleted file mode 100644
index 4c29ba4..0000000
--- a/arch/mips/include/asm/mach-excite/excite.h
+++ /dev/null
@@ -1,154 +0,0 @@
-#ifndef __EXCITE_H__
-#define __EXCITE_H__
-
-#include <linux/init.h>
-#include <asm/addrspace.h>
-#include <asm/types.h>
-
-#define EXCITE_CPU_EXT_CLOCK 100000000
-
-#if !defined(__ASSEMBLY__)
-void __init excite_kgdb_init(void);
-void excite_procfs_init(void);
-extern unsigned long memsize;
-extern char modetty[];
-extern u32 unit_id;
-#endif
-
-/* Base name for XICAP devices */
-#define XICAP_NAME	"xicap_gpi"
-
-/* OCD register offsets */
-#define LKB0		0x0038
-#define LKB5		0x0128
-#define LKM5		0x012C
-#define LKB7		0x0138
-#define LKM7		0x013c
-#define LKB8		0x0140
-#define LKM8		0x0144
-#define LKB9		0x0148
-#define LKM9		0x014c
-#define LKB10		0x0150
-#define LKM10		0x0154
-#define LKB11		0x0158
-#define LKM11		0x015c
-#define LKB12		0x0160
-#define LKM12		0x0164
-#define LKB13		0x0168
-#define LKM13		0x016c
-#define LDP0		0x0200
-#define LDP1		0x0210
-#define LDP2		0x0220
-#define LDP3		0x0230
-#define INTPIN0		0x0A40
-#define INTPIN1		0x0A44
-#define INTPIN2		0x0A48
-#define INTPIN3		0x0A4C
-#define INTPIN4		0x0A50
-#define INTPIN5		0x0A54
-#define INTPIN6		0x0A58
-#define INTPIN7		0x0A5C
-
-
-
-
-/* TITAN register offsets */
-#define CPRR		0x0004
-#define CPDSR		0x0008
-#define CPTC0R		0x000c
-#define CPTC1R		0x0010
-#define CPCFG0		0x0020
-#define CPCFG1		0x0024
-#define CPDST0A		0x0028
-#define CPDST0B		0x002c
-#define CPDST1A		0x0030
-#define CPDST1B		0x0034
-#define CPXDSTA		0x0038
-#define CPXDSTB		0x003c
-#define CPXCISRA	0x0048
-#define CPXCISRB	0x004c
-#define CPGIG0ER	0x0050
-#define CPGIG1ER	0x0054
-#define CPGRWL		0x0068
-#define CPURSLMT	0x00f8
-#define UACFG		0x0200
-#define UAINTS		0x0204
-#define SDRXFCIE	0x4828
-#define SDTXFCIE	0x4928
-#define INTP0Status0	0x1B00
-#define INTP0Mask0	0x1B04
-#define INTP0Set0	0x1B08
-#define INTP0Clear0	0x1B0C
-#define GXCFG		0x5000
-#define GXDMADRPFX	0x5018
-#define GXDMA_DESCADR	0x501c
-#define GXCH0TDESSTRT	0x5054
-
-/* IRQ definitions */
-#define NMICONFIG		0xac0
-#define TITAN_MSGINT	0xc4
-#define TITAN_IRQ	((TITAN_MSGINT / 0x20) + 2)
-#define FPGA0_MSGINT	0x5a
-#define FPGA0_IRQ	((FPGA0_MSGINT / 0x20) + 2)
-#define FPGA1_MSGINT	0x7b
-#define FPGA1_IRQ	((FPGA1_MSGINT / 0x20) + 2)
-#define PHY_MSGINT	0x9c
-#define PHY_IRQ		((PHY_MSGINT   / 0x20) + 2)
-
-#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE)
-/* Pre-release units used interrupt pin #9 */
-#define USB_IRQ		11
-#else
-/* Re-designed units use interrupt pin #1 */
-#define USB_MSGINT	0x39
-#define USB_IRQ		((USB_MSGINT / 0x20) + 2)
-#endif
-#define TIMER_IRQ	12
-
-
-/* Device address ranges */
-#define EXCITE_OFFS_OCD		0x1fffc000
-#define	EXCITE_SIZE_OCD		(16 * 1024)
-#define EXCITE_PHYS_OCD		CPHYSADDR(EXCITE_OFFS_OCD)
-#define EXCITE_ADDR_OCD		CKSEG1ADDR(EXCITE_OFFS_OCD)
-
-#define EXCITE_OFFS_SCRAM 	0x1fffa000
-#define	EXCITE_SIZE_SCRAM	(8 << 10)
-#define EXCITE_PHYS_SCRAM 	CPHYSADDR(EXCITE_OFFS_SCRAM)
-#define EXCITE_ADDR_SCRAM 	CKSEG1ADDR(EXCITE_OFFS_SCRAM)
-
-#define EXCITE_OFFS_PCI_IO	0x1fff8000
-#define	EXCITE_SIZE_PCI_IO	(8 << 10)
-#define EXCITE_PHYS_PCI_IO	CPHYSADDR(EXCITE_OFFS_PCI_IO)
-#define EXCITE_ADDR_PCI_IO 	CKSEG1ADDR(EXCITE_OFFS_PCI_IO)
-
-#define EXCITE_OFFS_TITAN	0x1fff0000
-#define EXCITE_SIZE_TITAN	(32 << 10)
-#define EXCITE_PHYS_TITAN	CPHYSADDR(EXCITE_OFFS_TITAN)
-#define EXCITE_ADDR_TITAN	CKSEG1ADDR(EXCITE_OFFS_TITAN)
-
-#define EXCITE_OFFS_PCI_MEM	0x1ffe0000
-#define EXCITE_SIZE_PCI_MEM	(64 << 10)
-#define EXCITE_PHYS_PCI_MEM	CPHYSADDR(EXCITE_OFFS_PCI_MEM)
-#define EXCITE_ADDR_PCI_MEM	CKSEG1ADDR(EXCITE_OFFS_PCI_MEM)
-
-#define EXCITE_OFFS_FPGA	0x1ffdc000
-#define EXCITE_SIZE_FPGA	(16 << 10)
-#define EXCITE_PHYS_FPGA	CPHYSADDR(EXCITE_OFFS_FPGA)
-#define EXCITE_ADDR_FPGA	CKSEG1ADDR(EXCITE_OFFS_FPGA)
-
-#define EXCITE_OFFS_NAND	0x1ffd8000
-#define EXCITE_SIZE_NAND	(16 << 10)
-#define EXCITE_PHYS_NAND	CPHYSADDR(EXCITE_OFFS_NAND)
-#define EXCITE_ADDR_NAND	CKSEG1ADDR(EXCITE_OFFS_NAND)
-
-#define EXCITE_OFFS_BOOTROM	0x1f000000
-#define EXCITE_SIZE_BOOTROM	(8 << 20)
-#define EXCITE_PHYS_BOOTROM	CPHYSADDR(EXCITE_OFFS_BOOTROM)
-#define EXCITE_ADDR_BOOTROM	CKSEG1ADDR(EXCITE_OFFS_BOOTROM)
-
-/* FPGA address offsets */
-#define EXCITE_FPGA_DPR		0x0104	/* dual-ported ram */
-#define EXCITE_FPGA_SYSCTL	0x0200	/* system control register block */
-
-#endif /* __EXCITE_H__ */
diff --git a/arch/mips/include/asm/mach-excite/excite_fpga.h b/arch/mips/include/asm/mach-excite/excite_fpga.h
deleted file mode 100644
index 0a1ef69..0000000
--- a/arch/mips/include/asm/mach-excite/excite_fpga.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef EXCITE_FPGA_H_INCLUDED
-#define EXCITE_FPGA_H_INCLUDED
-
-
-/**
- * Address alignment of the individual FPGA bytes.
- * The address arrangement of the individual bytes of the FPGA is two
- * byte aligned at the embedded MK2 platform.
- */
-#ifdef EXCITE_CCI_FPGA_MK2
-typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
-#else
-typedef unsigned char excite_cci_fpga_align_t;
-#endif
-
-
-/**
- * Size of Dual Ported RAM.
- */
-#define EXCITE_DPR_SIZE 263
-
-
-/**
- * Size of Reserved Status Fields in Dual Ported RAM.
- */
-#define EXCITE_DPR_STATUS_SIZE 7
-
-
-
-/**
- * FPGA.
- * Hardware register layout of the FPGA interface. The FPGA must accessed
- * byte wise solely.
- * @see EXCITE_CCI_DPR_MK2
- */
-typedef struct excite_fpga {
-
-	/**
-	 * Dual Ported RAM.
-	 */
-	excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
-
-	/**
-	 * Status.
-	 */
-	excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
-
-#ifdef EXCITE_CCI_FPGA_MK2
-	/**
-	 * RM9000 Interrupt.
-	 * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
-	 */
-	excite_cci_fpga_align_t rm9k_int;
-#else
-	/**
-	 * MK2 Interrupt.
-	 * Write access initiates interrupt at the ARM processor of the MK2.
-	 */
-	excite_cci_fpga_align_t mk2_int;
-
-	excite_cci_fpga_align_t gap[0x1000-0x10f];
-
-	/**
-	 * IRQ Source/Acknowledge.
-	 */
-	excite_cci_fpga_align_t rm9k_irq_src;
-
-	/**
-	 * IRQ Mask.
-	 * Set bits enable the related interrupt.
-	 */
-	excite_cci_fpga_align_t rm9k_irq_mask;
-#endif
-
-
-} excite_fpga;
-
-
-
-#endif	/* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/include/asm/mach-excite/excite_nandflash.h b/arch/mips/include/asm/mach-excite/excite_nandflash.h
deleted file mode 100644
index c4cf614..0000000
--- a/arch/mips/include/asm/mach-excite/excite_nandflash.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __EXCITE_NANDFLASH_H__
-#define __EXCITE_NANDFLASH_H__
-
-/* Resource names */
-#define EXCITE_NANDFLASH_RESOURCE_REGS	"excite_nandflash_regs"
-
-#endif /* __EXCITE_NANDFLASH_H__ */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_eth.h b/arch/mips/include/asm/mach-excite/rm9k_eth.h
deleted file mode 100644
index 94705a4..0000000
--- a/arch/mips/include/asm/mach-excite/rm9k_eth.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#if !defined(__RM9K_ETH_H__)
-#define __RM9K_ETH_H__
-
-#define RM9K_GE_NAME			"rm9k_ge"
-
-/* Resource names */
-#define RM9K_GE_RESOURCE_MAC      	"rm9k_ge_mac"
-#define RM9K_GE_RESOURCE_MSTAT      	"rm9k_ge_mstat"
-#define RM9K_GE_RESOURCE_PKTPROC	"rm9k_ge_pktproc"
-#define RM9K_GE_RESOURCE_XDMA		"rm9k_ge_xdma"
-#define RM9K_GE_RESOURCE_FIFO_RX  	"rm9k_ge_fifo_rx"
-#define RM9K_GE_RESOURCE_FIFO_TX  	"rm9k_ge_fifo_tx"
-#define RM9K_GE_RESOURCE_FIFOMEM_RX  	"rm9k_ge_fifo_memory_rx"
-#define RM9K_GE_RESOURCE_FIFOMEM_TX  	"rm9k_ge_fifo_memory_tx"
-#define RM9K_GE_RESOURCE_PHY      	"rm9k_ge_phy"
-#define RM9K_GE_RESOURCE_DMADESC_RX  	"rm9k_ge_dmadesc_rx"
-#define RM9K_GE_RESOURCE_DMADESC_TX  	"rm9k_ge_dmadesc_tx"
-#define RM9K_GE_RESOURCE_IRQ_MAIN	"rm9k_ge_irq_main"
-#define RM9K_GE_RESOURCE_IRQ_PHY	"rm9k_ge_irq_phy"
-#define RM9K_GE_RESOURCE_GPI_SLICE	"rm9k_ge_gpi_slice"
-#define RM9K_GE_RESOURCE_MDIO_CHANNEL	"rm9k_ge_mdio_channel"
-
-#endif /* !defined(__RM9K_ETH_H__) */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_wdt.h b/arch/mips/include/asm/mach-excite/rm9k_wdt.h
deleted file mode 100644
index 3fa3c08..0000000
--- a/arch/mips/include/asm/mach-excite/rm9k_wdt.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __RM9K_WDT_H__
-#define __RM9K_WDT_H__
-
-/* Device name */
-#define WDT_NAME		"wdt_gpi"
-
-/* Resource names */
-#define WDT_RESOURCE_REGS	"excite_watchdog_regs"
-#define WDT_RESOURCE_IRQ	"excite_watchdog_irq"
-#define WDT_RESOURCE_COUNTER	"excite_watchdog_counter"
-
-#endif /* __RM9K_WDT_H__ */
diff --git a/arch/mips/include/asm/mach-excite/rm9k_xicap.h b/arch/mips/include/asm/mach-excite/rm9k_xicap.h
deleted file mode 100644
index 0095777..0000000
--- a/arch/mips/include/asm/mach-excite/rm9k_xicap.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __EXCITE_XICAP_H__
-#define __EXCITE_XICAP_H__
-
-
-/* Resource names */
-#define XICAP_RESOURCE_FIFO_RX		"xicap_fifo_rx"
-#define XICAP_RESOURCE_FIFO_TX		"xicap_fifo_tx"
-#define XICAP_RESOURCE_XDMA 		"xicap_xdma"
-#define XICAP_RESOURCE_DMADESC		"xicap_dmadesc"
-#define XICAP_RESOURCE_PKTPROC  	"xicap_pktproc"
-#define XICAP_RESOURCE_IRQ		"xicap_irq"
-#define XICAP_RESOURCE_GPI_SLICE	"xicap_gpi_slice"
-#define XICAP_RESOURCE_FIFO_BLK		"xicap_fifo_blocks"
-#define XICAP_RESOURCE_PKT_STREAM	"xicap_pkt_stream"
-
-#endif /* __EXCITE_XICAP_H__ */
diff --git a/arch/mips/include/asm/mach-excite/war.h b/arch/mips/include/asm/mach-excite/war.h
deleted file mode 100644
index 1f82180..0000000
--- a/arch/mips/include/asm/mach-excite/war.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- */
-#ifndef __ASM_MIPS_MACH_EXCITE_WAR_H
-#define __ASM_MIPS_MACH_EXCITE_WAR_H
-
-#define R4600_V1_INDEX_ICACHEOP_WAR	0
-#define R4600_V1_HIT_CACHEOP_WAR	0
-#define R4600_V2_HIT_CACHEOP_WAR	0
-#define R5432_CP0_INTERRUPT_WAR		0
-#define BCM1250_M3_WAR			0
-#define SIBYTE_1956_WAR			0
-#define MIPS4K_ICACHE_REFILL_WAR	0
-#define MIPS_CACHE_SYNC_WAR		0
-#define TX49XX_ICACHE_INDEX_INV_WAR	0
-#define RM9000_CDEX_SMP_WAR		1
-#define ICACHE_REFILLS_WORKAROUND_WAR   1
-#define R10000_LLSC_WAR			0
-#define MIPS34K_MISSED_ITLB_WAR	0
-
-#endif /* __ASM_MIPS_MACH_EXCITE_WAR_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
new file mode 100644
index 0000000..021f77c
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
@@ -0,0 +1,305 @@
+/*
+ * The header file of cs5536 sourth bridge.
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu <liujl@lemote.com>
+ */
+
+#ifndef	_CS5536_H
+#define	_CS5536_H
+
+#include <linux/types.h>
+
+extern void _rdmsr(u32 msr, u32 *hi, u32 *lo);
+extern void _wrmsr(u32 msr, u32 hi, u32 lo);
+
+/*
+ * MSR module base
+ */
+#define	CS5536_SB_MSR_BASE	(0x00000000)
+#define	CS5536_GLIU_MSR_BASE	(0x10000000)
+#define	CS5536_ILLEGAL_MSR_BASE	(0x20000000)
+#define	CS5536_USB_MSR_BASE	(0x40000000)
+#define	CS5536_IDE_MSR_BASE	(0x60000000)
+#define	CS5536_DIVIL_MSR_BASE	(0x80000000)
+#define	CS5536_ACC_MSR_BASE	(0xa0000000)
+#define	CS5536_UNUSED_MSR_BASE	(0xc0000000)
+#define	CS5536_GLCP_MSR_BASE	(0xe0000000)
+
+#define	SB_MSR_REG(offset)	(CS5536_SB_MSR_BASE	| (offset))
+#define	GLIU_MSR_REG(offset)	(CS5536_GLIU_MSR_BASE	| (offset))
+#define	ILLEGAL_MSR_REG(offset)	(CS5536_ILLEGAL_MSR_BASE | (offset))
+#define	USB_MSR_REG(offset)	(CS5536_USB_MSR_BASE	| (offset))
+#define	IDE_MSR_REG(offset)	(CS5536_IDE_MSR_BASE	| (offset))
+#define	DIVIL_MSR_REG(offset)	(CS5536_DIVIL_MSR_BASE	| (offset))
+#define	ACC_MSR_REG(offset)	(CS5536_ACC_MSR_BASE	| (offset))
+#define	UNUSED_MSR_REG(offset)	(CS5536_UNUSED_MSR_BASE	| (offset))
+#define	GLCP_MSR_REG(offset)	(CS5536_GLCP_MSR_BASE	| (offset))
+
+/*
+ * BAR SPACE OF VIRTUAL PCI :
+ * range for pci probe use, length is the actual size.
+ */
+/* IO space for all DIVIL modules */
+#define	CS5536_IRQ_RANGE	0xffffffe0 /* USERD FOR PCI PROBE */
+#define	CS5536_IRQ_LENGTH	0x20	/* THE REGS ACTUAL LENGTH */
+#define	CS5536_SMB_RANGE	0xfffffff8
+#define	CS5536_SMB_LENGTH	0x08
+#define	CS5536_GPIO_RANGE	0xffffff00
+#define	CS5536_GPIO_LENGTH	0x100
+#define	CS5536_MFGPT_RANGE	0xffffffc0
+#define	CS5536_MFGPT_LENGTH	0x40
+#define	CS5536_ACPI_RANGE	0xffffffe0
+#define	CS5536_ACPI_LENGTH	0x20
+#define	CS5536_PMS_RANGE	0xffffff80
+#define	CS5536_PMS_LENGTH	0x80
+/* IO space for IDE */
+#define	CS5536_IDE_RANGE	0xfffffff0
+#define	CS5536_IDE_LENGTH	0x10
+/* IO space for ACC */
+#define	CS5536_ACC_RANGE	0xffffff80
+#define	CS5536_ACC_LENGTH	0x80
+/* MEM space for ALL USB modules */
+#define	CS5536_OHCI_RANGE	0xfffff000
+#define	CS5536_OHCI_LENGTH	0x1000
+#define	CS5536_EHCI_RANGE	0xfffff000
+#define	CS5536_EHCI_LENGTH	0x1000
+
+/*
+ * PCI MSR ACCESS
+ */
+#define	PCI_MSR_CTRL		0xF0
+#define	PCI_MSR_ADDR		0xF4
+#define	PCI_MSR_DATA_LO		0xF8
+#define	PCI_MSR_DATA_HI		0xFC
+
+/**************** MSR *****************************/
+
+/*
+ * GLIU STANDARD MSR
+ */
+#define	GLIU_CAP		0x00
+#define	GLIU_CONFIG		0x01
+#define	GLIU_SMI		0x02
+#define	GLIU_ERROR		0x03
+#define	GLIU_PM			0x04
+#define	GLIU_DIAG		0x05
+
+/*
+ * GLIU SPEC. MSR
+ */
+#define	GLIU_P2D_BM0		0x20
+#define	GLIU_P2D_BM1		0x21
+#define	GLIU_P2D_BM2		0x22
+#define	GLIU_P2D_BMK0		0x23
+#define	GLIU_P2D_BMK1		0x24
+#define	GLIU_P2D_BM3		0x25
+#define	GLIU_P2D_BM4		0x26
+#define	GLIU_COH		0x80
+#define	GLIU_PAE		0x81
+#define	GLIU_ARB		0x82
+#define	GLIU_ASMI		0x83
+#define	GLIU_AERR		0x84
+#define	GLIU_DEBUG		0x85
+#define	GLIU_PHY_CAP		0x86
+#define	GLIU_NOUT_RESP		0x87
+#define	GLIU_NOUT_WDATA		0x88
+#define	GLIU_WHOAMI		0x8B
+#define	GLIU_SLV_DIS		0x8C
+#define	GLIU_IOD_BM0		0xE0
+#define	GLIU_IOD_BM1		0xE1
+#define	GLIU_IOD_BM2		0xE2
+#define	GLIU_IOD_BM3		0xE3
+#define	GLIU_IOD_BM4		0xE4
+#define	GLIU_IOD_BM5		0xE5
+#define	GLIU_IOD_BM6		0xE6
+#define	GLIU_IOD_BM7		0xE7
+#define	GLIU_IOD_BM8		0xE8
+#define	GLIU_IOD_BM9		0xE9
+#define	GLIU_IOD_SC0		0xEA
+#define	GLIU_IOD_SC1		0xEB
+#define	GLIU_IOD_SC2		0xEC
+#define	GLIU_IOD_SC3		0xED
+#define	GLIU_IOD_SC4		0xEE
+#define	GLIU_IOD_SC5		0xEF
+#define	GLIU_IOD_SC6		0xF0
+#define	GLIU_IOD_SC7		0xF1
+
+/*
+ * SB STANDARD
+ */
+#define	SB_CAP		0x00
+#define	SB_CONFIG	0x01
+#define	SB_SMI		0x02
+#define	SB_ERROR	0x03
+#define	SB_MAR_ERR_EN		0x00000001
+#define	SB_TAR_ERR_EN		0x00000002
+#define	SB_RSVD_BIT1		0x00000004
+#define	SB_EXCEP_ERR_EN		0x00000008
+#define	SB_SYSE_ERR_EN		0x00000010
+#define	SB_PARE_ERR_EN		0x00000020
+#define	SB_TAS_ERR_EN		0x00000040
+#define	SB_MAR_ERR_FLAG		0x00010000
+#define	SB_TAR_ERR_FLAG		0x00020000
+#define	SB_RSVD_BIT2		0x00040000
+#define	SB_EXCEP_ERR_FLAG	0x00080000
+#define	SB_SYSE_ERR_FLAG	0x00100000
+#define	SB_PARE_ERR_FLAG	0x00200000
+#define	SB_TAS_ERR_FLAG		0x00400000
+#define	SB_PM		0x04
+#define	SB_DIAG		0x05
+
+/*
+ * SB SPEC.
+ */
+#define	SB_CTRL		0x10
+#define	SB_R0		0x20
+#define	SB_R1		0x21
+#define	SB_R2		0x22
+#define	SB_R3		0x23
+#define	SB_R4		0x24
+#define	SB_R5		0x25
+#define	SB_R6		0x26
+#define	SB_R7		0x27
+#define	SB_R8		0x28
+#define	SB_R9		0x29
+#define	SB_R10		0x2A
+#define	SB_R11		0x2B
+#define	SB_R12		0x2C
+#define	SB_R13		0x2D
+#define	SB_R14		0x2E
+#define	SB_R15		0x2F
+
+/*
+ * GLCP STANDARD
+ */
+#define	GLCP_CAP		0x00
+#define	GLCP_CONFIG		0x01
+#define	GLCP_SMI		0x02
+#define	GLCP_ERROR		0x03
+#define	GLCP_PM			0x04
+#define	GLCP_DIAG		0x05
+
+/*
+ * GLCP SPEC.
+ */
+#define	GLCP_CLK_DIS_DELAY	0x08
+#define	GLCP_PM_CLK_DISABLE	0x09
+#define	GLCP_GLB_PM		0x0B
+#define	GLCP_DBG_OUT		0x0C
+#define	GLCP_RSVD1		0x0D
+#define	GLCP_SOFT_COM		0x0E
+#define	SOFT_BAR_SMB_FLAG	0x00000001
+#define	SOFT_BAR_GPIO_FLAG	0x00000002
+#define	SOFT_BAR_MFGPT_FLAG	0x00000004
+#define	SOFT_BAR_IRQ_FLAG	0x00000008
+#define	SOFT_BAR_PMS_FLAG	0x00000010
+#define	SOFT_BAR_ACPI_FLAG	0x00000020
+#define	SOFT_BAR_IDE_FLAG	0x00000400
+#define	SOFT_BAR_ACC_FLAG	0x00000800
+#define	SOFT_BAR_OHCI_FLAG	0x00001000
+#define	SOFT_BAR_EHCI_FLAG	0x00002000
+#define	GLCP_RSVD2		0x0F
+#define	GLCP_CLK_OFF		0x10
+#define	GLCP_CLK_ACTIVE		0x11
+#define	GLCP_CLK_DISABLE	0x12
+#define	GLCP_CLK4ACK		0x13
+#define	GLCP_SYS_RST		0x14
+#define	GLCP_RSVD3		0x15
+#define	GLCP_DBG_CLK_CTRL	0x16
+#define	GLCP_CHIP_REV_ID	0x17
+
+/* PIC */
+#define	PIC_YSEL_LOW		0x20
+#define	PIC_YSEL_LOW_USB_SHIFT		8
+#define	PIC_YSEL_LOW_ACC_SHIFT		16
+#define	PIC_YSEL_LOW_FLASH_SHIFT	24
+#define	PIC_YSEL_HIGH		0x21
+#define	PIC_ZSEL_LOW		0x22
+#define	PIC_ZSEL_HIGH		0x23
+#define	PIC_IRQM_PRIM		0x24
+#define	PIC_IRQM_LPC		0x25
+#define	PIC_XIRR_STS_LOW	0x26
+#define	PIC_XIRR_STS_HIGH	0x27
+#define	PCI_SHDW		0x34
+
+/*
+ * DIVIL STANDARD
+ */
+#define	DIVIL_CAP		0x00
+#define	DIVIL_CONFIG		0x01
+#define	DIVIL_SMI		0x02
+#define	DIVIL_ERROR		0x03
+#define	DIVIL_PM		0x04
+#define	DIVIL_DIAG		0x05
+
+/*
+ * DIVIL SPEC.
+ */
+#define	DIVIL_LBAR_IRQ		0x08
+#define	DIVIL_LBAR_KEL		0x09
+#define	DIVIL_LBAR_SMB		0x0B
+#define	DIVIL_LBAR_GPIO		0x0C
+#define	DIVIL_LBAR_MFGPT	0x0D
+#define	DIVIL_LBAR_ACPI		0x0E
+#define	DIVIL_LBAR_PMS		0x0F
+#define	DIVIL_LEG_IO		0x14
+#define	DIVIL_BALL_OPTS		0x15
+#define	DIVIL_SOFT_IRQ		0x16
+#define	DIVIL_SOFT_RESET	0x17
+
+/* MFGPT */
+#define MFGPT_IRQ	0x28
+
+/*
+ * IDE STANDARD
+ */
+#define	IDE_CAP		0x00
+#define	IDE_CONFIG	0x01
+#define	IDE_SMI		0x02
+#define	IDE_ERROR	0x03
+#define	IDE_PM		0x04
+#define	IDE_DIAG	0x05
+
+/*
+ * IDE SPEC.
+ */
+#define	IDE_IO_BAR	0x08
+#define	IDE_CFG		0x10
+#define	IDE_DTC		0x12
+#define	IDE_CAST	0x13
+#define	IDE_ETC		0x14
+#define	IDE_INTERNAL_PM	0x15
+
+/*
+ * ACC STANDARD
+ */
+#define	ACC_CAP		0x00
+#define	ACC_CONFIG	0x01
+#define	ACC_SMI		0x02
+#define	ACC_ERROR	0x03
+#define	ACC_PM		0x04
+#define	ACC_DIAG	0x05
+
+/*
+ * USB STANDARD
+ */
+#define	USB_CAP		0x00
+#define	USB_CONFIG	0x01
+#define	USB_SMI		0x02
+#define	USB_ERROR	0x03
+#define	USB_PM		0x04
+#define	USB_DIAG	0x05
+
+/*
+ * USB SPEC.
+ */
+#define	USB_OHCI	0x08
+#define	USB_EHCI	0x09
+
+/****************** NATIVE ***************************/
+/* GPIO : I/O SPACE; REG : 32BITS */
+#define	GPIOL_OUT_VAL		0x00
+#define	GPIOL_OUT_EN		0x04
+
+#endif				/* _CS5536_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
new file mode 100644
index 0000000..4b493d6
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
@@ -0,0 +1,35 @@
+/*
+ * cs5536 mfgpt header file
+ */
+
+#ifndef _CS5536_MFGPT_H
+#define _CS5536_MFGPT_H
+
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+#ifdef CONFIG_CS5536_MFGPT
+extern void setup_mfgpt0_timer(void);
+extern void disable_mfgpt0_counter(void);
+extern void enable_mfgpt0_counter(void);
+#else
+static inline void __maybe_unused setup_mfgpt0_timer(void)
+{
+}
+static inline void __maybe_unused disable_mfgpt0_counter(void)
+{
+}
+static inline void __maybe_unused enable_mfgpt0_counter(void)
+{
+}
+#endif
+
+#define MFGPT_TICK_RATE 14318000
+#define COMPARE  ((MFGPT_TICK_RATE + HZ/2) / HZ)
+
+#define MFGPT_BASE	mfgpt_base
+#define MFGPT0_CMP2	(MFGPT_BASE + 2)
+#define MFGPT0_CNT	(MFGPT_BASE + 4)
+#define MFGPT0_SETUP	(MFGPT_BASE + 6)
+
+#endif /*!_CS5536_MFGPT_H */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
new file mode 100644
index 0000000..0dca9c8
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_pci.h
@@ -0,0 +1,153 @@
+/*
+ * the definition file of cs5536 Virtual Support Module(VSM).
+ * pci configuration space can be accessed through the VSM, so
+ * there is no need of the MSR read/write now, except the spec.
+ * MSR registers which are not implemented yet.
+ *
+ * Copyright (C) 2007 Lemote Inc.
+ * Author : jlliu, liujl@lemote.com
+ */
+
+#ifndef	_CS5536_PCI_H
+#define	_CS5536_PCI_H
+
+#include <linux/types.h>
+#include <linux/pci_regs.h>
+
+extern void cs5536_pci_conf_write4(int function, int reg, u32 value);
+extern u32 cs5536_pci_conf_read4(int function, int reg);
+
+#define	CS5536_ACC_INTR		9
+#define	CS5536_IDE_INTR		14
+#define	CS5536_USB_INTR		11
+#define	CS5536_MFGPT_INTR	5
+#define	CS5536_UART1_INTR	4
+#define	CS5536_UART2_INTR	3
+
+/************** PCI BUS DEVICE FUNCTION ***************/
+
+/*
+ * PCI bus device function
+ */
+#define	PCI_BUS_CS5536		0
+#define	PCI_IDSEL_CS5536	14
+
+/********** STANDARD PCI-2.2 EXPANSION ****************/
+
+/*
+ * PCI configuration space
+ * we have to virtualize the PCI configure space head, so we should
+ * define the necessary IDs and some others.
+ */
+
+/* CONFIG of PCI VENDOR ID*/
+#define CFG_PCI_VENDOR_ID(mod_dev_id, sys_vendor_id) \
+	(((mod_dev_id) << 16) | (sys_vendor_id))
+
+/* VENDOR ID */
+#define	CS5536_VENDOR_ID	0x1022
+
+/* DEVICE ID */
+#define	CS5536_ISA_DEVICE_ID		0x2090
+#define	CS5536_IDE_DEVICE_ID		0x209a
+#define	CS5536_ACC_DEVICE_ID		0x2093
+#define	CS5536_OHCI_DEVICE_ID		0x2094
+#define	CS5536_EHCI_DEVICE_ID		0x2095
+
+/* CLASS CODE : CLASS SUB-CLASS INTERFACE */
+#define	CS5536_ISA_CLASS_CODE		0x060100
+#define CS5536_IDE_CLASS_CODE		0x010180
+#define	CS5536_ACC_CLASS_CODE		0x040100
+#define	CS5536_OHCI_CLASS_CODE		0x0C0310
+#define	CS5536_EHCI_CLASS_CODE		0x0C0320
+
+/* BHLC : BIST HEADER-TYPE LATENCY-TIMER CACHE-LINE-SIZE */
+
+#define CFG_PCI_CACHE_LINE_SIZE(header_type, latency_timer)	\
+	((PCI_NONE_BIST << 24) | ((header_type) << 16) \
+		| ((latency_timer) << 8) | PCI_NORMAL_CACHE_LINE_SIZE);
+
+#define	PCI_NONE_BIST			0x00	/* RO not implemented yet. */
+#define	PCI_BRIDGE_HEADER_TYPE		0x80	/* RO */
+#define	PCI_NORMAL_HEADER_TYPE		0x00
+#define	PCI_NORMAL_LATENCY_TIMER	0x00
+#define	PCI_NORMAL_CACHE_LINE_SIZE	0x08	/* RW */
+
+/* BAR */
+#define	PCI_BAR0_REG			0x10
+#define	PCI_BAR1_REG			0x14
+#define	PCI_BAR2_REG			0x18
+#define	PCI_BAR3_REG			0x1c
+#define	PCI_BAR4_REG			0x20
+#define	PCI_BAR5_REG			0x24
+#define	PCI_BAR_COUNT			6
+#define	PCI_BAR_RANGE_MASK		0xFFFFFFFF
+
+/* CARDBUS CIS POINTER */
+#define	PCI_CARDBUS_CIS_POINTER		0x00000000
+
+/* SUBSYSTEM VENDOR ID  */
+#define	CS5536_SUB_VENDOR_ID		CS5536_VENDOR_ID
+
+/* SUBSYSTEM ID */
+#define	CS5536_ISA_SUB_ID		CS5536_ISA_DEVICE_ID
+#define	CS5536_IDE_SUB_ID		CS5536_IDE_DEVICE_ID
+#define	CS5536_ACC_SUB_ID		CS5536_ACC_DEVICE_ID
+#define	CS5536_OHCI_SUB_ID		CS5536_OHCI_DEVICE_ID
+#define	CS5536_EHCI_SUB_ID		CS5536_EHCI_DEVICE_ID
+
+/* EXPANSION ROM BAR */
+#define	PCI_EXPANSION_ROM_BAR		0x00000000
+
+/* CAPABILITIES POINTER */
+#define	PCI_CAPLIST_POINTER		0x00000000
+#define PCI_CAPLIST_USB_POINTER		0x40
+/* INTERRUPT */
+
+#define CFG_PCI_INTERRUPT_LINE(pin, mod_intr) \
+	((PCI_MAX_LATENCY << 24) | (PCI_MIN_GRANT << 16) | \
+		((pin) << 8) | (mod_intr))
+
+#define	PCI_MAX_LATENCY			0x40
+#define	PCI_MIN_GRANT			0x00
+#define	PCI_DEFAULT_PIN			0x01
+
+/*********** EXPANSION PCI REG ************************/
+
+/*
+ * ISA EXPANSION
+ */
+#define	PCI_UART1_INT_REG 	0x50
+#define PCI_UART2_INT_REG	0x54
+#define	PCI_ISA_FIXUP_REG	0x58
+
+/*
+ * IDE EXPANSION
+ */
+#define	PCI_IDE_CFG_REG		0x40
+#define	CS5536_IDE_FLASH_SIGNATURE	0xDEADBEEF
+#define	PCI_IDE_DTC_REG		0x48
+#define	PCI_IDE_CAST_REG	0x4C
+#define	PCI_IDE_ETC_REG		0x50
+#define	PCI_IDE_PM_REG		0x54
+#define	PCI_IDE_INT_REG		0x60
+
+/*
+ * ACC EXPANSION
+ */
+#define	PCI_ACC_INT_REG		0x50
+
+/*
+ * OHCI EXPANSION : INTTERUPT IS IMPLEMENTED BY THE OHCI
+ */
+#define	PCI_OHCI_PM_REG		0x40
+#define	PCI_OHCI_INT_REG	0x50
+
+/*
+ * EHCI EXPANSION
+ */
+#define	PCI_EHCI_LEGSMIEN_REG	0x50
+#define	PCI_EHCI_LEGSMISTS_REG	0x54
+#define	PCI_EHCI_FLADJ_REG	0x60
+
+#endif				/* _CS5536_PCI_H_ */
diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
new file mode 100644
index 0000000..6305bea
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_vsm.h
@@ -0,0 +1,31 @@
+/*
+ * the read/write interfaces for Virtual Support Module(VSM)
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#ifndef	_CS5536_VSM_H
+#define	_CS5536_VSM_H
+
+#include <linux/types.h>
+
+typedef void (*cs5536_pci_vsm_write)(int reg, u32 value);
+typedef u32 (*cs5536_pci_vsm_read)(int reg);
+
+#define DECLARE_CS5536_MODULE(name) \
+extern void pci_##name##_write_reg(int reg, u32 value); \
+extern u32 pci_##name##_read_reg(int reg);
+
+/* ide module */
+DECLARE_CS5536_MODULE(ide)
+/* acc module */
+DECLARE_CS5536_MODULE(acc)
+/* ohci module */
+DECLARE_CS5536_MODULE(ohci)
+/* isa module */
+DECLARE_CS5536_MODULE(isa)
+/* ehci module */
+DECLARE_CS5536_MODULE(ehci)
+
+#endif				/* _CS5536_VSM_H */
diff --git a/arch/mips/include/asm/mach-loongson/dma-coherence.h b/arch/mips/include/asm/mach-loongson/dma-coherence.h
index 71a6851..981c75f 100644
--- a/arch/mips/include/asm/mach-loongson/dma-coherence.h
+++ b/arch/mips/include/asm/mach-loongson/dma-coherence.h
@@ -28,7 +28,11 @@
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
 	dma_addr_t dma_addr)
 {
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+	return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
+#else
 	return dma_addr & 0x7fffffff;
+#endif
 }
 
 static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index da70bcf..ee8bc83 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -15,9 +15,6 @@
 #include <linux/io.h>
 #include <linux/init.h>
 
-/* there is an internal bonito64-compatiable northbridge in loongson2e/2f */
-#include <asm/mips-boards/bonito64.h>
-
 /* loongson internal northbridge initialization */
 extern void bonito_irq_init(void);
 
@@ -32,7 +29,19 @@
 /* loongson-specific command line, env and memory initialization */
 extern void __init prom_init_memory(void);
 extern void __init prom_init_cmdline(void);
+extern void __init prom_init_machtype(void);
 extern void __init prom_init_env(void);
+#ifdef CONFIG_LOONGSON_UART_BASE
+extern unsigned long _loongson_uart_base, loongson_uart_base;
+extern void prom_init_loongson_uart_base(void);
+#endif
+
+static inline void prom_init_uart_base(void)
+{
+#ifdef CONFIG_LOONGSON_UART_BASE
+	prom_init_loongson_uart_base();
+#endif
+}
 
 /* irq operation functions */
 extern void bonito_irqdispatch(void);
@@ -40,25 +49,276 @@
 extern void __init set_irq_trigger_mode(void);
 extern void __init mach_init_irq(void);
 extern void mach_irq_dispatch(unsigned int pending);
+extern int mach_i8259_irq(void);
+
+/* We need this in some places... */
+#define delay()	({		\
+	int x;				\
+	for (x = 0; x < 100000; x++)	\
+		__asm__ __volatile__(""); \
+})
+
+#define LOONGSON_REG(x) \
+	(*(volatile u32 *)((char *)CKSEG1ADDR(LOONGSON_REG_BASE) + (x)))
+
+#define LOONGSON_IRQ_BASE	32
+#define LOONGSON2_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6) /* cpu perf counter */
+
+#define LOONGSON_FLASH_BASE	0x1c000000
+#define LOONGSON_FLASH_SIZE	0x02000000	/* 32M */
+#define LOONGSON_FLASH_TOP	(LOONGSON_FLASH_BASE+LOONGSON_FLASH_SIZE-1)
+
+#define LOONGSON_LIO0_BASE	0x1e000000
+#define LOONGSON_LIO0_SIZE	0x01C00000	/* 28M */
+#define LOONGSON_LIO0_TOP	(LOONGSON_LIO0_BASE+LOONGSON_LIO0_SIZE-1)
+
+#define LOONGSON_BOOT_BASE	0x1fc00000
+#define LOONGSON_BOOT_SIZE	0x00100000	/* 1M */
+#define LOONGSON_BOOT_TOP 	(LOONGSON_BOOT_BASE+LOONGSON_BOOT_SIZE-1)
+#define LOONGSON_REG_BASE 	0x1fe00000
+#define LOONGSON_REG_SIZE 	0x00100000	/* 256Bytes + 256Bytes + ??? */
+#define LOONGSON_REG_TOP	(LOONGSON_REG_BASE+LOONGSON_REG_SIZE-1)
+
+#define LOONGSON_LIO1_BASE 	0x1ff00000
+#define LOONGSON_LIO1_SIZE 	0x00100000	/* 1M */
+#define LOONGSON_LIO1_TOP	(LOONGSON_LIO1_BASE+LOONGSON_LIO1_SIZE-1)
+
+#define LOONGSON_PCILO0_BASE	0x10000000
+#define LOONGSON_PCILO1_BASE	0x14000000
+#define LOONGSON_PCILO2_BASE	0x18000000
+#define LOONGSON_PCILO_BASE	LOONGSON_PCILO0_BASE
+#define LOONGSON_PCILO_SIZE	0x0c000000	/* 64M * 3 */
+#define LOONGSON_PCILO_TOP	(LOONGSON_PCILO0_BASE+LOONGSON_PCILO_SIZE-1)
+
+#define LOONGSON_PCICFG_BASE	0x1fe80000
+#define LOONGSON_PCICFG_SIZE	0x00000800	/* 2K */
+#define LOONGSON_PCICFG_TOP	(LOONGSON_PCICFG_BASE+LOONGSON_PCICFG_SIZE-1)
+#define LOONGSON_PCIIO_BASE	0x1fd00000
+#define LOONGSON_PCIIO_SIZE	0x00100000	/* 1M */
+#define LOONGSON_PCIIO_TOP	(LOONGSON_PCIIO_BASE+LOONGSON_PCIIO_SIZE-1)
+
+/* Loongson Register Bases */
+
+#define LOONGSON_PCICONFIGBASE	0x00
+#define LOONGSON_REGBASE	0x100
 
 /* PCI Configuration Registers */
-#define LOONGSON_PCI_ISR4C  BONITO_PCI_REG(0x4c)
+
+#define LOONGSON_PCI_REG(x)	LOONGSON_REG(LOONGSON_PCICONFIGBASE + (x))
+#define LOONGSON_PCIDID		LOONGSON_PCI_REG(0x00)
+#define LOONGSON_PCICMD		LOONGSON_PCI_REG(0x04)
+#define LOONGSON_PCICLASS 	LOONGSON_PCI_REG(0x08)
+#define LOONGSON_PCILTIMER	LOONGSON_PCI_REG(0x0c)
+#define LOONGSON_PCIBASE0 	LOONGSON_PCI_REG(0x10)
+#define LOONGSON_PCIBASE1 	LOONGSON_PCI_REG(0x14)
+#define LOONGSON_PCIBASE2 	LOONGSON_PCI_REG(0x18)
+#define LOONGSON_PCIBASE3 	LOONGSON_PCI_REG(0x1c)
+#define LOONGSON_PCIBASE4 	LOONGSON_PCI_REG(0x20)
+#define LOONGSON_PCIEXPRBASE	LOONGSON_PCI_REG(0x30)
+#define LOONGSON_PCIINT		LOONGSON_PCI_REG(0x3c)
+
+#define LOONGSON_PCI_ISR4C	LOONGSON_PCI_REG(0x4c)
+
+#define LOONGSON_PCICMD_PERR_CLR	0x80000000
+#define LOONGSON_PCICMD_SERR_CLR	0x40000000
+#define LOONGSON_PCICMD_MABORT_CLR	0x20000000
+#define LOONGSON_PCICMD_MTABORT_CLR	0x10000000
+#define LOONGSON_PCICMD_TABORT_CLR	0x08000000
+#define LOONGSON_PCICMD_MPERR_CLR 	0x01000000
+#define LOONGSON_PCICMD_PERRRESPEN	0x00000040
+#define LOONGSON_PCICMD_ASTEPEN		0x00000080
+#define LOONGSON_PCICMD_SERREN		0x00000100
+#define LOONGSON_PCILTIMER_BUSLATENCY	0x0000ff00
+#define LOONGSON_PCILTIMER_BUSLATENCY_SHIFT	8
+
+/* Loongson h/w Configuration */
+
+#define LOONGSON_GENCFG_OFFSET		0x4
+#define LOONGSON_GENCFG	LOONGSON_REG(LOONGSON_REGBASE + LOONGSON_GENCFG_OFFSET)
+
+#define LOONGSON_GENCFG_DEBUGMODE	0x00000001
+#define LOONGSON_GENCFG_SNOOPEN		0x00000002
+#define LOONGSON_GENCFG_CPUSELFRESET	0x00000004
+
+#define LOONGSON_GENCFG_FORCE_IRQA	0x00000008
+#define LOONGSON_GENCFG_IRQA_ISOUT	0x00000010
+#define LOONGSON_GENCFG_IRQA_FROM_INT1	0x00000020
+#define LOONGSON_GENCFG_BYTESWAP	0x00000040
+
+#define LOONGSON_GENCFG_UNCACHED	0x00000080
+#define LOONGSON_GENCFG_PREFETCHEN	0x00000100
+#define LOONGSON_GENCFG_WBEHINDEN	0x00000200
+#define LOONGSON_GENCFG_CACHEALG	0x00000c00
+#define LOONGSON_GENCFG_CACHEALG_SHIFT	10
+#define LOONGSON_GENCFG_PCIQUEUE	0x00001000
+#define LOONGSON_GENCFG_CACHESTOP	0x00002000
+#define LOONGSON_GENCFG_MSTRBYTESWAP	0x00004000
+#define LOONGSON_GENCFG_BUSERREN	0x00008000
+#define LOONGSON_GENCFG_NORETRYTIMEOUT	0x00010000
+#define LOONGSON_GENCFG_SHORTCOPYTIMEOUT	0x00020000
+
+/* PCI address map control */
+
+#define LOONGSON_PCIMAP			LOONGSON_REG(LOONGSON_REGBASE + 0x10)
+#define LOONGSON_PCIMEMBASECFG		LOONGSON_REG(LOONGSON_REGBASE + 0x14)
+#define LOONGSON_PCIMAP_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x18)
+
+/* GPIO Regs - r/w */
+
+#define LOONGSON_GPIODATA 		LOONGSON_REG(LOONGSON_REGBASE + 0x1c)
+#define LOONGSON_GPIOIE			LOONGSON_REG(LOONGSON_REGBASE + 0x20)
+
+/* ICU Configuration Regs - r/w */
+
+#define LOONGSON_INTEDGE		LOONGSON_REG(LOONGSON_REGBASE + 0x24)
+#define LOONGSON_INTSTEER 		LOONGSON_REG(LOONGSON_REGBASE + 0x28)
+#define LOONGSON_INTPOL			LOONGSON_REG(LOONGSON_REGBASE + 0x2c)
+
+/* ICU Enable Regs - IntEn & IntISR are r/o. */
+
+#define LOONGSON_INTENSET 		LOONGSON_REG(LOONGSON_REGBASE + 0x30)
+#define LOONGSON_INTENCLR 		LOONGSON_REG(LOONGSON_REGBASE + 0x34)
+#define LOONGSON_INTEN			LOONGSON_REG(LOONGSON_REGBASE + 0x38)
+#define LOONGSON_INTISR			LOONGSON_REG(LOONGSON_REGBASE + 0x3c)
+
+/* ICU */
+#define LOONGSON_ICU_MBOXES		0x0000000f
+#define LOONGSON_ICU_MBOXES_SHIFT 	0
+#define LOONGSON_ICU_DMARDY		0x00000010
+#define LOONGSON_ICU_DMAEMPTY		0x00000020
+#define LOONGSON_ICU_COPYRDY		0x00000040
+#define LOONGSON_ICU_COPYEMPTY		0x00000080
+#define LOONGSON_ICU_COPYERR		0x00000100
+#define LOONGSON_ICU_PCIIRQ		0x00000200
+#define LOONGSON_ICU_MASTERERR		0x00000400
+#define LOONGSON_ICU_SYSTEMERR		0x00000800
+#define LOONGSON_ICU_DRAMPERR		0x00001000
+#define LOONGSON_ICU_RETRYERR		0x00002000
+#define LOONGSON_ICU_GPIOS		0x01ff0000
+#define LOONGSON_ICU_GPIOS_SHIFT		16
+#define LOONGSON_ICU_GPINS		0x7e000000
+#define LOONGSON_ICU_GPINS_SHIFT		25
+#define LOONGSON_ICU_MBOX(N)		(1<<(LOONGSON_ICU_MBOXES_SHIFT+(N)))
+#define LOONGSON_ICU_GPIO(N)		(1<<(LOONGSON_ICU_GPIOS_SHIFT+(N)))
+#define LOONGSON_ICU_GPIN(N)		(1<<(LOONGSON_ICU_GPINS_SHIFT+(N)))
+
+/* PCI prefetch window base & mask */
+
+#define LOONGSON_MEM_WIN_BASE_L 	LOONGSON_REG(LOONGSON_REGBASE + 0x40)
+#define LOONGSON_MEM_WIN_BASE_H 	LOONGSON_REG(LOONGSON_REGBASE + 0x44)
+#define LOONGSON_MEM_WIN_MASK_L 	LOONGSON_REG(LOONGSON_REGBASE + 0x48)
+#define LOONGSON_MEM_WIN_MASK_H 	LOONGSON_REG(LOONGSON_REGBASE + 0x4c)
 
 /* PCI_Hit*_Sel_* */
 
-#define LOONGSON_PCI_HIT0_SEL_L     BONITO(BONITO_REGBASE + 0x50)
-#define LOONGSON_PCI_HIT0_SEL_H     BONITO(BONITO_REGBASE + 0x54)
-#define LOONGSON_PCI_HIT1_SEL_L     BONITO(BONITO_REGBASE + 0x58)
-#define LOONGSON_PCI_HIT1_SEL_H     BONITO(BONITO_REGBASE + 0x5c)
-#define LOONGSON_PCI_HIT2_SEL_L     BONITO(BONITO_REGBASE + 0x60)
-#define LOONGSON_PCI_HIT2_SEL_H     BONITO(BONITO_REGBASE + 0x64)
+#define LOONGSON_PCI_HIT0_SEL_L		LOONGSON_REG(LOONGSON_REGBASE + 0x50)
+#define LOONGSON_PCI_HIT0_SEL_H		LOONGSON_REG(LOONGSON_REGBASE + 0x54)
+#define LOONGSON_PCI_HIT1_SEL_L		LOONGSON_REG(LOONGSON_REGBASE + 0x58)
+#define LOONGSON_PCI_HIT1_SEL_H		LOONGSON_REG(LOONGSON_REGBASE + 0x5c)
+#define LOONGSON_PCI_HIT2_SEL_L		LOONGSON_REG(LOONGSON_REGBASE + 0x60)
+#define LOONGSON_PCI_HIT2_SEL_H		LOONGSON_REG(LOONGSON_REGBASE + 0x64)
 
 /* PXArb Config & Status */
 
-#define LOONGSON_PXARB_CFG      BONITO(BONITO_REGBASE + 0x68)
-#define LOONGSON_PXARB_STATUS       BONITO(BONITO_REGBASE + 0x6c)
+#define LOONGSON_PXARB_CFG		LOONGSON_REG(LOONGSON_REGBASE + 0x68)
+#define LOONGSON_PXARB_STATUS		LOONGSON_REG(LOONGSON_REGBASE + 0x6c)
 
-/* loongson2-specific perf counter IRQ */
-#define LOONGSON2_PERFCNT_IRQ   (MIPS_CPU_IRQ_BASE + 6)
+/* pcimap */
+
+#define LOONGSON_PCIMAP_PCIMAP_LO0	0x0000003f
+#define LOONGSON_PCIMAP_PCIMAP_LO0_SHIFT	0
+#define LOONGSON_PCIMAP_PCIMAP_LO1	0x00000fc0
+#define LOONGSON_PCIMAP_PCIMAP_LO1_SHIFT	6
+#define LOONGSON_PCIMAP_PCIMAP_LO2	0x0003f000
+#define LOONGSON_PCIMAP_PCIMAP_LO2_SHIFT	12
+#define LOONGSON_PCIMAP_PCIMAP_2	0x00040000
+#define LOONGSON_PCIMAP_WIN(WIN, ADDR)	\
+	((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
+
+#ifdef CONFIG_CPU_SUPPORTS_CPUFREQ
+#include <linux/cpufreq.h>
+extern void loongson2_cpu_wait(void);
+extern struct cpufreq_frequency_table loongson2_clockmod_table[];
+
+/* Chip Config */
+#define LOONGSON_CHIPCFG0		LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#endif
+
+/*
+ * address windows configuration module
+ *
+ * loongson2e do not have this module
+ */
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+
+/* address window config module base address */
+#define LOONGSON_ADDRWINCFG_BASE		0x3ff00000ul
+#define LOONGSON_ADDRWINCFG_SIZE		0x180
+
+extern unsigned long _loongson_addrwincfg_base;
+#define LOONGSON_ADDRWINCFG(offset) \
+	(*(volatile u64 *)(_loongson_addrwincfg_base + (offset)))
+
+#define CPU_WIN0_BASE	LOONGSON_ADDRWINCFG(0x00)
+#define CPU_WIN1_BASE	LOONGSON_ADDRWINCFG(0x08)
+#define CPU_WIN2_BASE	LOONGSON_ADDRWINCFG(0x10)
+#define CPU_WIN3_BASE	LOONGSON_ADDRWINCFG(0x18)
+
+#define CPU_WIN0_MASK	LOONGSON_ADDRWINCFG(0x20)
+#define CPU_WIN1_MASK	LOONGSON_ADDRWINCFG(0x28)
+#define CPU_WIN2_MASK	LOONGSON_ADDRWINCFG(0x30)
+#define CPU_WIN3_MASK	LOONGSON_ADDRWINCFG(0x38)
+
+#define CPU_WIN0_MMAP	LOONGSON_ADDRWINCFG(0x40)
+#define CPU_WIN1_MMAP	LOONGSON_ADDRWINCFG(0x48)
+#define CPU_WIN2_MMAP	LOONGSON_ADDRWINCFG(0x50)
+#define CPU_WIN3_MMAP	LOONGSON_ADDRWINCFG(0x58)
+
+#define PCIDMA_WIN0_BASE	LOONGSON_ADDRWINCFG(0x60)
+#define PCIDMA_WIN1_BASE	LOONGSON_ADDRWINCFG(0x68)
+#define PCIDMA_WIN2_BASE	LOONGSON_ADDRWINCFG(0x70)
+#define PCIDMA_WIN3_BASE	LOONGSON_ADDRWINCFG(0x78)
+
+#define PCIDMA_WIN0_MASK	LOONGSON_ADDRWINCFG(0x80)
+#define PCIDMA_WIN1_MASK	LOONGSON_ADDRWINCFG(0x88)
+#define PCIDMA_WIN2_MASK	LOONGSON_ADDRWINCFG(0x90)
+#define PCIDMA_WIN3_MASK	LOONGSON_ADDRWINCFG(0x98)
+
+#define PCIDMA_WIN0_MMAP	LOONGSON_ADDRWINCFG(0xa0)
+#define PCIDMA_WIN1_MMAP	LOONGSON_ADDRWINCFG(0xa8)
+#define PCIDMA_WIN2_MMAP	LOONGSON_ADDRWINCFG(0xb0)
+#define PCIDMA_WIN3_MMAP	LOONGSON_ADDRWINCFG(0xb8)
+
+#define ADDRWIN_WIN0	0
+#define ADDRWIN_WIN1	1
+#define ADDRWIN_WIN2	2
+#define ADDRWIN_WIN3	3
+
+#define ADDRWIN_MAP_DST_DDR	0
+#define ADDRWIN_MAP_DST_PCI	1
+#define ADDRWIN_MAP_DST_LIO	1
+
+/*
+ * s: CPU, PCIDMA
+ * d: DDR, PCI, LIO
+ * win: 0, 1, 2, 3
+ * src: map source
+ * dst: map destination
+ * size: ~mask + 1
+ */
+#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
+	s##_WIN##w##_BASE = (src); \
+	s##_WIN##w##_MMAP = (src) | ADDRWIN_MAP_DST_##d; \
+	s##_WIN##w##_MASK = ~(size-1); \
+} while (0)
+
+#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
+	LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
+#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
+	LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
+#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
+	LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
+
+#endif	/* ! CONFIG_CPU_SUPPORTS_ADDRWINCFG */
 
 #endif /* __ASM_MACH_LOONGSON_LOONGSON_H */
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 206ea20..acf8359 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -13,10 +13,15 @@
 
 #ifdef CONFIG_LEMOTE_FULOONG2E
 
-#define LOONGSON_UART_BASE (BONITO_PCIIO_BASE + 0x3f8)
-
 #define LOONGSON_MACHTYPE MACH_LEMOTE_FL2E
 
 #endif
 
+/* use fuloong2f as the default machine of LEMOTE_MACH2F */
+#ifdef CONFIG_LEMOTE_MACH2F
+
+#define LOONGSON_MACHTYPE MACH_LEMOTE_FL2F
+
+#endif
+
 #endif /* __ASM_MACH_LOONGSON_MACHINE_H */
diff --git a/arch/mips/include/asm/mach-loongson/mem.h b/arch/mips/include/asm/mach-loongson/mem.h
index bd7b3cb..e9960f3 100644
--- a/arch/mips/include/asm/mach-loongson/mem.h
+++ b/arch/mips/include/asm/mach-loongson/mem.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -12,19 +12,30 @@
 #define __ASM_MACH_LOONGSON_MEM_H
 
 /*
- * On Lemote Loongson 2e
+ * high memory space
  *
- * the high memory space starts from 512M.
- * the peripheral registers reside between 0x1000:0000 and 0x2000:0000.
+ * in loongson2e, starts from 512M
+ * in loongson2f, starts from 2G 256M
+ */
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_HIGHMEM_START	0x20000000
+#else
+#define LOONGSON_HIGHMEM_START	0x90000000
+#endif
+
+/*
+ * the peripheral registers(MMIO):
+ *
+ * On the Lemote Loongson 2e system, reside between 0x1000:0000 and 0x2000:0000.
+ * On the Lemote Loongson 2f system, reside between 0x1000:0000 and 0x8000:0000.
  */
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-
-#define LOONGSON_HIGHMEM_START  0x20000000
-
 #define LOONGSON_MMIO_MEM_START 0x10000000
-#define LOONGSON_MMIO_MEM_END   0x20000000
 
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_MMIO_MEM_END	0x20000000
+#else
+#define LOONGSON_MMIO_MEM_END	0x80000000
 #endif
 
 #endif /* __ASM_MACH_LOONGSON_MEM_H */
diff --git a/arch/mips/include/asm/mach-loongson/pci.h b/arch/mips/include/asm/mach-loongson/pci.h
index f1663ca..a199a4f 100644
--- a/arch/mips/include/asm/mach-loongson/pci.h
+++ b/arch/mips/include/asm/mach-loongson/pci.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2008 Zhang Le <r0bertz@gentoo.org>
+ * Copyright (c) 2009 Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
@@ -22,16 +23,39 @@
 #ifndef __ASM_MACH_LOONGSON_PCI_H_
 #define __ASM_MACH_LOONGSON_PCI_H_
 
-extern struct pci_ops bonito64_pci_ops;
+extern struct pci_ops loongson_pci_ops;
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-
-/* this pci memory space is mapped by pcimap in pci.c */
-#define LOONGSON_PCI_MEM_START	BONITO_PCILO1_BASE
-#define LOONGSON_PCI_MEM_END	(BONITO_PCILO1_BASE + 0x04000000 * 2)
 /* this is an offset from mips_io_port_base */
 #define LOONGSON_PCI_IO_START	0x00004000UL
 
-#endif
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+
+/*
+ * we use address window2 to map cpu address space to pci space
+ * window2: cpu [1G, 2G] -> pci [1G, 2G]
+ * why not use window 0 & 1? because they are used by cpu when booting.
+ * window0: cpu [0, 256M] -> ddr [0, 256M]
+ * window1: cpu [256M, 512M] -> pci [256M, 512M]
+ */
+
+/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
+#define LOONGSON_CPU_MEM_SRC	0x40000000ul		/* 1G */
+#define LOONGSON_PCI_MEM_DST	LOONGSON_CPU_MEM_SRC
+
+#define LOONGSON_PCI_MEM_START	LOONGSON_PCI_MEM_DST
+#define LOONGSON_PCI_MEM_END	(0x80000000ul-1)	/* 2G */
+
+#define MMAP_CPUTOPCI_SIZE	(LOONGSON_PCI_MEM_END - \
+					LOONGSON_PCI_MEM_START + 1)
+
+#else	/* loongson2f/32bit & loongson2e */
+
+/* this pci memory space is mapped by pcimap in pci.c */
+#define LOONGSON_PCI_MEM_START	LOONGSON_PCILO1_BASE
+#define LOONGSON_PCI_MEM_END	(LOONGSON_PCILO1_BASE + 0x04000000 * 2)
+/* this is an offset from mips_io_port_base */
+#define LOONGSON_PCI_IO_START	0x00004000UL
+
+#endif	/* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
 
 #endif /* !__ASM_MACH_LOONGSON_PCI_H_ */
diff --git a/arch/mips/include/asm/mach-powertv/asic.h b/arch/mips/include/asm/mach-powertv/asic.h
new file mode 100644
index 0000000..bcad43a
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/asic.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _ASM_MACH_POWERTV_ASIC_H
+#define _ASM_MACH_POWERTV_ASIC_H
+
+#include <linux/ioport.h>
+#include <asm/mach-powertv/asic_regs.h>
+
+#define DVR_CAPABLE     (1<<0)
+#define PCIE_CAPABLE    (1<<1)
+#define FFS_CAPABLE     (1<<2)
+#define DISPLAY_CAPABLE (1<<3)
+
+/* Platform Family types
+ * For compitability, the new value must be added in the end */
+enum family_type {
+	FAMILY_8500,
+	FAMILY_8500RNG,
+	FAMILY_4500,
+	FAMILY_1500,
+	FAMILY_8600,
+	FAMILY_4600,
+	FAMILY_4600VZA,
+	FAMILY_8600VZB,
+	FAMILY_1500VZE,
+	FAMILY_1500VZF,
+	FAMILIES
+};
+
+/* Register maps for each ASIC */
+extern const struct register_map calliope_register_map;
+extern const struct register_map cronus_register_map;
+extern const struct register_map zeus_register_map;
+
+extern struct resource dvr_cronus_resources[];
+extern struct resource dvr_zeus_resources[];
+extern struct resource non_dvr_calliope_resources[];
+extern struct resource non_dvr_cronus_resources[];
+extern struct resource non_dvr_cronuslite_resources[];
+extern struct resource non_dvr_vz_calliope_resources[];
+extern struct resource non_dvr_vze_calliope_resources[];
+extern struct resource non_dvr_vzf_calliope_resources[];
+extern struct resource non_dvr_zeus_resources[];
+
+extern void powertv_platform_init(void);
+extern void platform_alloc_bootmem(void);
+extern enum asic_type platform_get_asic(void);
+extern enum family_type platform_get_family(void);
+extern int platform_supports_dvr(void);
+extern int platform_supports_ffs(void);
+extern int platform_supports_pcie(void);
+extern int platform_supports_display(void);
+extern void configure_platform(void);
+extern void platform_configure_usb_ehci(void);
+extern void platform_unconfigure_usb_ehci(void);
+extern void platform_configure_usb_ohci(void);
+extern void platform_unconfigure_usb_ohci(void);
+
+/* Platform Resources */
+#define ASIC_RESOURCE_GET_EXISTS 1
+extern struct resource *asic_resource_get(const char *name);
+extern void platform_release_memory(void *baddr, int size);
+
+/* Reboot Cause */
+extern void set_reboot_cause(char code, unsigned int data, unsigned int data2);
+extern void set_locked_reboot_cause(char code, unsigned int data,
+	unsigned int data2);
+
+enum sys_reboot_type {
+	sys_unknown_reboot = 0x00,	/* Unknown reboot cause */
+	sys_davic_change = 0x01,	/* Reboot due to change in DAVIC
+					 * mode */
+	sys_user_reboot = 0x02,		/* Reboot initiated by user */
+	sys_system_reboot = 0x03,	/* Reboot initiated by OS */
+	sys_trap_reboot = 0x04,		/* Reboot due to a CPU trap */
+	sys_silent_reboot = 0x05,	/* Silent reboot */
+	sys_boot_ldr_reboot = 0x06,	/* Bootloader reboot */
+	sys_power_up_reboot = 0x07,	/* Power on bootup.  Older
+					 * drivers may report as
+					 * userReboot. */
+	sys_code_change = 0x08,		/* Reboot to take code change.
+					 * Older drivers may report as
+					 * userReboot. */
+	sys_hardware_reset = 0x09,	/* HW watchdog or front-panel
+					 * reset button reset.  Older
+					 * drivers may report as
+					 * userReboot. */
+	sys_watchdogInterrupt = 0x0A	/* Pre-watchdog interrupt */
+};
+
+#endif /* _ASM_MACH_POWERTV_ASIC_H */
diff --git a/arch/mips/include/asm/mach-powertv/asic_regs.h b/arch/mips/include/asm/mach-powertv/asic_regs.h
new file mode 100644
index 0000000..9a65c93
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/asic_regs.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __ASM_MACH_POWERTV_ASIC_H_
+#define __ASM_MACH_POWERTV_ASIC_H_
+#include <linux/io.h>
+
+/* ASIC types */
+enum asic_type {
+	ASIC_UNKNOWN,
+	ASIC_ZEUS,
+	ASIC_CALLIOPE,
+	ASIC_CRONUS,
+	ASIC_CRONUSLITE,
+	ASICS
+};
+
+/* hardcoded values read from Chip Version registers */
+#define CRONUS_10	0x0B4C1C20
+#define CRONUS_11	0x0B4C1C21
+#define CRONUSLITE_10	0x0B4C1C40
+
+#define NAND_FLASH_BASE	0x03000000
+#define ZEUS_IO_BASE	0x09000000
+#define CALLIOPE_IO_BASE	0x08000000
+#define CRONUS_IO_BASE	0x09000000
+#define ASIC_IO_SIZE	0x01000000
+
+/* Definitions for backward compatibility */
+#define UART1_INTSTAT	uart1_intstat
+#define UART1_INTEN	uart1_inten
+#define UART1_CONFIG1	uart1_config1
+#define UART1_CONFIG2	uart1_config2
+#define UART1_DIVISORHI	uart1_divisorhi
+#define UART1_DIVISORLO	uart1_divisorlo
+#define UART1_DATA	uart1_data
+#define UART1_STATUS	uart1_status
+
+/* ASIC register enumeration */
+struct register_map {
+	u32 eic_slow0_strt_add;
+	u32 eic_cfg_bits;
+	u32 eic_ready_status;
+
+	u32 chipver3;
+	u32 chipver2;
+	u32 chipver1;
+	u32 chipver0;
+
+	u32 uart1_intstat;
+	u32 uart1_inten;
+	u32 uart1_config1;
+	u32 uart1_config2;
+	u32 uart1_divisorhi;
+	u32 uart1_divisorlo;
+	u32 uart1_data;
+	u32 uart1_status;
+
+	u32 int_stat_3;
+	u32 int_stat_2;
+	u32 int_stat_1;
+	u32 int_stat_0;
+	u32 int_config;
+	u32 int_int_scan;
+	u32 ien_int_3;
+	u32 ien_int_2;
+	u32 ien_int_1;
+	u32 ien_int_0;
+	u32 int_level_3_3;
+	u32 int_level_3_2;
+	u32 int_level_3_1;
+	u32 int_level_3_0;
+	u32 int_level_2_3;
+	u32 int_level_2_2;
+	u32 int_level_2_1;
+	u32 int_level_2_0;
+	u32 int_level_1_3;
+	u32 int_level_1_2;
+	u32 int_level_1_1;
+	u32 int_level_1_0;
+	u32 int_level_0_3;
+	u32 int_level_0_2;
+	u32 int_level_0_1;
+	u32 int_level_0_0;
+	u32 int_docsis_en;
+
+	u32 mips_pll_setup;
+	u32 usb_fs;
+	u32 test_bus;
+	u32 crt_spare;
+	u32 usb2_ohci_int_mask;
+	u32 usb2_strap;
+	u32 ehci_hcapbase;
+	u32 ohci_hc_revision;
+	u32 bcm1_bs_lmi_steer;
+	u32 usb2_control;
+	u32 usb2_stbus_obc;
+	u32 usb2_stbus_mess_size;
+	u32 usb2_stbus_chunk_size;
+
+	u32 pcie_regs;
+	u32 tim_ch;
+	u32 tim_cl;
+	u32 gpio_dout;
+	u32 gpio_din;
+	u32 gpio_dir;
+	u32 watchdog;
+	u32 front_panel;
+
+	u32 register_maps;
+};
+
+extern enum asic_type asic;
+extern const struct register_map *register_map;
+extern unsigned long asic_phy_base;	/* Physical address of ASIC */
+extern unsigned long asic_base;		/* Virtual address of ASIC */
+
+/*
+ * Macros to interface to registers through their ioremapped address
+ * asic_reg_offset	Returns the offset of a given register from the start
+ *			of the ASIC address space
+ * asic_reg_phys_addr	Returns the physical address of the given register
+ * asic_reg_addr	Returns the iomapped virtual address of the given
+ *			register.
+ */
+#define asic_reg_offset(x)	(register_map->x)
+#define asic_reg_phys_addr(x)	(asic_phy_base + asic_reg_offset(x))
+#define asic_reg_addr(x) \
+	((unsigned int *) (asic_base + asic_reg_offset(x)))
+
+/*
+ * The asic_reg macro is gone. It should be replaced by either asic_read or
+ * asic_write, as appropriate.
+ */
+
+#define asic_read(x)		readl(asic_reg_addr(x))
+#define asic_write(v, x)	writel(v, asic_reg_addr(x))
+
+extern void asic_irq_init(void);
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/dma-coherence.h b/arch/mips/include/asm/mach-powertv/dma-coherence.h
new file mode 100644
index 0000000..5b8d5eb
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/dma-coherence.h
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ *
+ * Version from mach-generic modified to support PowerTV port
+ * Portions Copyright (C) 2009  Cisco Systems, Inc.
+ * Copyright (C) 2006  Ralf Baechle <ralf@linux-mips.org>
+ *
+ */
+
+#ifndef __ASM_MACH_POWERTV_DMA_COHERENCE_H
+#define __ASM_MACH_POWERTV_DMA_COHERENCE_H
+
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/device.h>
+#include <asm/mach-powertv/asic.h>
+
+static inline bool is_kseg2(void *addr)
+{
+	return (unsigned long)addr >= KSEG2;
+}
+
+static inline unsigned long virt_to_phys_from_pte(void *addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	unsigned long virt_addr = (unsigned long)addr;
+	unsigned long phys_addr = 0UL;
+
+	/* get the page global directory. */
+	pgd = pgd_offset_k(virt_addr);
+
+	if (!pgd_none(*pgd)) {
+		/* get the page upper directory */
+		pud = pud_offset(pgd, virt_addr);
+		if (!pud_none(*pud)) {
+			/* get the page middle directory */
+			pmd = pmd_offset(pud, virt_addr);
+			if (!pmd_none(*pmd)) {
+				/* get a pointer to the page table entry */
+				ptep = pte_offset(pmd, virt_addr);
+				pte = *ptep;
+				/* check for a valid page */
+				if (pte_present(pte)) {
+					/* get the physical address the page is
+					 * refering to */
+					phys_addr = (unsigned long)
+						page_to_phys(pte_page(pte));
+					/* add the offset within the page */
+					phys_addr |= (virt_addr & ~PAGE_MASK);
+				}
+			}
+		}
+	}
+
+	return phys_addr;
+}
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+	size_t size)
+{
+	if (is_kseg2(addr))
+		return phys_to_bus(virt_to_phys_from_pte(addr));
+	else
+		return phys_to_bus(virt_to_phys(addr));
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+	struct page *page)
+{
+	return phys_to_bus(page_to_phys(page));
+}
+
+static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
+	dma_addr_t dma_addr)
+{
+	return bus_to_phys(dma_addr);
+}
+
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
+	size_t size, enum dma_data_direction direction)
+{
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+	/*
+	 * we fall back to GFP_DMA when the mask isn't all 1s,
+	 * so we can't guarantee allocations that must be
+	 * within a tighter range than GFP_DMA..
+	 */
+	if (mask < DMA_BIT_MASK(24))
+		return 0;
+
+	return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+	return;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+					 dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+	return 0;
+}
+
+#endif /* __ASM_MACH_POWERTV_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-powertv/interrupts.h b/arch/mips/include/asm/mach-powertv/interrupts.h
new file mode 100644
index 0000000..629a574
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/interrupts.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef	_ASM_MACH_POWERTV_INTERRUPTS_H_
+#define _ASM_MACH_POWERTV_INTERRUPTS_H_
+
+/*
+ * Defines for all of the interrupt lines
+ */
+
+/* Definitions for backward compatibility */
+#define kIrq_Uart1		irq_uart1
+
+#define ibase 0
+
+/*------------- Register: int_stat_3 */
+/* 126 unused (bit 31) */
+#define irq_asc2video		(ibase+126)	/* ASC 2 Video Interrupt */
+#define irq_asc1video		(ibase+125)	/* ASC 1 Video Interrupt */
+#define irq_comms_block_wd	(ibase+124)	/* ASC 1 Video Interrupt */
+#define irq_fdma_mailbox	(ibase+123)	/* FDMA Mailbox Output */
+#define irq_fdma_gp		(ibase+122)	/* FDMA GP Output */
+#define irq_mips_pic		(ibase+121)	/* MIPS Performance Counter
+						 * Interrupt */
+#define irq_mips_timer		(ibase+120)	/* MIPS Timer Interrupt */
+#define irq_memory_protect	(ibase+119)	/* Memory Protection Interrupt
+						 * -- Ored by glue logic inside
+						 *  SPARC ILC (see
+						 *  INT_MEM_PROT_STAT, below,
+						 *  for individual interrupts)
+						 */
+/* 118 unused (bit 22) */
+#define irq_sbag		(ibase+117)	/* SBAG Interrupt -- Ored by
+						 * glue logic inside SPARC ILC
+						 * (see INT_SBAG_STAT, below,
+						 * for individual interrupts) */
+#define irq_qam_b_fec		(ibase+116)	/* QAM  B FEC Interrupt */
+#define irq_qam_a_fec		(ibase+115)	/* QAM A FEC Interrupt */
+/* 114 unused 	(bit 18) */
+#define irq_mailbox		(ibase+113)	/* Mailbox Debug Interrupt  --
+						 * Ored by glue logic inside
+						 * SPARC ILC (see
+						 * INT_MAILBOX_STAT, below, for
+						 * individual interrupts) */
+#define irq_fuse_stat1		(ibase+112)	/* Fuse Status 1 */
+#define irq_fuse_stat2		(ibase+111)	/* Fuse Status 2 */
+#define irq_fuse_stat3		(ibase+110)	/* Blitter Interrupt / Fuse
+						 * Status 3 */
+#define irq_blitter		(ibase+110)	/* Blitter Interrupt / Fuse
+						 * Status 3 */
+#define irq_avc1_pp0		(ibase+109)	/* AVC Decoder #1 PP0
+						 * Interrupt */
+#define irq_avc1_pp1		(ibase+108)	/* AVC Decoder #1 PP1
+						 * Interrupt */
+#define irq_avc1_mbe		(ibase+107)	/* AVC Decoder #1 MBE
+						 * Interrupt */
+#define irq_avc2_pp0		(ibase+106)	/* AVC Decoder #2 PP0
+						 * Interrupt */
+#define irq_avc2_pp1		(ibase+105)	/* AVC Decoder #2 PP1
+						 * Interrupt */
+#define irq_avc2_mbe		(ibase+104)	/* AVC Decoder #2 MBE
+						 * Interrupt */
+#define irq_zbug_spi		(ibase+103)	/* Zbug SPI Slave Interrupt */
+#define irq_qam_mod2		(ibase+102)	/* QAM Modulator 2 DMA
+						 * Interrupt */
+#define irq_ir_rx		(ibase+101)	/* IR RX 2 Interrupt */
+#define irq_aud_dsp2		(ibase+100)	/* Audio DSP #2 Interrupt */
+#define irq_aud_dsp1		(ibase+99)	/* Audio DSP #1 Interrupt */
+#define irq_docsis		(ibase+98)	/* DOCSIS Debug Interrupt */
+#define irq_sd_dvp1		(ibase+97)	/* SD DVP #1 Interrupt */
+#define irq_sd_dvp2		(ibase+96)	/* SD DVP #2 Interrupt */
+/*------------- Register: int_stat_2 */
+#define irq_hd_dvp		(ibase+95)	/* HD DVP Interrupt */
+#define kIrq_Prewatchdog	(ibase+94)	/* watchdog Pre-Interrupt */
+#define irq_timer2		(ibase+93)	/* Programmable Timer
+						 * Interrupt 2 */
+#define irq_1394		(ibase+92)	/* 1394 Firewire Interrupt */
+#define irq_usbohci		(ibase+91)	/* USB 2.0 OHCI Interrupt */
+#define irq_usbehci		(ibase+90)	/* USB 2.0 EHCI Interrupt */
+#define irq_pciexp		(ibase+89)	/* PCI Express 0 Interrupt */
+#define irq_pciexp0		(ibase+89)	/* PCI Express 0 Interrupt */
+#define irq_afe1		(ibase+88)	/* AFE 1 Interrupt */
+#define irq_sata		(ibase+87)	/* SATA 1 Interrupt */
+#define irq_sata1		(ibase+87)	/* SATA 1 Interrupt */
+#define irq_dtcp		(ibase+86)	/* DTCP Interrupt */
+#define irq_pciexp1		(ibase+85)	/* PCI Express 1 Interrupt */
+/* 84 unused 	(bit 20) */
+/* 83 unused 	(bit 19) */
+/* 82 unused 	(bit 18) */
+#define irq_sata2		(ibase+81)	/* SATA2 Interrupt */
+#define irq_uart2		(ibase+80)	/* UART2 Interrupt */
+#define irq_legacy_usb		(ibase+79)	/* Legacy USB Host ISR (1.1
+						 * Host module) */
+#define irq_pod			(ibase+78)	/* POD Interrupt */
+#define irq_slave_usb		(ibase+77)	/* Slave USB */
+#define irq_denc1		(ibase+76)	/* DENC #1 VTG Interrupt */
+#define irq_vbi_vtg		(ibase+75)	/* VBI VTG Interrupt */
+#define irq_afe2		(ibase+74)	/* AFE 2 Interrupt */
+#define irq_denc2		(ibase+73)	/* DENC #2 VTG Interrupt */
+#define irq_asc2		(ibase+72)	/* ASC #2 Interrupt */
+#define irq_asc1		(ibase+71)	/* ASC #1 Interrupt */
+#define irq_mod_dma		(ibase+70)	/* Modulator DMA Interrupt */
+#define irq_byte_eng1		(ibase+69)	/* Byte Engine Interrupt [1] */
+#define irq_byte_eng0		(ibase+68)	/* Byte Engine Interrupt [0] */
+/* 67 unused 	(bit 03) */
+/* 66 unused 	(bit 02) */
+/* 65 unused 	(bit 01) */
+/* 64 unused 	(bit 00) */
+/*------------- Register: int_stat_1 */
+/* 63 unused 	(bit 31) */
+/* 62 unused 	(bit 30) */
+/* 61 unused 	(bit 29) */
+/* 60 unused 	(bit 28) */
+/* 59 unused 	(bit 27) */
+/* 58 unused 	(bit 26) */
+/* 57 unused 	(bit 25) */
+/* 56 unused 	(bit 24) */
+#define irq_buf_dma_mem2mem	(ibase+55)	/* BufDMA Memory to Memory
+						 * Interrupt */
+#define irq_buf_dma_usbtransmit	(ibase+54)	/* BufDMA USB Transmit
+						 * Interrupt */
+#define irq_buf_dma_qpskpodtransmit (ibase+53)	/* BufDMA QPSK/POD Tramsit
+						 * Interrupt */
+#define irq_buf_dma_transmit_error (ibase+52)	/* BufDMA Transmit Error
+						 * Interrupt */
+#define irq_buf_dma_usbrecv	(ibase+51)	/* BufDMA USB Receive
+						 * Interrupt */
+#define irq_buf_dma_qpskpodrecv	(ibase+50)	/* BufDMA QPSK/POD Receive
+						 * Interrupt */
+#define irq_buf_dma_recv_error	(ibase+49)	/* BufDMA Receive Error
+						 * Interrupt */
+#define irq_qamdma_transmit_play (ibase+48)	/* QAMDMA Transmit/Play
+						 * Interrupt */
+#define irq_qamdma_transmit_error (ibase+47)	/* QAMDMA Transmit Error
+						 * Interrupt */
+#define irq_qamdma_recv2high	(ibase+46)	/* QAMDMA Receive 2 High
+						 * (Chans 63-32) */
+#define irq_qamdma_recv2low	(ibase+45)	/* QAMDMA Receive 2 Low
+						 * (Chans 31-0) */
+#define irq_qamdma_recv1high	(ibase+44)	/* QAMDMA Receive 1 High
+						 * (Chans 63-32) */
+#define irq_qamdma_recv1low	(ibase+43)	/* QAMDMA Receive 1 Low
+						 * (Chans 31-0) */
+#define irq_qamdma_recv_error	(ibase+42)	/* QAMDMA Receive Error
+						 * Interrupt */
+#define irq_mpegsplice		(ibase+41)	/* MPEG Splice Interrupt */
+#define irq_deinterlace_rdy	(ibase+40)	/* Deinterlacer Frame Ready
+						 * Interrupt */
+#define irq_ext_in0		(ibase+39)	/* External Interrupt irq_in0 */
+#define irq_gpio3		(ibase+38)	/* GP I/O IRQ 3 - From GP I/O
+						 * Module */
+#define irq_gpio2		(ibase+37)	/* GP I/O IRQ 2 - From GP I/O
+						 * Module (ABE_intN) */
+#define irq_pcrcmplt1		(ibase+36)	/* PCR Capture Complete  or
+						 * Discontinuity 1 */
+#define irq_pcrcmplt2		(ibase+35)	/* PCR Capture Complete or
+						 * Discontinuity 2 */
+#define irq_parse_peierr	(ibase+34)	/* PID Parser Error Detect
+						 * (PEI) */
+#define irq_parse_cont_err	(ibase+33)	/* PID Parser continuity error
+						 * detect */
+#define irq_ds1framer		(ibase+32)	/* DS1 Framer Interrupt */
+/*------------- Register: int_stat_0 */
+#define irq_gpio1		(ibase+31)	/* GP I/O IRQ 1 - From GP I/O
+						 * Module */
+#define irq_gpio0		(ibase+30)	/* GP I/O IRQ 0 - From GP I/O
+						 * Module */
+#define irq_qpsk_out_aloha	(ibase+29)	/* QPSK Output Slotted Aloha
+						 * (chan 3) Transmission
+						 * Completed OK */
+#define irq_qpsk_out_tdma	(ibase+28)	/* QPSK Output TDMA (chan 2)
+						 * Transmission Completed OK */
+#define irq_qpsk_out_reserve	(ibase+27)	/* QPSK Output Reservation
+						 * (chan 1) Transmission
+						 * Completed OK */
+#define irq_qpsk_out_aloha_err	(ibase+26)	/* QPSK Output Slotted Aloha
+						 * (chan 3)Transmission
+						 * completed with Errors. */
+#define irq_qpsk_out_tdma_err	(ibase+25)	/* QPSK Output TDMA (chan 2)
+						 * Transmission completed with
+						 * Errors. */
+#define irq_qpsk_out_rsrv_err	(ibase+24)	/* QPSK Output Reservation
+						 * (chan 1) Transmission
+						 * completed with Errors */
+#define irq_aloha_fail		(ibase+23)	/* Unsuccessful Resend of Aloha
+						 * for N times. Aloha retry
+						 * timeout for channel 3. */
+#define irq_timer1		(ibase+22)	/* Programmable Timer
+						 * Interrupt */
+#define irq_keyboard		(ibase+21)	/* Keyboard Module Interrupt */
+#define irq_i2c			(ibase+20)	/* I2C Module Interrupt */
+#define irq_spi			(ibase+19)	/* SPI Module Interrupt */
+#define irq_irblaster		(ibase+18)	/* IR Blaster Interrupt */
+#define irq_splice_detect	(ibase+17)	/* PID Key Change Interrupt or
+						 * Splice Detect Interrupt */
+#define irq_se_micro		(ibase+16)	/* Secure Micro I/F Module
+						 * Interrupt */
+#define irq_uart1		(ibase+15)	/* UART Interrupt */
+#define irq_irrecv		(ibase+14)	/* IR Receiver Interrupt */
+#define irq_host_int1		(ibase+13)	/* Host-to-Host Interrupt 1 */
+#define irq_host_int0		(ibase+12)	/* Host-to-Host Interrupt 0 */
+#define irq_qpsk_hecerr		(ibase+11)	/* QPSK HEC Error Interrupt */
+#define irq_qpsk_crcerr		(ibase+10)	/* QPSK AAL-5 CRC Error
+						 * Interrupt */
+/* 9 unused 	(bit 09) */
+/* 8 unused 	(bit 08) */
+#define irq_psicrcerr		(ibase+7) 	/* QAM PSI CRC Error
+						 * Interrupt */
+#define irq_psilength_err	(ibase+6) 	/* QAM PSI Length Error
+						 * Interrupt */
+#define irq_esfforward		(ibase+5) 	/* ESF Interrupt Mark From
+						 * Forward Path Reference -
+						 * every 3ms when forward Mbits
+						 * and forward slot control
+						 * bytes are updated. */
+#define irq_esfreverse		(ibase+4) 	/* ESF Interrupt Mark from
+						 * Reverse Path Reference -
+						 * delayed from forward mark by
+						 * the ranging delay plus a
+						 * fixed amount. When reverse
+						 * Mbits and reverse slot
+						 * control bytes are updated.
+						 * Occurs every 3ms for 3.0M and
+						 * 1.554 M upstream rates and
+						 * every 6 ms for 256K upstream
+						 * rate. */
+#define irq_aloha_timeout	(ibase+3) 	/* Slotted-Aloha timeout on
+						 * Channel 1. */
+#define irq_reservation		(ibase+2) 	/* Partial (or Incremental)
+						 * Reservation Message Completed
+						 * or Slotted aloha verify for
+						 * channel 1. */
+#define irq_aloha3		(ibase+1) 	/* Slotted-Aloha Message Verify
+						 * Interrupt or Reservation
+						 * increment completed for
+						 * channel 3. */
+#define irq_mpeg_d		(ibase+0) 	/* MPEG Decoder Interrupt */
+#endif	/* _ASM_MACH_POWERTV_INTERRUPTS_H_ */
+
diff --git a/arch/mips/include/asm/mach-powertv/ioremap.h b/arch/mips/include/asm/mach-powertv/ioremap.h
new file mode 100644
index 0000000..e6276d5
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/ioremap.h
@@ -0,0 +1,90 @@
+/*
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ * Portions Copyright (C)  Cisco Systems, Inc.
+ */
+#ifndef __ASM_MACH_POWERTV_IOREMAP_H
+#define __ASM_MACH_POWERTV_IOREMAP_H
+
+#include <linux/types.h>
+
+#define LOW_MEM_BOUNDARY_PHYS	0x20000000
+#define LOW_MEM_BOUNDARY_MASK	(~(LOW_MEM_BOUNDARY_PHYS - 1))
+
+/*
+ * The bus addresses are different than the physical addresses that
+ * the processor sees by an offset. This offset varies by ASIC
+ * version. Define a variable to hold the offset and some macros to
+ * make the conversion simpler. */
+extern unsigned long phys_to_bus_offset;
+
+#ifdef CONFIG_HIGHMEM
+#define MEM_GAP_PHYS		0x60000000
+/*
+ * TODO: We will use the hard code for conversion between physical and
+ * bus until the bootloader releases their device tree to us.
+ */
+#define phys_to_bus(x) (((x) < LOW_MEM_BOUNDARY_PHYS) ? \
+	((x) + phys_to_bus_offset) : (x))
+#define bus_to_phys(x) (((x) < MEM_GAP_PHYS_ADDR) ? \
+	((x) - phys_to_bus_offset) : (x))
+#else
+#define phys_to_bus(x) ((x) + phys_to_bus_offset)
+#define bus_to_phys(x) ((x) - phys_to_bus_offset)
+#endif
+
+/*
+ * Determine whether the address we are given is for an ASIC device
+ * Params:  addr    Address to check
+ * Returns: Zero if the address is not for ASIC devices, non-zero
+ *      if it is.
+ */
+static inline int asic_is_device_addr(phys_t addr)
+{
+	return !((phys_t)addr & (phys_t) LOW_MEM_BOUNDARY_MASK);
+}
+
+/*
+ * Determine whether the address we are given is external RAM mappable
+ * into KSEG1.
+ * Params:  addr    Address to check
+ * Returns: Zero if the address is not for external RAM and
+ */
+static inline int asic_is_lowmem_ram_addr(phys_t addr)
+{
+	/*
+	 * The RAM always starts at the following address in the processor's
+	 * physical address space
+	 */
+	static const phys_t phys_ram_base = 0x10000000;
+	phys_t bus_ram_base;
+
+	bus_ram_base = phys_to_bus_offset + phys_ram_base;
+
+	return addr >= bus_ram_base &&
+		addr < (bus_ram_base + (LOW_MEM_BOUNDARY_PHYS - phys_ram_base));
+}
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+	unsigned long flags)
+{
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return 0;
+}
+#endif /* __ASM_MACH_POWERTV_IOREMAP_H */
diff --git a/arch/mips/include/asm/mach-powertv/irq.h b/arch/mips/include/asm/mach-powertv/irq.h
new file mode 100644
index 0000000..4bd5d0c
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/irq.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _ASM_MACH_POWERTV_IRQ_H
+#define _ASM_MACH_POWERTV_IRQ_H
+#include <asm/mach-powertv/interrupts.h>
+
+#define MIPS_CPU_IRQ_BASE	ibase
+#define NR_IRQS			127
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/powertv-clock.h b/arch/mips/include/asm/mach-powertv/powertv-clock.h
new file mode 100644
index 0000000..6f3e9a0
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/powertv-clock.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/*
+ * Local definitions for the powertv PCI code
+ */
+
+#ifndef _POWERTV_PCI_POWERTV_PCI_H_
+#define _POWERTV_PCI_POWERTV_PCI_H_
+extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+extern int asic_pcie_init(void);
+extern int asic_pcie_init(void);
+
+extern int log_level;
+#endif
diff --git a/arch/mips/include/asm/mach-powertv/war.h b/arch/mips/include/asm/mach-powertv/war.h
new file mode 100644
index 0000000..7ac05ec
--- /dev/null
+++ b/arch/mips/include/asm/mach-powertv/war.h
@@ -0,0 +1,28 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This version for the PowerTV platform copied from the Malta version.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ */
+#ifndef __ASM_MACH_POWERTV_WAR_H
+#define __ASM_MACH_POWERTV_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR	0
+#define R4600_V1_HIT_CACHEOP_WAR	0
+#define R4600_V2_HIT_CACHEOP_WAR	0
+#define R5432_CP0_INTERRUPT_WAR		0
+#define BCM1250_M3_WAR			0
+#define SIBYTE_1956_WAR			0
+#define MIPS4K_ICACHE_REFILL_WAR	1
+#define MIPS_CACHE_SYNC_WAR		1
+#define TX49XX_ICACHE_INDEX_INV_WAR	0
+#define RM9000_CDEX_SMP_WAR		0
+#define ICACHE_REFILLS_WORKAROUND_WAR	1
+#define R10000_LLSC_WAR			0
+#define MIPS34K_MISSED_ITLB_WAR		0
+
+#endif /* __ASM_MACH_POWERTV_WAR_H */
diff --git a/arch/mips/include/asm/mips-boards/bonito64.h b/arch/mips/include/asm/mips-boards/bonito64.h
index a576ce0..d14e2ad 100644
--- a/arch/mips/include/asm/mips-boards/bonito64.h
+++ b/arch/mips/include/asm/mips-boards/bonito64.h
@@ -26,11 +26,6 @@
 /* offsets from base register */
 #define BONITO(x)	(x)
 
-#elif defined(CONFIG_LEMOTE_FULOONG2E)
-
-#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
-#define BONITO_IRQ_BASE   32
-
 #else
 
 /*
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 6083db5..145bb81 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -24,6 +24,33 @@
 #endif /* SMTC */
 #include <asm-generic/mm_hooks.h>
 
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+
+#define TLBMISS_HANDLER_SETUP_PGD(pgd)				\
+	tlbmiss_handler_setup_pgd((unsigned long)(pgd))
+
+static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
+{
+	/* Check for swapper_pg_dir and convert to physical address. */
+	if ((pgd & CKSEG3) == CKSEG0)
+		pgd = CPHYSADDR(pgd);
+	write_c0_context(pgd << 11);
+}
+
+#define TLBMISS_HANDLER_SETUP()						\
+	do {								\
+		TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);		\
+		write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
+	} while (0)
+
+
+static inline unsigned long get_current_pgd(void)
+{
+	return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
+}
+
+#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using  pgd_current*/
+
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
  * to the current pgd for each processor. Also, the proc. id is stuffed
@@ -46,7 +73,7 @@
 	back_to_back_c0_hazard();					\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif
-
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
 #define ASID_INC	0x40
diff --git a/arch/mips/include/asm/octeon/cvmx-agl-defs.h b/arch/mips/include/asm/octeon/cvmx-agl-defs.h
new file mode 100644
index 0000000..ec94b9a
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-agl-defs.h
@@ -0,0 +1,1194 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_AGL_DEFS_H__
+#define __CVMX_AGL_DEFS_H__
+
+#define CVMX_AGL_GMX_BAD_REG \
+	 CVMX_ADD_IO_SEG(0x00011800E0000518ull)
+#define CVMX_AGL_GMX_BIST \
+	 CVMX_ADD_IO_SEG(0x00011800E0000400ull)
+#define CVMX_AGL_GMX_DRV_CTL \
+	 CVMX_ADD_IO_SEG(0x00011800E00007F0ull)
+#define CVMX_AGL_GMX_INF_MODE \
+	 CVMX_ADD_IO_SEG(0x00011800E00007F8ull)
+#define CVMX_AGL_GMX_PRTX_CFG(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000010ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM0(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000180ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM1(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000188ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM2(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000190ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM3(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000198ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM4(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00001A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM5(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00001A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CAM_EN(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000108ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_ADR_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000100ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_DECISION(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000040ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_CHK(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000020ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000018ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_MAX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000030ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_FRM_MIN(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000028ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_IFG(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000058ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_INT_EN(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000008ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_INT_REG(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000000ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_JABBER(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000038ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_PAUSE_DROP_TIME(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000068ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000050ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000088ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000098ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DMAC(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00000A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_OCTS_DRP(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00000B8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000080ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00000C0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000090ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DMAC(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00000A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00000B0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RXX_UDD_SKP(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000048ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_RX_BP_DROPX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000420ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_BP_OFFX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000460ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_BP_ONX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000440ull + (((offset) & 1) * 8))
+#define CVMX_AGL_GMX_RX_PRT_INFO \
+	 CVMX_ADD_IO_SEG(0x00011800E00004E8ull)
+#define CVMX_AGL_GMX_RX_TX_STATUS \
+	 CVMX_ADD_IO_SEG(0x00011800E00007E8ull)
+#define CVMX_AGL_GMX_SMACX(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000230ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_STAT_BP \
+	 CVMX_ADD_IO_SEG(0x00011800E0000520ull)
+#define CVMX_AGL_GMX_TXX_APPEND(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000218ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000270ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_MIN_PKT(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000240ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_INTERVAL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000248ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_PKT_TIME(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000238ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_TOGO(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000258ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_PAUSE_ZERO(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000260ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_SOFT_PAUSE(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000250ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT0(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000280ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT1(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000288ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT2(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000290ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT3(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000298ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT4(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002A0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT5(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002A8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT6(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002B0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT7(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002B8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT8(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002C0ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STAT9(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E00002C8ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_STATS_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000268ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TXX_THRESH(offset) \
+	 CVMX_ADD_IO_SEG(0x00011800E0000210ull + (((offset) & 1) * 2048))
+#define CVMX_AGL_GMX_TX_BP \
+	 CVMX_ADD_IO_SEG(0x00011800E00004D0ull)
+#define CVMX_AGL_GMX_TX_COL_ATTEMPT \
+	 CVMX_ADD_IO_SEG(0x00011800E0000498ull)
+#define CVMX_AGL_GMX_TX_IFG \
+	 CVMX_ADD_IO_SEG(0x00011800E0000488ull)
+#define CVMX_AGL_GMX_TX_INT_EN \
+	 CVMX_ADD_IO_SEG(0x00011800E0000508ull)
+#define CVMX_AGL_GMX_TX_INT_REG \
+	 CVMX_ADD_IO_SEG(0x00011800E0000500ull)
+#define CVMX_AGL_GMX_TX_JAM \
+	 CVMX_ADD_IO_SEG(0x00011800E0000490ull)
+#define CVMX_AGL_GMX_TX_LFSR \
+	 CVMX_ADD_IO_SEG(0x00011800E00004F8ull)
+#define CVMX_AGL_GMX_TX_OVR_BP \
+	 CVMX_ADD_IO_SEG(0x00011800E00004C8ull)
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_DMAC \
+	 CVMX_ADD_IO_SEG(0x00011800E00004A0ull)
+#define CVMX_AGL_GMX_TX_PAUSE_PKT_TYPE \
+	 CVMX_ADD_IO_SEG(0x00011800E00004A8ull)
+
+union cvmx_agl_gmx_bad_reg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_bad_reg_s {
+		uint64_t reserved_38_63:26;
+		uint64_t txpsh1:1;
+		uint64_t txpop1:1;
+		uint64_t ovrflw1:1;
+		uint64_t txpsh:1;
+		uint64_t txpop:1;
+		uint64_t ovrflw:1;
+		uint64_t reserved_27_31:5;
+		uint64_t statovr:1;
+		uint64_t reserved_23_25:3;
+		uint64_t loststat:1;
+		uint64_t reserved_4_21:18;
+		uint64_t out_ovr:2;
+		uint64_t reserved_0_1:2;
+	} s;
+	struct cvmx_agl_gmx_bad_reg_s cn52xx;
+	struct cvmx_agl_gmx_bad_reg_s cn52xxp1;
+	struct cvmx_agl_gmx_bad_reg_cn56xx {
+		uint64_t reserved_35_63:29;
+		uint64_t txpsh:1;
+		uint64_t txpop:1;
+		uint64_t ovrflw:1;
+		uint64_t reserved_27_31:5;
+		uint64_t statovr:1;
+		uint64_t reserved_23_25:3;
+		uint64_t loststat:1;
+		uint64_t reserved_3_21:19;
+		uint64_t out_ovr:1;
+		uint64_t reserved_0_1:2;
+	} cn56xx;
+	struct cvmx_agl_gmx_bad_reg_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_bist {
+	uint64_t u64;
+	struct cvmx_agl_gmx_bist_s {
+		uint64_t reserved_10_63:54;
+		uint64_t status:10;
+	} s;
+	struct cvmx_agl_gmx_bist_s cn52xx;
+	struct cvmx_agl_gmx_bist_s cn52xxp1;
+	struct cvmx_agl_gmx_bist_s cn56xx;
+	struct cvmx_agl_gmx_bist_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_drv_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_drv_ctl_s {
+		uint64_t reserved_49_63:15;
+		uint64_t byp_en1:1;
+		uint64_t reserved_45_47:3;
+		uint64_t pctl1:5;
+		uint64_t reserved_37_39:3;
+		uint64_t nctl1:5;
+		uint64_t reserved_17_31:15;
+		uint64_t byp_en:1;
+		uint64_t reserved_13_15:3;
+		uint64_t pctl:5;
+		uint64_t reserved_5_7:3;
+		uint64_t nctl:5;
+	} s;
+	struct cvmx_agl_gmx_drv_ctl_s cn52xx;
+	struct cvmx_agl_gmx_drv_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_drv_ctl_cn56xx {
+		uint64_t reserved_17_63:47;
+		uint64_t byp_en:1;
+		uint64_t reserved_13_15:3;
+		uint64_t pctl:5;
+		uint64_t reserved_5_7:3;
+		uint64_t nctl:5;
+	} cn56xx;
+	struct cvmx_agl_gmx_drv_ctl_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_inf_mode {
+	uint64_t u64;
+	struct cvmx_agl_gmx_inf_mode_s {
+		uint64_t reserved_2_63:62;
+		uint64_t en:1;
+		uint64_t reserved_0_0:1;
+	} s;
+	struct cvmx_agl_gmx_inf_mode_s cn52xx;
+	struct cvmx_agl_gmx_inf_mode_s cn52xxp1;
+	struct cvmx_agl_gmx_inf_mode_s cn56xx;
+	struct cvmx_agl_gmx_inf_mode_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_prtx_cfg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_prtx_cfg_s {
+		uint64_t reserved_6_63:58;
+		uint64_t tx_en:1;
+		uint64_t rx_en:1;
+		uint64_t slottime:1;
+		uint64_t duplex:1;
+		uint64_t speed:1;
+		uint64_t en:1;
+	} s;
+	struct cvmx_agl_gmx_prtx_cfg_s cn52xx;
+	struct cvmx_agl_gmx_prtx_cfg_s cn52xxp1;
+	struct cvmx_agl_gmx_prtx_cfg_s cn56xx;
+	struct cvmx_agl_gmx_prtx_cfg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam0 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam0_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam0_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam0_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam1 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam1_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam1_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam1_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam2 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam2_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam2_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam2_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam3 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam3_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam3_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam3_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam4 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam4_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam4_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam4_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam5 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam5_s {
+		uint64_t adr:64;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam5_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam5_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_cam_en {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_cam_en_s {
+		uint64_t reserved_8_63:56;
+		uint64_t en:8;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_cam_en_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_cam_en_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_adr_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_adr_ctl_s {
+		uint64_t reserved_4_63:60;
+		uint64_t cam_mode:1;
+		uint64_t mcst:2;
+		uint64_t bcst:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xx;
+	struct cvmx_agl_gmx_rxx_adr_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xx;
+	struct cvmx_agl_gmx_rxx_adr_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_decision {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_decision_s {
+		uint64_t reserved_5_63:59;
+		uint64_t cnt:5;
+	} s;
+	struct cvmx_agl_gmx_rxx_decision_s cn52xx;
+	struct cvmx_agl_gmx_rxx_decision_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_decision_s cn56xx;
+	struct cvmx_agl_gmx_rxx_decision_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_chk {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_frm_chk_s {
+		uint64_t reserved_9_63:55;
+		uint64_t skperr:1;
+		uint64_t rcverr:1;
+		uint64_t lenerr:1;
+		uint64_t alnerr:1;
+		uint64_t fcserr:1;
+		uint64_t jabber:1;
+		uint64_t maxerr:1;
+		uint64_t reserved_1_1:1;
+		uint64_t minerr:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_frm_chk_s cn52xx;
+	struct cvmx_agl_gmx_rxx_frm_chk_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_frm_chk_s cn56xx;
+	struct cvmx_agl_gmx_rxx_frm_chk_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_frm_ctl_s {
+		uint64_t reserved_10_63:54;
+		uint64_t pre_align:1;
+		uint64_t pad_len:1;
+		uint64_t vlan_len:1;
+		uint64_t pre_free:1;
+		uint64_t ctl_smac:1;
+		uint64_t ctl_mcst:1;
+		uint64_t ctl_bck:1;
+		uint64_t ctl_drp:1;
+		uint64_t pre_strp:1;
+		uint64_t pre_chk:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xx;
+	struct cvmx_agl_gmx_rxx_frm_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xx;
+	struct cvmx_agl_gmx_rxx_frm_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_max {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_frm_max_s {
+		uint64_t reserved_16_63:48;
+		uint64_t len:16;
+	} s;
+	struct cvmx_agl_gmx_rxx_frm_max_s cn52xx;
+	struct cvmx_agl_gmx_rxx_frm_max_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_frm_max_s cn56xx;
+	struct cvmx_agl_gmx_rxx_frm_max_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_frm_min {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_frm_min_s {
+		uint64_t reserved_16_63:48;
+		uint64_t len:16;
+	} s;
+	struct cvmx_agl_gmx_rxx_frm_min_s cn52xx;
+	struct cvmx_agl_gmx_rxx_frm_min_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_frm_min_s cn56xx;
+	struct cvmx_agl_gmx_rxx_frm_min_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_ifg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_ifg_s {
+		uint64_t reserved_4_63:60;
+		uint64_t ifg:4;
+	} s;
+	struct cvmx_agl_gmx_rxx_ifg_s cn52xx;
+	struct cvmx_agl_gmx_rxx_ifg_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_ifg_s cn56xx;
+	struct cvmx_agl_gmx_rxx_ifg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_int_en {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_int_en_s {
+		uint64_t reserved_20_63:44;
+		uint64_t pause_drp:1;
+		uint64_t reserved_16_18:3;
+		uint64_t ifgerr:1;
+		uint64_t coldet:1;
+		uint64_t falerr:1;
+		uint64_t rsverr:1;
+		uint64_t pcterr:1;
+		uint64_t ovrerr:1;
+		uint64_t reserved_9_9:1;
+		uint64_t skperr:1;
+		uint64_t rcverr:1;
+		uint64_t lenerr:1;
+		uint64_t alnerr:1;
+		uint64_t fcserr:1;
+		uint64_t jabber:1;
+		uint64_t maxerr:1;
+		uint64_t reserved_1_1:1;
+		uint64_t minerr:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_int_en_s cn52xx;
+	struct cvmx_agl_gmx_rxx_int_en_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_int_en_s cn56xx;
+	struct cvmx_agl_gmx_rxx_int_en_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_int_reg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_int_reg_s {
+		uint64_t reserved_20_63:44;
+		uint64_t pause_drp:1;
+		uint64_t reserved_16_18:3;
+		uint64_t ifgerr:1;
+		uint64_t coldet:1;
+		uint64_t falerr:1;
+		uint64_t rsverr:1;
+		uint64_t pcterr:1;
+		uint64_t ovrerr:1;
+		uint64_t reserved_9_9:1;
+		uint64_t skperr:1;
+		uint64_t rcverr:1;
+		uint64_t lenerr:1;
+		uint64_t alnerr:1;
+		uint64_t fcserr:1;
+		uint64_t jabber:1;
+		uint64_t maxerr:1;
+		uint64_t reserved_1_1:1;
+		uint64_t minerr:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_int_reg_s cn52xx;
+	struct cvmx_agl_gmx_rxx_int_reg_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_int_reg_s cn56xx;
+	struct cvmx_agl_gmx_rxx_int_reg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_jabber {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_jabber_s {
+		uint64_t reserved_16_63:48;
+		uint64_t cnt:16;
+	} s;
+	struct cvmx_agl_gmx_rxx_jabber_s cn52xx;
+	struct cvmx_agl_gmx_rxx_jabber_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_jabber_s cn56xx;
+	struct cvmx_agl_gmx_rxx_jabber_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_pause_drop_time {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_pause_drop_time_s {
+		uint64_t reserved_16_63:48;
+		uint64_t status:16;
+	} s;
+	struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xx;
+	struct cvmx_agl_gmx_rxx_pause_drop_time_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xx;
+	struct cvmx_agl_gmx_rxx_pause_drop_time_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_ctl_s {
+		uint64_t reserved_1_63:63;
+		uint64_t rd_clr:1;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_octs_s {
+		uint64_t reserved_48_63:16;
+		uint64_t cnt:48;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_octs_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_octs_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_octs_ctl_s {
+		uint64_t reserved_48_63:16;
+		uint64_t cnt:48;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_dmac {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_octs_dmac_s {
+		uint64_t reserved_48_63:16;
+		uint64_t cnt:48;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_octs_drp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_octs_drp_s {
+		uint64_t reserved_48_63:16;
+		uint64_t cnt:48;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_octs_drp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_pkts_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_bad {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_pkts_bad_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_bad_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_dmac {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_stats_pkts_drp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_stats_pkts_drp_s {
+		uint64_t reserved_32_63:32;
+		uint64_t cnt:32;
+	} s;
+	struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xx;
+	struct cvmx_agl_gmx_rxx_stats_pkts_drp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rxx_udd_skp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rxx_udd_skp_s {
+		uint64_t reserved_9_63:55;
+		uint64_t fcssel:1;
+		uint64_t reserved_7_7:1;
+		uint64_t len:7;
+	} s;
+	struct cvmx_agl_gmx_rxx_udd_skp_s cn52xx;
+	struct cvmx_agl_gmx_rxx_udd_skp_s cn52xxp1;
+	struct cvmx_agl_gmx_rxx_udd_skp_s cn56xx;
+	struct cvmx_agl_gmx_rxx_udd_skp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_dropx {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rx_bp_dropx_s {
+		uint64_t reserved_6_63:58;
+		uint64_t mark:6;
+	} s;
+	struct cvmx_agl_gmx_rx_bp_dropx_s cn52xx;
+	struct cvmx_agl_gmx_rx_bp_dropx_s cn52xxp1;
+	struct cvmx_agl_gmx_rx_bp_dropx_s cn56xx;
+	struct cvmx_agl_gmx_rx_bp_dropx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_offx {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rx_bp_offx_s {
+		uint64_t reserved_6_63:58;
+		uint64_t mark:6;
+	} s;
+	struct cvmx_agl_gmx_rx_bp_offx_s cn52xx;
+	struct cvmx_agl_gmx_rx_bp_offx_s cn52xxp1;
+	struct cvmx_agl_gmx_rx_bp_offx_s cn56xx;
+	struct cvmx_agl_gmx_rx_bp_offx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_bp_onx {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rx_bp_onx_s {
+		uint64_t reserved_9_63:55;
+		uint64_t mark:9;
+	} s;
+	struct cvmx_agl_gmx_rx_bp_onx_s cn52xx;
+	struct cvmx_agl_gmx_rx_bp_onx_s cn52xxp1;
+	struct cvmx_agl_gmx_rx_bp_onx_s cn56xx;
+	struct cvmx_agl_gmx_rx_bp_onx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_prt_info {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rx_prt_info_s {
+		uint64_t reserved_18_63:46;
+		uint64_t drop:2;
+		uint64_t reserved_2_15:14;
+		uint64_t commit:2;
+	} s;
+	struct cvmx_agl_gmx_rx_prt_info_s cn52xx;
+	struct cvmx_agl_gmx_rx_prt_info_s cn52xxp1;
+	struct cvmx_agl_gmx_rx_prt_info_cn56xx {
+		uint64_t reserved_17_63:47;
+		uint64_t drop:1;
+		uint64_t reserved_1_15:15;
+		uint64_t commit:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_rx_prt_info_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_rx_tx_status {
+	uint64_t u64;
+	struct cvmx_agl_gmx_rx_tx_status_s {
+		uint64_t reserved_6_63:58;
+		uint64_t tx:2;
+		uint64_t reserved_2_3:2;
+		uint64_t rx:2;
+	} s;
+	struct cvmx_agl_gmx_rx_tx_status_s cn52xx;
+	struct cvmx_agl_gmx_rx_tx_status_s cn52xxp1;
+	struct cvmx_agl_gmx_rx_tx_status_cn56xx {
+		uint64_t reserved_5_63:59;
+		uint64_t tx:1;
+		uint64_t reserved_1_3:3;
+		uint64_t rx:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_rx_tx_status_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_smacx {
+	uint64_t u64;
+	struct cvmx_agl_gmx_smacx_s {
+		uint64_t reserved_48_63:16;
+		uint64_t smac:48;
+	} s;
+	struct cvmx_agl_gmx_smacx_s cn52xx;
+	struct cvmx_agl_gmx_smacx_s cn52xxp1;
+	struct cvmx_agl_gmx_smacx_s cn56xx;
+	struct cvmx_agl_gmx_smacx_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_stat_bp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_stat_bp_s {
+		uint64_t reserved_17_63:47;
+		uint64_t bp:1;
+		uint64_t cnt:16;
+	} s;
+	struct cvmx_agl_gmx_stat_bp_s cn52xx;
+	struct cvmx_agl_gmx_stat_bp_s cn52xxp1;
+	struct cvmx_agl_gmx_stat_bp_s cn56xx;
+	struct cvmx_agl_gmx_stat_bp_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_append {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_append_s {
+		uint64_t reserved_4_63:60;
+		uint64_t force_fcs:1;
+		uint64_t fcs:1;
+		uint64_t pad:1;
+		uint64_t preamble:1;
+	} s;
+	struct cvmx_agl_gmx_txx_append_s cn52xx;
+	struct cvmx_agl_gmx_txx_append_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_append_s cn56xx;
+	struct cvmx_agl_gmx_txx_append_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_ctl_s {
+		uint64_t reserved_2_63:62;
+		uint64_t xsdef_en:1;
+		uint64_t xscol_en:1;
+	} s;
+	struct cvmx_agl_gmx_txx_ctl_s cn52xx;
+	struct cvmx_agl_gmx_txx_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_ctl_s cn56xx;
+	struct cvmx_agl_gmx_txx_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_min_pkt {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_min_pkt_s {
+		uint64_t reserved_8_63:56;
+		uint64_t min_size:8;
+	} s;
+	struct cvmx_agl_gmx_txx_min_pkt_s cn52xx;
+	struct cvmx_agl_gmx_txx_min_pkt_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_min_pkt_s cn56xx;
+	struct cvmx_agl_gmx_txx_min_pkt_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_pkt_interval {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_pause_pkt_interval_s {
+		uint64_t reserved_16_63:48;
+		uint64_t interval:16;
+	} s;
+	struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xx;
+	struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xx;
+	struct cvmx_agl_gmx_txx_pause_pkt_interval_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_pkt_time {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_pause_pkt_time_s {
+		uint64_t reserved_16_63:48;
+		uint64_t time:16;
+	} s;
+	struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xx;
+	struct cvmx_agl_gmx_txx_pause_pkt_time_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xx;
+	struct cvmx_agl_gmx_txx_pause_pkt_time_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_togo {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_pause_togo_s {
+		uint64_t reserved_16_63:48;
+		uint64_t time:16;
+	} s;
+	struct cvmx_agl_gmx_txx_pause_togo_s cn52xx;
+	struct cvmx_agl_gmx_txx_pause_togo_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_pause_togo_s cn56xx;
+	struct cvmx_agl_gmx_txx_pause_togo_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_pause_zero {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_pause_zero_s {
+		uint64_t reserved_1_63:63;
+		uint64_t send:1;
+	} s;
+	struct cvmx_agl_gmx_txx_pause_zero_s cn52xx;
+	struct cvmx_agl_gmx_txx_pause_zero_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_pause_zero_s cn56xx;
+	struct cvmx_agl_gmx_txx_pause_zero_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_soft_pause {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_soft_pause_s {
+		uint64_t reserved_16_63:48;
+		uint64_t time:16;
+	} s;
+	struct cvmx_agl_gmx_txx_soft_pause_s cn52xx;
+	struct cvmx_agl_gmx_txx_soft_pause_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_soft_pause_s cn56xx;
+	struct cvmx_agl_gmx_txx_soft_pause_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat0 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat0_s {
+		uint64_t xsdef:32;
+		uint64_t xscol:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat0_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat0_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat0_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat0_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat1 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat1_s {
+		uint64_t scol:32;
+		uint64_t mcol:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat1_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat1_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat1_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat1_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat2 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat2_s {
+		uint64_t reserved_48_63:16;
+		uint64_t octs:48;
+	} s;
+	struct cvmx_agl_gmx_txx_stat2_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat2_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat2_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat2_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat3 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat3_s {
+		uint64_t reserved_32_63:32;
+		uint64_t pkts:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat3_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat3_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat3_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat3_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat4 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat4_s {
+		uint64_t hist1:32;
+		uint64_t hist0:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat4_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat4_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat4_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat4_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat5 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat5_s {
+		uint64_t hist3:32;
+		uint64_t hist2:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat5_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat5_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat5_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat5_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat6 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat6_s {
+		uint64_t hist5:32;
+		uint64_t hist4:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat6_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat6_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat6_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat6_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat7 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat7_s {
+		uint64_t hist7:32;
+		uint64_t hist6:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat7_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat7_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat7_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat7_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat8 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat8_s {
+		uint64_t mcst:32;
+		uint64_t bcst:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat8_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat8_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat8_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat8_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stat9 {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stat9_s {
+		uint64_t undflw:32;
+		uint64_t ctl:32;
+	} s;
+	struct cvmx_agl_gmx_txx_stat9_s cn52xx;
+	struct cvmx_agl_gmx_txx_stat9_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stat9_s cn56xx;
+	struct cvmx_agl_gmx_txx_stat9_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_stats_ctl {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_stats_ctl_s {
+		uint64_t reserved_1_63:63;
+		uint64_t rd_clr:1;
+	} s;
+	struct cvmx_agl_gmx_txx_stats_ctl_s cn52xx;
+	struct cvmx_agl_gmx_txx_stats_ctl_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_stats_ctl_s cn56xx;
+	struct cvmx_agl_gmx_txx_stats_ctl_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_txx_thresh {
+	uint64_t u64;
+	struct cvmx_agl_gmx_txx_thresh_s {
+		uint64_t reserved_6_63:58;
+		uint64_t cnt:6;
+	} s;
+	struct cvmx_agl_gmx_txx_thresh_s cn52xx;
+	struct cvmx_agl_gmx_txx_thresh_s cn52xxp1;
+	struct cvmx_agl_gmx_txx_thresh_s cn56xx;
+	struct cvmx_agl_gmx_txx_thresh_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_bp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_bp_s {
+		uint64_t reserved_2_63:62;
+		uint64_t bp:2;
+	} s;
+	struct cvmx_agl_gmx_tx_bp_s cn52xx;
+	struct cvmx_agl_gmx_tx_bp_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_bp_cn56xx {
+		uint64_t reserved_1_63:63;
+		uint64_t bp:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_tx_bp_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_col_attempt {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_col_attempt_s {
+		uint64_t reserved_5_63:59;
+		uint64_t limit:5;
+	} s;
+	struct cvmx_agl_gmx_tx_col_attempt_s cn52xx;
+	struct cvmx_agl_gmx_tx_col_attempt_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_col_attempt_s cn56xx;
+	struct cvmx_agl_gmx_tx_col_attempt_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_ifg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_ifg_s {
+		uint64_t reserved_8_63:56;
+		uint64_t ifg2:4;
+		uint64_t ifg1:4;
+	} s;
+	struct cvmx_agl_gmx_tx_ifg_s cn52xx;
+	struct cvmx_agl_gmx_tx_ifg_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_ifg_s cn56xx;
+	struct cvmx_agl_gmx_tx_ifg_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_int_en {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_int_en_s {
+		uint64_t reserved_18_63:46;
+		uint64_t late_col:2;
+		uint64_t reserved_14_15:2;
+		uint64_t xsdef:2;
+		uint64_t reserved_10_11:2;
+		uint64_t xscol:2;
+		uint64_t reserved_4_7:4;
+		uint64_t undflw:2;
+		uint64_t reserved_1_1:1;
+		uint64_t pko_nxa:1;
+	} s;
+	struct cvmx_agl_gmx_tx_int_en_s cn52xx;
+	struct cvmx_agl_gmx_tx_int_en_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_int_en_cn56xx {
+		uint64_t reserved_17_63:47;
+		uint64_t late_col:1;
+		uint64_t reserved_13_15:3;
+		uint64_t xsdef:1;
+		uint64_t reserved_9_11:3;
+		uint64_t xscol:1;
+		uint64_t reserved_3_7:5;
+		uint64_t undflw:1;
+		uint64_t reserved_1_1:1;
+		uint64_t pko_nxa:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_tx_int_en_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_int_reg {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_int_reg_s {
+		uint64_t reserved_18_63:46;
+		uint64_t late_col:2;
+		uint64_t reserved_14_15:2;
+		uint64_t xsdef:2;
+		uint64_t reserved_10_11:2;
+		uint64_t xscol:2;
+		uint64_t reserved_4_7:4;
+		uint64_t undflw:2;
+		uint64_t reserved_1_1:1;
+		uint64_t pko_nxa:1;
+	} s;
+	struct cvmx_agl_gmx_tx_int_reg_s cn52xx;
+	struct cvmx_agl_gmx_tx_int_reg_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_int_reg_cn56xx {
+		uint64_t reserved_17_63:47;
+		uint64_t late_col:1;
+		uint64_t reserved_13_15:3;
+		uint64_t xsdef:1;
+		uint64_t reserved_9_11:3;
+		uint64_t xscol:1;
+		uint64_t reserved_3_7:5;
+		uint64_t undflw:1;
+		uint64_t reserved_1_1:1;
+		uint64_t pko_nxa:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_tx_int_reg_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_jam {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_jam_s {
+		uint64_t reserved_8_63:56;
+		uint64_t jam:8;
+	} s;
+	struct cvmx_agl_gmx_tx_jam_s cn52xx;
+	struct cvmx_agl_gmx_tx_jam_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_jam_s cn56xx;
+	struct cvmx_agl_gmx_tx_jam_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_lfsr {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_lfsr_s {
+		uint64_t reserved_16_63:48;
+		uint64_t lfsr:16;
+	} s;
+	struct cvmx_agl_gmx_tx_lfsr_s cn52xx;
+	struct cvmx_agl_gmx_tx_lfsr_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_lfsr_s cn56xx;
+	struct cvmx_agl_gmx_tx_lfsr_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_ovr_bp {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_ovr_bp_s {
+		uint64_t reserved_10_63:54;
+		uint64_t en:2;
+		uint64_t reserved_6_7:2;
+		uint64_t bp:2;
+		uint64_t reserved_2_3:2;
+		uint64_t ign_full:2;
+	} s;
+	struct cvmx_agl_gmx_tx_ovr_bp_s cn52xx;
+	struct cvmx_agl_gmx_tx_ovr_bp_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_ovr_bp_cn56xx {
+		uint64_t reserved_9_63:55;
+		uint64_t en:1;
+		uint64_t reserved_5_7:3;
+		uint64_t bp:1;
+		uint64_t reserved_1_3:3;
+		uint64_t ign_full:1;
+	} cn56xx;
+	struct cvmx_agl_gmx_tx_ovr_bp_cn56xx cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_pause_pkt_dmac {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_pause_pkt_dmac_s {
+		uint64_t reserved_48_63:16;
+		uint64_t dmac:48;
+	} s;
+	struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xx;
+	struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xx;
+	struct cvmx_agl_gmx_tx_pause_pkt_dmac_s cn56xxp1;
+};
+
+union cvmx_agl_gmx_tx_pause_pkt_type {
+	uint64_t u64;
+	struct cvmx_agl_gmx_tx_pause_pkt_type_s {
+		uint64_t reserved_16_63:48;
+		uint64_t type:16;
+	} s;
+	struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xx;
+	struct cvmx_agl_gmx_tx_pause_pkt_type_s cn52xxp1;
+	struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xx;
+	struct cvmx_agl_gmx_tx_pause_pkt_type_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-mixx-defs.h b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h
new file mode 100644
index 0000000..dab6dca
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-mixx-defs.h
@@ -0,0 +1,248 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_MIXX_DEFS_H__
+#define __CVMX_MIXX_DEFS_H__
+
+#define CVMX_MIXX_BIST(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100078ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_CTL(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100020ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_INTENA(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100050ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRCNT(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100030ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRHWM(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100028ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRING1(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100010ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_IRING2(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100018ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ISR(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100048ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORCNT(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100040ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORHWM(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100038ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORING1(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100000ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_ORING2(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100008ull + (((offset) & 1) * 2048))
+#define CVMX_MIXX_REMCNT(offset) \
+	 CVMX_ADD_IO_SEG(0x0001070000100058ull + (((offset) & 1) * 2048))
+
+union cvmx_mixx_bist {
+	uint64_t u64;
+	struct cvmx_mixx_bist_s {
+		uint64_t reserved_4_63:60;
+		uint64_t mrqdat:1;
+		uint64_t ipfdat:1;
+		uint64_t irfdat:1;
+		uint64_t orfdat:1;
+	} s;
+	struct cvmx_mixx_bist_s cn52xx;
+	struct cvmx_mixx_bist_s cn52xxp1;
+	struct cvmx_mixx_bist_s cn56xx;
+	struct cvmx_mixx_bist_s cn56xxp1;
+};
+
+union cvmx_mixx_ctl {
+	uint64_t u64;
+	struct cvmx_mixx_ctl_s {
+		uint64_t reserved_8_63:56;
+		uint64_t crc_strip:1;
+		uint64_t busy:1;
+		uint64_t en:1;
+		uint64_t reset:1;
+		uint64_t lendian:1;
+		uint64_t nbtarb:1;
+		uint64_t mrq_hwm:2;
+	} s;
+	struct cvmx_mixx_ctl_s cn52xx;
+	struct cvmx_mixx_ctl_s cn52xxp1;
+	struct cvmx_mixx_ctl_s cn56xx;
+	struct cvmx_mixx_ctl_s cn56xxp1;
+};
+
+union cvmx_mixx_intena {
+	uint64_t u64;
+	struct cvmx_mixx_intena_s {
+		uint64_t reserved_7_63:57;
+		uint64_t orunena:1;
+		uint64_t irunena:1;
+		uint64_t data_drpena:1;
+		uint64_t ithena:1;
+		uint64_t othena:1;
+		uint64_t ivfena:1;
+		uint64_t ovfena:1;
+	} s;
+	struct cvmx_mixx_intena_s cn52xx;
+	struct cvmx_mixx_intena_s cn52xxp1;
+	struct cvmx_mixx_intena_s cn56xx;
+	struct cvmx_mixx_intena_s cn56xxp1;
+};
+
+union cvmx_mixx_ircnt {
+	uint64_t u64;
+	struct cvmx_mixx_ircnt_s {
+		uint64_t reserved_20_63:44;
+		uint64_t ircnt:20;
+	} s;
+	struct cvmx_mixx_ircnt_s cn52xx;
+	struct cvmx_mixx_ircnt_s cn52xxp1;
+	struct cvmx_mixx_ircnt_s cn56xx;
+	struct cvmx_mixx_ircnt_s cn56xxp1;
+};
+
+union cvmx_mixx_irhwm {
+	uint64_t u64;
+	struct cvmx_mixx_irhwm_s {
+		uint64_t reserved_40_63:24;
+		uint64_t ibplwm:20;
+		uint64_t irhwm:20;
+	} s;
+	struct cvmx_mixx_irhwm_s cn52xx;
+	struct cvmx_mixx_irhwm_s cn52xxp1;
+	struct cvmx_mixx_irhwm_s cn56xx;
+	struct cvmx_mixx_irhwm_s cn56xxp1;
+};
+
+union cvmx_mixx_iring1 {
+	uint64_t u64;
+	struct cvmx_mixx_iring1_s {
+		uint64_t reserved_60_63:4;
+		uint64_t isize:20;
+		uint64_t reserved_36_39:4;
+		uint64_t ibase:33;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_mixx_iring1_s cn52xx;
+	struct cvmx_mixx_iring1_s cn52xxp1;
+	struct cvmx_mixx_iring1_s cn56xx;
+	struct cvmx_mixx_iring1_s cn56xxp1;
+};
+
+union cvmx_mixx_iring2 {
+	uint64_t u64;
+	struct cvmx_mixx_iring2_s {
+		uint64_t reserved_52_63:12;
+		uint64_t itlptr:20;
+		uint64_t reserved_20_31:12;
+		uint64_t idbell:20;
+	} s;
+	struct cvmx_mixx_iring2_s cn52xx;
+	struct cvmx_mixx_iring2_s cn52xxp1;
+	struct cvmx_mixx_iring2_s cn56xx;
+	struct cvmx_mixx_iring2_s cn56xxp1;
+};
+
+union cvmx_mixx_isr {
+	uint64_t u64;
+	struct cvmx_mixx_isr_s {
+		uint64_t reserved_7_63:57;
+		uint64_t orun:1;
+		uint64_t irun:1;
+		uint64_t data_drp:1;
+		uint64_t irthresh:1;
+		uint64_t orthresh:1;
+		uint64_t idblovf:1;
+		uint64_t odblovf:1;
+	} s;
+	struct cvmx_mixx_isr_s cn52xx;
+	struct cvmx_mixx_isr_s cn52xxp1;
+	struct cvmx_mixx_isr_s cn56xx;
+	struct cvmx_mixx_isr_s cn56xxp1;
+};
+
+union cvmx_mixx_orcnt {
+	uint64_t u64;
+	struct cvmx_mixx_orcnt_s {
+		uint64_t reserved_20_63:44;
+		uint64_t orcnt:20;
+	} s;
+	struct cvmx_mixx_orcnt_s cn52xx;
+	struct cvmx_mixx_orcnt_s cn52xxp1;
+	struct cvmx_mixx_orcnt_s cn56xx;
+	struct cvmx_mixx_orcnt_s cn56xxp1;
+};
+
+union cvmx_mixx_orhwm {
+	uint64_t u64;
+	struct cvmx_mixx_orhwm_s {
+		uint64_t reserved_20_63:44;
+		uint64_t orhwm:20;
+	} s;
+	struct cvmx_mixx_orhwm_s cn52xx;
+	struct cvmx_mixx_orhwm_s cn52xxp1;
+	struct cvmx_mixx_orhwm_s cn56xx;
+	struct cvmx_mixx_orhwm_s cn56xxp1;
+};
+
+union cvmx_mixx_oring1 {
+	uint64_t u64;
+	struct cvmx_mixx_oring1_s {
+		uint64_t reserved_60_63:4;
+		uint64_t osize:20;
+		uint64_t reserved_36_39:4;
+		uint64_t obase:33;
+		uint64_t reserved_0_2:3;
+	} s;
+	struct cvmx_mixx_oring1_s cn52xx;
+	struct cvmx_mixx_oring1_s cn52xxp1;
+	struct cvmx_mixx_oring1_s cn56xx;
+	struct cvmx_mixx_oring1_s cn56xxp1;
+};
+
+union cvmx_mixx_oring2 {
+	uint64_t u64;
+	struct cvmx_mixx_oring2_s {
+		uint64_t reserved_52_63:12;
+		uint64_t otlptr:20;
+		uint64_t reserved_20_31:12;
+		uint64_t odbell:20;
+	} s;
+	struct cvmx_mixx_oring2_s cn52xx;
+	struct cvmx_mixx_oring2_s cn52xxp1;
+	struct cvmx_mixx_oring2_s cn56xx;
+	struct cvmx_mixx_oring2_s cn56xxp1;
+};
+
+union cvmx_mixx_remcnt {
+	uint64_t u64;
+	struct cvmx_mixx_remcnt_s {
+		uint64_t reserved_52_63:12;
+		uint64_t iremcnt:20;
+		uint64_t reserved_20_31:12;
+		uint64_t oremcnt:20;
+	} s;
+	struct cvmx_mixx_remcnt_s cn52xx;
+	struct cvmx_mixx_remcnt_s cn52xxp1;
+	struct cvmx_mixx_remcnt_s cn56xx;
+	struct cvmx_mixx_remcnt_s cn56xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-smix-defs.h b/arch/mips/include/asm/octeon/cvmx-smix-defs.h
new file mode 100644
index 0000000..9ae45fc
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-smix-defs.h
@@ -0,0 +1,178 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file 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 file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_SMIX_DEFS_H__
+#define __CVMX_SMIX_DEFS_H__
+
+#define CVMX_SMIX_CLK(offset) \
+	 CVMX_ADD_IO_SEG(0x0001180000001818ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_CMD(offset) \
+	 CVMX_ADD_IO_SEG(0x0001180000001800ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_EN(offset) \
+	 CVMX_ADD_IO_SEG(0x0001180000001820ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_RD_DAT(offset) \
+	 CVMX_ADD_IO_SEG(0x0001180000001810ull + (((offset) & 1) * 256))
+#define CVMX_SMIX_WR_DAT(offset) \
+	 CVMX_ADD_IO_SEG(0x0001180000001808ull + (((offset) & 1) * 256))
+
+union cvmx_smix_clk {
+	uint64_t u64;
+	struct cvmx_smix_clk_s {
+		uint64_t reserved_25_63:39;
+		uint64_t mode:1;
+		uint64_t reserved_21_23:3;
+		uint64_t sample_hi:5;
+		uint64_t sample_mode:1;
+		uint64_t reserved_14_14:1;
+		uint64_t clk_idle:1;
+		uint64_t preamble:1;
+		uint64_t sample:4;
+		uint64_t phase:8;
+	} s;
+	struct cvmx_smix_clk_cn30xx {
+		uint64_t reserved_21_63:43;
+		uint64_t sample_hi:5;
+		uint64_t reserved_14_15:2;
+		uint64_t clk_idle:1;
+		uint64_t preamble:1;
+		uint64_t sample:4;
+		uint64_t phase:8;
+	} cn30xx;
+	struct cvmx_smix_clk_cn30xx cn31xx;
+	struct cvmx_smix_clk_cn30xx cn38xx;
+	struct cvmx_smix_clk_cn30xx cn38xxp2;
+	struct cvmx_smix_clk_cn50xx {
+		uint64_t reserved_25_63:39;
+		uint64_t mode:1;
+		uint64_t reserved_21_23:3;
+		uint64_t sample_hi:5;
+		uint64_t reserved_14_15:2;
+		uint64_t clk_idle:1;
+		uint64_t preamble:1;
+		uint64_t sample:4;
+		uint64_t phase:8;
+	} cn50xx;
+	struct cvmx_smix_clk_s cn52xx;
+	struct cvmx_smix_clk_cn50xx cn52xxp1;
+	struct cvmx_smix_clk_s cn56xx;
+	struct cvmx_smix_clk_cn50xx cn56xxp1;
+	struct cvmx_smix_clk_cn30xx cn58xx;
+	struct cvmx_smix_clk_cn30xx cn58xxp1;
+};
+
+union cvmx_smix_cmd {
+	uint64_t u64;
+	struct cvmx_smix_cmd_s {
+		uint64_t reserved_18_63:46;
+		uint64_t phy_op:2;
+		uint64_t reserved_13_15:3;
+		uint64_t phy_adr:5;
+		uint64_t reserved_5_7:3;
+		uint64_t reg_adr:5;
+	} s;
+	struct cvmx_smix_cmd_cn30xx {
+		uint64_t reserved_17_63:47;
+		uint64_t phy_op:1;
+		uint64_t reserved_13_15:3;
+		uint64_t phy_adr:5;
+		uint64_t reserved_5_7:3;
+		uint64_t reg_adr:5;
+	} cn30xx;
+	struct cvmx_smix_cmd_cn30xx cn31xx;
+	struct cvmx_smix_cmd_cn30xx cn38xx;
+	struct cvmx_smix_cmd_cn30xx cn38xxp2;
+	struct cvmx_smix_cmd_s cn50xx;
+	struct cvmx_smix_cmd_s cn52xx;
+	struct cvmx_smix_cmd_s cn52xxp1;
+	struct cvmx_smix_cmd_s cn56xx;
+	struct cvmx_smix_cmd_s cn56xxp1;
+	struct cvmx_smix_cmd_cn30xx cn58xx;
+	struct cvmx_smix_cmd_cn30xx cn58xxp1;
+};
+
+union cvmx_smix_en {
+	uint64_t u64;
+	struct cvmx_smix_en_s {
+		uint64_t reserved_1_63:63;
+		uint64_t en:1;
+	} s;
+	struct cvmx_smix_en_s cn30xx;
+	struct cvmx_smix_en_s cn31xx;
+	struct cvmx_smix_en_s cn38xx;
+	struct cvmx_smix_en_s cn38xxp2;
+	struct cvmx_smix_en_s cn50xx;
+	struct cvmx_smix_en_s cn52xx;
+	struct cvmx_smix_en_s cn52xxp1;
+	struct cvmx_smix_en_s cn56xx;
+	struct cvmx_smix_en_s cn56xxp1;
+	struct cvmx_smix_en_s cn58xx;
+	struct cvmx_smix_en_s cn58xxp1;
+};
+
+union cvmx_smix_rd_dat {
+	uint64_t u64;
+	struct cvmx_smix_rd_dat_s {
+		uint64_t reserved_18_63:46;
+		uint64_t pending:1;
+		uint64_t val:1;
+		uint64_t dat:16;
+	} s;
+	struct cvmx_smix_rd_dat_s cn30xx;
+	struct cvmx_smix_rd_dat_s cn31xx;
+	struct cvmx_smix_rd_dat_s cn38xx;
+	struct cvmx_smix_rd_dat_s cn38xxp2;
+	struct cvmx_smix_rd_dat_s cn50xx;
+	struct cvmx_smix_rd_dat_s cn52xx;
+	struct cvmx_smix_rd_dat_s cn52xxp1;
+	struct cvmx_smix_rd_dat_s cn56xx;
+	struct cvmx_smix_rd_dat_s cn56xxp1;
+	struct cvmx_smix_rd_dat_s cn58xx;
+	struct cvmx_smix_rd_dat_s cn58xxp1;
+};
+
+union cvmx_smix_wr_dat {
+	uint64_t u64;
+	struct cvmx_smix_wr_dat_s {
+		uint64_t reserved_18_63:46;
+		uint64_t pending:1;
+		uint64_t val:1;
+		uint64_t dat:16;
+	} s;
+	struct cvmx_smix_wr_dat_s cn30xx;
+	struct cvmx_smix_wr_dat_s cn31xx;
+	struct cvmx_smix_wr_dat_s cn38xx;
+	struct cvmx_smix_wr_dat_s cn38xxp2;
+	struct cvmx_smix_wr_dat_s cn50xx;
+	struct cvmx_smix_wr_dat_s cn52xx;
+	struct cvmx_smix_wr_dat_s cn52xxp1;
+	struct cvmx_smix_wr_dat_s cn56xx;
+	struct cvmx_smix_wr_dat_s cn56xxp1;
+	struct cvmx_smix_wr_dat_s cn58xx;
+	struct cvmx_smix_wr_dat_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index cac9b1a..4d0a8c6 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -47,6 +47,7 @@
 extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
 extern void octeon_crypto_disable(struct octeon_cop2_state *state,
 				  unsigned long flags);
+extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
 
 extern void octeon_init_cvmcount(void);
 
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index d6eb613..1854336 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -390,6 +390,19 @@
 #include <asm-generic/pgtable.h>
 
 /*
+ * uncached accelerated TLB map for video memory access
+ */
+#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
+struct file;
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+		unsigned long size, pgprot_t vma_prot);
+int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
+		unsigned long size, pgprot_t *vma_prot);
+#endif
+
+/*
  * We provide our own get_unmapped area to cope with the virtual aliasing
  * constraints placed on us by the cache architecture.
  */
diff --git a/arch/mips/include/asm/sgialib.h b/arch/mips/include/asm/sgialib.h
index bfce5c7..63741ca 100644
--- a/arch/mips/include/asm/sgialib.h
+++ b/arch/mips/include/asm/sgialib.h
@@ -85,8 +85,7 @@
 extern PCHAR ArcGetEnvironmentVariable(PCHAR name);
 extern LONG ArcSetEnvironmentVariable(PCHAR name, PCHAR value);
 
-/* ARCS command line acquisition and parsing. */
-extern char *prom_getcmdline(void);
+/* ARCS command line parsing. */
 extern void prom_init_cmdline(void);
 
 /* Acquiring info about the current time, etc. */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index db0fa7b..3b6da33 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -51,9 +51,6 @@
 		LONG_S	v1, PT_ACX(sp)
 #else
 		mfhi	v1
-		LONG_S	v1, PT_HI(sp)
-		mflo	v1
-		LONG_S	v1, PT_LO(sp)
 #endif
 #ifdef CONFIG_32BIT
 		LONG_S	$8, PT_R8(sp)
@@ -62,10 +59,17 @@
 		LONG_S	$10, PT_R10(sp)
 		LONG_S	$11, PT_R11(sp)
 		LONG_S	$12, PT_R12(sp)
+#ifndef CONFIG_CPU_HAS_SMARTMIPS
+		LONG_S	v1, PT_HI(sp)
+		mflo	v1
+#endif
 		LONG_S	$13, PT_R13(sp)
 		LONG_S	$14, PT_R14(sp)
 		LONG_S	$15, PT_R15(sp)
 		LONG_S	$24, PT_R24(sp)
+#ifndef CONFIG_CPU_HAS_SMARTMIPS
+		LONG_S	v1, PT_LO(sp)
+#endif
 		.endm
 
 		.macro	SAVE_STATIC
@@ -83,15 +87,19 @@
 #ifdef CONFIG_SMP
 #ifdef CONFIG_MIPS_MT_SMTC
 #define PTEBASE_SHIFT	19	/* TCBIND */
+#define CPU_ID_REG CP0_TCBIND
+#define CPU_ID_MFC0 mfc0
+#elif defined(CONFIG_MIPS_PGD_C0_CONTEXT)
+#define PTEBASE_SHIFT	48	/* XCONTEXT */
+#define CPU_ID_REG CP0_XCONTEXT
+#define CPU_ID_MFC0 MFC0
 #else
 #define PTEBASE_SHIFT	23	/* CONTEXT */
+#define CPU_ID_REG CP0_CONTEXT
+#define CPU_ID_MFC0 MFC0
 #endif
 		.macro	get_saved_sp	/* SMP variation */
-#ifdef CONFIG_MIPS_MT_SMTC
-		mfc0	k0, CP0_TCBIND
-#else
-		MFC0	k0, CP0_CONTEXT
-#endif
+		CPU_ID_MFC0	k0, CPU_ID_REG
 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
 		lui	k1, %hi(kernelsp)
 #else
@@ -107,11 +115,7 @@
 		.endm
 
 		.macro	set_saved_sp stackp temp temp2
-#ifdef CONFIG_MIPS_MT_SMTC
-		mfc0	\temp, CP0_TCBIND
-#else
-		MFC0	\temp, CP0_CONTEXT
-#endif
+		CPU_ID_MFC0	\temp, CPU_ID_REG
 		LONG_SRL	\temp, PTEBASE_SHIFT
 		LONG_S	\stackp, kernelsp(\temp)
 		.endm
@@ -166,7 +170,6 @@
 		LONG_S	$0, PT_R0(sp)
 		mfc0	v1, CP0_STATUS
 		LONG_S	$2, PT_R2(sp)
-		LONG_S	v1, PT_STATUS(sp)
 #ifdef CONFIG_MIPS_MT_SMTC
 		/*
 		 * Ideally, these instructions would be shuffled in
@@ -178,20 +181,21 @@
 		LONG_S	v1, PT_TCSTATUS(sp)
 #endif /* CONFIG_MIPS_MT_SMTC */
 		LONG_S	$4, PT_R4(sp)
-		mfc0	v1, CP0_CAUSE
 		LONG_S	$5, PT_R5(sp)
-		LONG_S	v1, PT_CAUSE(sp)
+		LONG_S	v1, PT_STATUS(sp)
+		mfc0	v1, CP0_CAUSE
 		LONG_S	$6, PT_R6(sp)
-		MFC0	v1, CP0_EPC
 		LONG_S	$7, PT_R7(sp)
+		LONG_S	v1, PT_CAUSE(sp)
+		MFC0	v1, CP0_EPC
 #ifdef CONFIG_64BIT
 		LONG_S	$8, PT_R8(sp)
 		LONG_S	$9, PT_R9(sp)
 #endif
-		LONG_S	v1, PT_EPC(sp)
 		LONG_S	$25, PT_R25(sp)
 		LONG_S	$28, PT_R28(sp)
 		LONG_S	$31, PT_R31(sp)
+		LONG_S	v1, PT_EPC(sp)
 		ori	$28, sp, _THREAD_MASK
 		xori	$28, _THREAD_MASK
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index eecd2a9..9326af5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -2,14 +2,17 @@
 # Makefile for the Linux/MIPS kernel.
 #
 
-CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
-
 extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 		   ptrace.o reset.o setup.o signal.o syscall.o \
 		   time.o topology.o traps.o unaligned.o watch.o
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_early_printk.o = -pg
+endif
+
 obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
 obj-$(CONFIG_CEVT_R4K_LIB)	+= cevt-r4k.o
 obj-$(CONFIG_MIPS_MT_SMTC)	+= cevt-smtc.o
@@ -19,6 +22,7 @@
 obj-$(CONFIG_CEVT_TXX9)		+= cevt-txx9.o
 obj-$(CONFIG_CSRC_BCM1480)	+= csrc-bcm1480.o
 obj-$(CONFIG_CSRC_IOASIC)	+= csrc-ioasic.o
+obj-$(CONFIG_CSRC_POWERTV)	+= csrc-powertv.o
 obj-$(CONFIG_CSRC_R4K_LIB)	+= csrc-r4k.o
 obj-$(CONFIG_CSRC_SB1250)	+= csrc-sb1250.o
 obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
@@ -26,6 +30,8 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
+obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o ftrace.o
+
 obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS32)	+= r4k_fpu.o r4k_switch.o
 obj-$(CONFIG_CPU_MIPS64)	+= r4k_fpu.o r4k_switch.o
@@ -92,4 +98,8 @@
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)	+= 8250-platform.o
 
+obj-$(CONFIG_MIPS_CPUFREQ)	+= cpufreq/
+
 EXTRA_CFLAGS += -Werror
+
+CPPFLAGS_vmlinux.lds		:= $(KBUILD_CFLAGS)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 7a51866..80e202e 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -16,6 +16,7 @@
 #include <linux/ptrace.h>
 #include <linux/smp.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
@@ -32,6 +33,7 @@
  * the CPU very much.
  */
 void (*cpu_wait)(void);
+EXPORT_SYMBOL(cpu_wait);
 
 static void r3081_wait(void)
 {
diff --git a/arch/mips/kernel/cpufreq/Kconfig b/arch/mips/kernel/cpufreq/Kconfig
new file mode 100644
index 0000000..58c601e
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Kconfig
@@ -0,0 +1,41 @@
+#
+# CPU Frequency scaling
+#
+
+config MIPS_EXTERNAL_TIMER
+	bool
+
+config MIPS_CPUFREQ
+	bool
+	default y
+	depends on CPU_SUPPORTS_CPUFREQ && MIPS_EXTERNAL_TIMER
+
+if MIPS_CPUFREQ
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+if CPU_FREQ
+
+comment "CPUFreq processor drivers"
+
+config LOONGSON2_CPUFREQ
+	tristate "Loongson2 CPUFreq Driver"
+	select CPU_FREQ_TABLE
+	depends on MIPS_CPUFREQ
+	help
+	  This option adds a CPUFreq driver for loongson processors which
+	  support software configurable cpu frequency.
+
+	  Loongson2F and it's successors support this feature.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
+endif	# CPU_FREQ
+
+endmenu
+
+endif	# MIPS_CPUFREQ
diff --git a/arch/mips/kernel/cpufreq/Makefile b/arch/mips/kernel/cpufreq/Makefile
new file mode 100644
index 0000000..c3479a43
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Linux/MIPS cpufreq.
+#
+
+obj-$(CONFIG_LOONGSON2_CPUFREQ) += loongson2_cpufreq.o loongson2_clock.o
diff --git a/arch/mips/kernel/cpufreq/loongson2_clock.c b/arch/mips/kernel/cpufreq/loongson2_clock.c
new file mode 100644
index 0000000..d7ca256
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_clock.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.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/cpufreq.h>
+#include <linux/platform_device.h>
+
+#include <asm/clock.h>
+
+#include <loongson.h>
+
+static LIST_HEAD(clock_list);
+static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(clock_list_sem);
+
+/* Minimum CLK support */
+enum {
+	DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
+	DC_87PT, DC_DISABLE, DC_RESV
+};
+
+struct cpufreq_frequency_table loongson2_clockmod_table[] = {
+	{DC_RESV, CPUFREQ_ENTRY_INVALID},
+	{DC_ZERO, CPUFREQ_ENTRY_INVALID},
+	{DC_25PT, 0},
+	{DC_37PT, 0},
+	{DC_50PT, 0},
+	{DC_62PT, 0},
+	{DC_75PT, 0},
+	{DC_87PT, 0},
+	{DC_DISABLE, 0},
+	{DC_RESV, CPUFREQ_TABLE_END},
+};
+EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
+
+static struct clk cpu_clk = {
+	.name = "cpu_clk",
+	.flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
+	.rate = 800000000,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	return &cpu_clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+static void propagate_rate(struct clk *clk)
+{
+	struct clk *clkp;
+
+	list_for_each_entry(clkp, &clock_list, node) {
+		if (likely(clkp->parent != clk))
+			continue;
+		if (likely(clkp->ops && clkp->ops->recalc))
+			clkp->ops->recalc(clkp);
+		if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
+			propagate_rate(clkp);
+	}
+}
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return (unsigned long)clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return clk_set_rate_ex(clk, rate, 0);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
+{
+	int ret = 0;
+	int regval;
+	int i;
+
+	if (likely(clk->ops && clk->ops->set_rate)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&clock_lock, flags);
+		ret = clk->ops->set_rate(clk, rate, algo_id);
+		spin_unlock_irqrestore(&clock_lock, flags);
+	}
+
+	if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+		propagate_rate(clk);
+
+	for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
+	     i++) {
+		if (loongson2_clockmod_table[i].frequency ==
+		    CPUFREQ_ENTRY_INVALID)
+			continue;
+		if (rate == loongson2_clockmod_table[i].frequency)
+			break;
+	}
+	if (rate != loongson2_clockmod_table[i].frequency)
+		return -ENOTSUPP;
+
+	clk->rate = rate;
+
+	regval = LOONGSON_CHIPCFG0;
+	regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
+	LOONGSON_CHIPCFG0 = regval;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate_ex);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (likely(clk->ops && clk->ops->round_rate)) {
+		unsigned long flags, rounded;
+
+		spin_lock_irqsave(&clock_lock, flags);
+		rounded = clk->ops->round_rate(clk, rate);
+		spin_unlock_irqrestore(&clock_lock, flags);
+
+		return rounded;
+	}
+
+	return rate;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/*
+ * This is the simple version of Loongson-2 wait, Maybe we need do this in
+ * interrupt disabled content
+ */
+
+DEFINE_SPINLOCK(loongson2_wait_lock);
+void loongson2_cpu_wait(void)
+{
+	u32 cpu_freq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&loongson2_wait_lock, flags);
+	cpu_freq = LOONGSON_CHIPCFG0;
+	LOONGSON_CHIPCFG0 &= ~0x7;	/* Put CPU into wait mode */
+	LOONGSON_CHIPCFG0 = cpu_freq;	/* Restore CPU state */
+	spin_unlock_irqrestore(&loongson2_wait_lock, flags);
+}
+EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
diff --git a/arch/mips/kernel/cpufreq/loongson2_cpufreq.c b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
new file mode 100644
index 0000000..2f6a0b1
--- /dev/null
+++ b/arch/mips/kernel/cpufreq/loongson2_cpufreq.c
@@ -0,0 +1,227 @@
+/*
+ * Cpufreq driver for the loongson-2 processors
+ *
+ * The 2E revision of loongson processor not support this feature.
+ *
+ * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.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/cpufreq.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sched.h>	/* set_cpus_allowed() */
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <asm/clock.h>
+
+#include <loongson.h>
+
+static uint nowait;
+
+static struct clk *cpuclk;
+
+static void (*saved_cpu_wait) (void);
+
+static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
+					unsigned long val, void *data);
+
+static struct notifier_block loongson2_cpufreq_notifier_block = {
+	.notifier_call = loongson2_cpu_freq_notifier
+};
+
+static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
+					unsigned long val, void *data)
+{
+	if (val == CPUFREQ_POSTCHANGE)
+		current_cpu_data.udelay_val = loops_per_jiffy;
+
+	return 0;
+}
+
+static unsigned int loongson2_cpufreq_get(unsigned int cpu)
+{
+	return clk_get_rate(cpuclk);
+}
+
+/*
+ * Here we notify other drivers of the proposed change and the final change.
+ */
+static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
+				     unsigned int target_freq,
+				     unsigned int relation)
+{
+	unsigned int cpu = policy->cpu;
+	unsigned int newstate = 0;
+	cpumask_t cpus_allowed;
+	struct cpufreq_freqs freqs;
+	unsigned int freq;
+
+	if (!cpu_online(cpu))
+		return -ENODEV;
+
+	cpus_allowed = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+	if (cpufreq_frequency_table_target
+	    (policy, &loongson2_clockmod_table[0], target_freq, relation,
+	     &newstate))
+		return -EINVAL;
+
+	freq =
+	    ((cpu_clock_freq / 1000) *
+	     loongson2_clockmod_table[newstate].index) / 8;
+	if (freq < policy->min || freq > policy->max)
+		return -EINVAL;
+
+	pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000);
+
+	freqs.cpu = cpu;
+	freqs.old = loongson2_cpufreq_get(cpu);
+	freqs.new = freq;
+	freqs.flags = 0;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/* notifiers */
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	set_cpus_allowed(current, cpus_allowed);
+
+	/* setting the cpu frequency */
+	clk_set_rate(cpuclk, freq);
+
+	/* notifiers */
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	pr_debug("cpufreq: set frequency %u kHz\n", freq);
+
+	return 0;
+}
+
+static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	int i;
+
+	if (!cpu_online(policy->cpu))
+		return -ENODEV;
+
+	cpuclk = clk_get(NULL, "cpu_clk");
+	if (IS_ERR(cpuclk)) {
+		printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
+		return PTR_ERR(cpuclk);
+	}
+
+	cpuclk->rate = cpu_clock_freq / 1000;
+	if (!cpuclk->rate)
+		return -EINVAL;
+
+	/* clock table init */
+	for (i = 2;
+	     (loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END);
+	     i++)
+		loongson2_clockmod_table[i].frequency = (cpuclk->rate * i) / 8;
+
+	policy->cur = loongson2_cpufreq_get(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
+					 policy->cpu);
+
+	return cpufreq_frequency_table_cpuinfo(policy,
+					    &loongson2_clockmod_table[0]);
+}
+
+static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy,
+					      &loongson2_clockmod_table[0]);
+}
+
+static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	clk_put(cpuclk);
+	return 0;
+}
+
+static struct freq_attr *loongson2_table_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver loongson2_cpufreq_driver = {
+	.owner = THIS_MODULE,
+	.name = "loongson2",
+	.init = loongson2_cpufreq_cpu_init,
+	.verify = loongson2_cpufreq_verify,
+	.target = loongson2_cpufreq_target,
+	.get = loongson2_cpufreq_get,
+	.exit = loongson2_cpufreq_exit,
+	.attr = loongson2_table_attr,
+};
+
+static struct platform_device_id platform_device_ids[] = {
+	{
+		.name = "loongson2_cpufreq",
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(platform, platform_device_ids);
+
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = "loongson2_cpufreq",
+		.owner = THIS_MODULE,
+	},
+	.id_table = platform_device_ids,
+};
+
+static int __init cpufreq_init(void)
+{
+	int ret;
+
+	/* Register platform stuff */
+	ret = platform_driver_register(&platform_driver);
+	if (ret)
+		return ret;
+
+	pr_info("cpufreq: Loongson-2F CPU frequency driver.\n");
+
+	cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
+				  CPUFREQ_TRANSITION_NOTIFIER);
+
+	ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
+
+	if (!ret && !nowait) {
+		saved_cpu_wait = cpu_wait;
+		cpu_wait = loongson2_cpu_wait;
+	}
+
+	return ret;
+}
+
+static void __exit cpufreq_exit(void)
+{
+	if (!nowait && saved_cpu_wait)
+		cpu_wait = saved_cpu_wait;
+	cpufreq_unregister_driver(&loongson2_cpufreq_driver);
+	cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+
+	platform_driver_unregister(&platform_driver);
+}
+
+module_init(cpufreq_init);
+module_exit(cpufreq_exit);
+
+module_param(nowait, uint, 0644);
+MODULE_PARM_DESC(nowait, "Disable Loongson-2F specific wait");
+
+MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
+MODULE_DESCRIPTION("cpufreq driver for Loongson2F");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/kernel/csrc-powertv.c b/arch/mips/kernel/csrc-powertv.c
new file mode 100644
index 0000000..a27c16c
--- /dev/null
+++ b/arch/mips/kernel/csrc-powertv.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2008 Scientific-Atlanta, 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+/*
+ * The file comes from kernel/csrc-r4k.c
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+
+#include <asm/time.h>			/* Not included in linux/time.h */
+
+#include <asm/mach-powertv/asic_regs.h>
+#include "powertv-clock.h"
+
+/* MIPS PLL Register Definitions */
+#define PLL_GET_M(x)		(((x) >> 8) & 0x000000FF)
+#define PLL_GET_N(x)		(((x) >> 16) & 0x000000FF)
+#define PLL_GET_P(x)		(((x) >> 24) & 0x00000007)
+
+/*
+ * returns:  Clock frequency in kHz
+ */
+unsigned int __init mips_get_pll_freq(void)
+{
+	unsigned int pll_reg, m, n, p;
+	unsigned int fin = 54000; /* Base frequency in kHz */
+	unsigned int fout;
+
+	/* Read PLL register setting */
+	pll_reg = asic_read(mips_pll_setup);
+	m = PLL_GET_M(pll_reg);
+	n = PLL_GET_N(pll_reg);
+	p = PLL_GET_P(pll_reg);
+	pr_info("MIPS PLL Register:0x%x  M=%d  N=%d  P=%d\n", pll_reg, m, n, p);
+
+	/* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
+	fout = ((2 * n * fin) / (m * (0x01 << p)));
+
+	pr_info("MIPS Clock Freq=%d kHz\n", fout);
+
+	return fout;
+}
+
+static cycle_t c0_hpt_read(struct clocksource *cs)
+{
+	return read_c0_count();
+}
+
+static struct clocksource clocksource_mips = {
+	.name		= "powertv-counter",
+	.read		= c0_hpt_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init powertv_c0_hpt_clocksource_init(void)
+{
+	unsigned int pll_freq = mips_get_pll_freq();
+
+	pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
+		(pll_freq % 1000) * 100 / 1000);
+
+	mips_hpt_frequency = pll_freq / 2 * 1000;
+
+	clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
+
+	clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
+
+	clocksource_register(&clocksource_mips);
+}
+
+/**
+ * struct tim_c - free running counter
+ * @hi:	High 16 bits of the counter
+ * @lo:	Low 32 bits of the counter
+ *
+ * Lays out the structure of the free running counter in memory. This counter
+ * increments at a rate of 27 MHz/8 on all platforms.
+ */
+struct tim_c {
+	unsigned int hi;
+	unsigned int lo;
+};
+
+static struct tim_c *tim_c;
+
+static cycle_t tim_c_read(struct clocksource *cs)
+{
+	unsigned int hi;
+	unsigned int next_hi;
+	unsigned int lo;
+
+	hi = readl(&tim_c->hi);
+
+	for (;;) {
+		lo = readl(&tim_c->lo);
+		next_hi = readl(&tim_c->hi);
+		if (next_hi == hi)
+			break;
+		hi = next_hi;
+	}
+
+pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
+	return ((u64) hi << 32) | lo;
+}
+
+#define TIM_C_SIZE		48		/* # bits in the timer */
+
+static struct clocksource clocksource_tim_c = {
+	.name		= "powertv-tim_c",
+	.read		= tim_c_read,
+	.mask		= CLOCKSOURCE_MASK(TIM_C_SIZE),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/**
+ * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
+ *
+ * The hard part here is coming up with a constant k and shift s such that
+ * the 48-bit TIM_C value multiplied by k doesn't overflow and that value,
+ * when shifted right by s, yields the corresponding number of nanoseconds.
+ * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
+ * 1 / (27,000,000/8) seconds. Multiply that by a billion and you get the
+ * number of nanoseconds. Since the TIM_C value has 48 bits and the math is
+ * done in 64 bits, avoiding an overflow means that k must be less than
+ * 64 - 48 = 16 bits.
+ */
+static void __init powertv_tim_c_clocksource_init(void)
+{
+	int			prescale;
+	unsigned long		dividend;
+	unsigned long		k;
+	int			s;
+	const int		max_k_bits = (64 - 48) - 1;
+	const unsigned long	billion = 1000000000;
+	const unsigned long	counts_per_second = 27000000 / 8;
+
+	prescale = BITS_PER_LONG - ilog2(billion) - 1;
+	dividend = billion << prescale;
+	k = dividend / counts_per_second;
+	s = ilog2(k) - max_k_bits;
+
+	if (s < 0)
+		s = prescale;
+
+	else {
+		k >>= s;
+		s += prescale;
+	}
+
+	clocksource_tim_c.mult = k;
+	clocksource_tim_c.shift = s;
+	clocksource_tim_c.rating = 200;
+
+	clocksource_register(&clocksource_tim_c);
+	tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
+}
+
+/**
+ powertv_clocksource_init - initialize all clocksources
+ */
+void __init powertv_clocksource_init(void)
+{
+	powertv_c0_hpt_clocksource_init();
+	powertv_tim_c_clocksource_init();
+}
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
new file mode 100644
index 0000000..68b0670
--- /dev/null
+++ b/arch/mips/kernel/ftrace.c
@@ -0,0 +1,275 @@
+/*
+ * Code for replacing ftrace calls with jumps.
+ *
+ * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
+ * Copyright (C) 2009 DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ * Thanks goes to Steven Rostedt for writing the original x86 version.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/init.h>
+#include <linux/ftrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+#define JAL 0x0c000000		/* jump & link: ip --> ra, jump to target */
+#define ADDR_MASK 0x03ffffff	/*  op_code|addr : 31...26|25 ....0 */
+#define jump_insn_encode(op_code, addr) \
+	((unsigned int)((op_code) | (((addr) >> 2) & ADDR_MASK)))
+
+static unsigned int ftrace_nop = 0x00000000;
+
+static int ftrace_modify_code(unsigned long ip, unsigned int new_code)
+{
+	int faulted;
+
+	/* *(unsigned int *)ip = new_code; */
+	safe_store_code(new_code, ip, faulted);
+
+	if (unlikely(faulted))
+		return -EFAULT;
+
+	flush_icache_range(ip, ip + 8);
+
+	return 0;
+}
+
+static int lui_v1;
+static int jal_mcount;
+
+int ftrace_make_nop(struct module *mod,
+		    struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned int new;
+	int faulted;
+	unsigned long ip = rec->ip;
+
+	/* We have compiled module with -mlong-calls, but compiled the kernel
+	 * without it, we need to cope with them respectively. */
+	if (ip & 0x40000000) {
+		/* record it for ftrace_make_call */
+		if (lui_v1 == 0) {
+			/* lui_v1 = *(unsigned int *)ip; */
+			safe_load_code(lui_v1, ip, faulted);
+
+			if (unlikely(faulted))
+				return -EFAULT;
+		}
+
+		/* lui v1, hi_16bit_of_mcount        --> b 1f (0x10000004)
+		 * addiu v1, v1, low_16bit_of_mcount
+		 * move at, ra
+		 * jalr v1
+		 * nop
+		 * 				     1f: (ip + 12)
+		 */
+		new = 0x10000004;
+	} else {
+		/* record/calculate it for ftrace_make_call */
+		if (jal_mcount == 0) {
+			/* We can record it directly like this:
+			 *     jal_mcount = *(unsigned int *)ip;
+			 * Herein, jump over the first two nop instructions */
+			jal_mcount = jump_insn_encode(JAL, (MCOUNT_ADDR + 8));
+		}
+
+		/* move at, ra
+		 * jalr v1		--> nop
+		 */
+		new = ftrace_nop;
+	}
+	return ftrace_modify_code(ip, new);
+}
+
+static int modified;	/* initialized as 0 by default */
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+	unsigned int new;
+	unsigned long ip = rec->ip;
+
+	/* We just need to remove the "b ftrace_stub" at the fist time! */
+	if (modified == 0) {
+		modified = 1;
+		ftrace_modify_code(addr, ftrace_nop);
+	}
+	/* ip, module: 0xc0000000, kernel: 0x80000000 */
+	new = (ip & 0x40000000) ? lui_v1 : jal_mcount;
+
+	return ftrace_modify_code(ip, new);
+}
+
+#define FTRACE_CALL_IP ((unsigned long)(&ftrace_call))
+
+int ftrace_update_ftrace_func(ftrace_func_t func)
+{
+	unsigned int new;
+
+	new = jump_insn_encode(JAL, (unsigned long)func);
+
+	return ftrace_modify_code(FTRACE_CALL_IP, new);
+}
+
+int __init ftrace_dyn_arch_init(void *data)
+{
+	/* The return code is retured via data */
+	*(unsigned long *)data = 0;
+
+	return 0;
+}
+#endif				/* CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+extern void ftrace_graph_call(void);
+#define JMP	0x08000000	/* jump to target directly */
+#define CALL_FTRACE_GRAPH_CALLER \
+	jump_insn_encode(JMP, (unsigned long)(&ftrace_graph_caller))
+#define FTRACE_GRAPH_CALL_IP	((unsigned long)(&ftrace_graph_call))
+
+int ftrace_enable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP,
+				  CALL_FTRACE_GRAPH_CALLER);
+}
+
+int ftrace_disable_ftrace_graph_caller(void)
+{
+	return ftrace_modify_code(FTRACE_GRAPH_CALL_IP, ftrace_nop);
+}
+
+#endif				/* !CONFIG_DYNAMIC_FTRACE */
+
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
+#define S_RA_SP	(0xafbf << 16)	/* s{d,w} ra, offset(sp) */
+#define S_R_SP	(0xafb0 << 16)  /* s{d,w} R, offset(sp) */
+#define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
+
+unsigned long ftrace_get_parent_addr(unsigned long self_addr,
+				     unsigned long parent,
+				     unsigned long parent_addr,
+				     unsigned long fp)
+{
+	unsigned long sp, ip, ra;
+	unsigned int code;
+	int faulted;
+
+	/* in module or kernel? */
+	if (self_addr & 0x40000000) {
+		/* module: move to the instruction "lui v1, HI_16BIT_OF_MCOUNT" */
+		ip = self_addr - 20;
+	} else {
+		/* kernel: move to the instruction "move ra, at" */
+		ip = self_addr - 12;
+	}
+
+	/* search the text until finding the non-store instruction or "s{d,w}
+	 * ra, offset(sp)" instruction */
+	do {
+		ip -= 4;
+
+		/* get the code at "ip": code = *(unsigned int *)ip; */
+		safe_load_code(code, ip, faulted);
+
+		if (unlikely(faulted))
+			return 0;
+
+		/* If we hit the non-store instruction before finding where the
+		 * ra is stored, then this is a leaf function and it does not
+		 * store the ra on the stack. */
+		if ((code & S_R_SP) != S_R_SP)
+			return parent_addr;
+
+	} while (((code & S_RA_SP) != S_RA_SP));
+
+	sp = fp + (code & OFFSET_MASK);
+
+	/* ra = *(unsigned long *)sp; */
+	safe_load_stack(ra, sp, faulted);
+	if (unlikely(faulted))
+		return 0;
+
+	if (ra == parent)
+		return sp;
+	return 0;
+}
+
+#endif
+
+/*
+ * Hook the return address and push it in the stack of return addrs
+ * in current thread info.
+ */
+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
+			   unsigned long fp)
+{
+	unsigned long old;
+	struct ftrace_graph_ent trace;
+	unsigned long return_hooker = (unsigned long)
+	    &return_to_handler;
+	int faulted;
+
+	if (unlikely(atomic_read(&current->tracing_graph_pause)))
+		return;
+
+	/* "parent" is the stack address saved the return address of the caller
+	 * of _mcount.
+	 *
+	 * if the gcc < 4.5, a leaf function does not save the return address
+	 * in the stack address, so, we "emulate" one in _mcount's stack space,
+	 * and hijack it directly, but for a non-leaf function, it save the
+	 * return address to the its own stack space, we can not hijack it
+	 * directly, but need to find the real stack address,
+	 * ftrace_get_parent_addr() does it!
+	 *
+	 * if gcc>= 4.5, with the new -mmcount-ra-address option, for a
+	 * non-leaf function, the location of the return address will be saved
+	 * to $12 for us, and for a leaf function, only put a zero into $12. we
+	 * do it in ftrace_graph_caller of mcount.S.
+	 */
+
+	/* old = *parent; */
+	safe_load_stack(old, parent, faulted);
+	if (unlikely(faulted))
+		goto out;
+#ifndef KBUILD_MCOUNT_RA_ADDRESS
+	parent = (unsigned long *)ftrace_get_parent_addr(self_addr, old,
+							 (unsigned long)parent,
+							 fp);
+	/* If fails when getting the stack address of the non-leaf function's
+	 * ra, stop function graph tracer and return */
+	if (parent == 0)
+		goto out;
+#endif
+	/* *parent = return_hooker; */
+	safe_store_stack(return_hooker, parent, faulted);
+	if (unlikely(faulted))
+		goto out;
+
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth, fp) ==
+	    -EBUSY) {
+		*parent = old;
+		return;
+	}
+
+	trace.func = self_addr;
+
+	/* Only trace if the calling function expects to */
+	if (!ftrace_graph_entry(&trace)) {
+		current->curr_ret_stack--;
+		*parent = old;
+	}
+	return;
+out:
+	ftrace_graph_stop();
+	WARN_ON(1);
+}
+#endif				/* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 8b0b418..981f86c 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/kallsyms.h>
 #include <linux/kgdb.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/system.h>
@@ -150,3 +151,32 @@
 		kgdb_early_setup = 1;
 #endif
 }
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+void __irq_entry do_IRQ(unsigned int irq)
+{
+	irq_enter();
+	__DO_IRQ_SMTC_HOOK(irq);
+	generic_handle_irq(irq);
+	irq_exit();
+}
+
+#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
+/*
+ * To avoid inefficient and in some cases pathological re-checking of
+ * IRQ affinity, we have this variant that skips the affinity check.
+ */
+
+void __irq_entry do_IRQ_no_affinity(unsigned int irq)
+{
+	irq_enter();
+	__NO_AFFINITY_IRQ_SMTC_HOOK(irq);
+	generic_handle_irq(irq);
+	irq_exit();
+}
+
+#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
new file mode 100644
index 0000000..0a9cfdb
--- /dev/null
+++ b/arch/mips/kernel/mcount.S
@@ -0,0 +1,189 @@
+/*
+ * MIPS specific _mcount support
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2009 Lemote Inc. & DSLab, Lanzhou University, China
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ */
+
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/ftrace.h>
+
+	.text
+	.set noreorder
+	.set noat
+
+	.macro MCOUNT_SAVE_REGS
+	PTR_SUBU	sp, PT_SIZE
+	PTR_S	ra, PT_R31(sp)
+	PTR_S	AT, PT_R1(sp)
+	PTR_S	a0, PT_R4(sp)
+	PTR_S	a1, PT_R5(sp)
+	PTR_S	a2, PT_R6(sp)
+	PTR_S	a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+	PTR_S	a4, PT_R8(sp)
+	PTR_S	a5, PT_R9(sp)
+	PTR_S	a6, PT_R10(sp)
+	PTR_S	a7, PT_R11(sp)
+#endif
+	.endm
+
+	.macro MCOUNT_RESTORE_REGS
+	PTR_L	ra, PT_R31(sp)
+	PTR_L	AT, PT_R1(sp)
+	PTR_L	a0, PT_R4(sp)
+	PTR_L	a1, PT_R5(sp)
+	PTR_L	a2, PT_R6(sp)
+	PTR_L	a3, PT_R7(sp)
+#ifdef CONFIG_64BIT
+	PTR_L	a4, PT_R8(sp)
+	PTR_L	a5, PT_R9(sp)
+	PTR_L	a6, PT_R10(sp)
+	PTR_L	a7, PT_R11(sp)
+#endif
+#ifdef CONFIG_64BIT
+	PTR_ADDIU	sp, PT_SIZE
+#else
+	PTR_ADDIU	sp, (PT_SIZE + 8)
+#endif
+.endm
+
+	.macro RETURN_BACK
+	jr ra
+	 move ra, AT
+	.endm
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+
+NESTED(ftrace_caller, PT_SIZE, ra)
+	.globl _mcount
+_mcount:
+	b	ftrace_stub
+	 nop
+	lw	t1, function_trace_stop
+	bnez	t1, ftrace_stub
+	 nop
+
+	MCOUNT_SAVE_REGS
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	PTR_S	t0, PT_R12(sp)	/* t0 saved the location of the return address(at) by -mmcount-ra-address */
+#endif
+
+	move	a0, ra		/* arg1: next ip, selfaddr */
+	.globl ftrace_call
+ftrace_call:
+	nop	/* a placeholder for the call to a real tracing function */
+	 move	a1, AT		/* arg2: the caller's next ip, parent */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+	.globl ftrace_graph_call
+ftrace_graph_call:
+	nop
+	 nop
+#endif
+
+	MCOUNT_RESTORE_REGS
+	.globl ftrace_stub
+ftrace_stub:
+	RETURN_BACK
+	END(ftrace_caller)
+
+#else	/* ! CONFIG_DYNAMIC_FTRACE */
+
+NESTED(_mcount, PT_SIZE, ra)
+	lw	t1, function_trace_stop
+	bnez	t1, ftrace_stub
+	 nop
+	PTR_LA	t1, ftrace_stub
+	PTR_L	t2, ftrace_trace_function /* Prepare t2 for (1) */
+	bne	t1, t2, static_trace
+	 nop
+
+#ifdef	CONFIG_FUNCTION_GRAPH_TRACER
+	PTR_L	t3, ftrace_graph_return
+	bne	t1, t3, ftrace_graph_caller
+	 nop
+	PTR_LA	t1, ftrace_graph_entry_stub
+	PTR_L	t3, ftrace_graph_entry
+	bne	t1, t3, ftrace_graph_caller
+	 nop
+#endif
+	b	ftrace_stub
+	 nop
+
+static_trace:
+	MCOUNT_SAVE_REGS
+
+	move	a0, ra		/* arg1: next ip, selfaddr */
+	jalr	t2		/* (1) call *ftrace_trace_function */
+	 move	a1, AT		/* arg2: the caller's next ip, parent */
+
+	MCOUNT_RESTORE_REGS
+	.globl ftrace_stub
+ftrace_stub:
+	RETURN_BACK
+	END(_mcount)
+
+#endif	/* ! CONFIG_DYNAMIC_FTRACE */
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+
+NESTED(ftrace_graph_caller, PT_SIZE, ra)
+#ifdef CONFIG_DYNAMIC_FTRACE
+	PTR_L	a1, PT_R31(sp)	/* load the original ra from the stack */
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	PTR_L	t0, PT_R12(sp)	/* load the original t0 from the stack */
+#endif
+#else
+	MCOUNT_SAVE_REGS
+	move	a1, ra		/* arg2: next ip, selfaddr */
+#endif
+
+#ifdef KBUILD_MCOUNT_RA_ADDRESS
+	bnez	t0, 1f		/* non-leaf func: t0 saved the location of the return address */
+	 nop
+	PTR_LA	t0, PT_R1(sp)	/* leaf func: get the location of at(old ra) from our own stack */
+1:	move	a0, t0		/* arg1: the location of the return address */
+#else
+	PTR_LA	a0, PT_R1(sp)	/* arg1: &AT -> a0 */
+#endif
+	jal	prepare_ftrace_return
+#ifdef CONFIG_FRAME_POINTER
+	 move	a2, fp		/* arg3: frame pointer */
+#else
+#ifdef CONFIG_64BIT
+	 PTR_LA	a2, PT_SIZE(sp)
+#else
+	 PTR_LA	a2, (PT_SIZE+8)(sp)
+#endif
+#endif
+
+	MCOUNT_RESTORE_REGS
+	RETURN_BACK
+	END(ftrace_graph_caller)
+
+	.align	2
+	.globl	return_to_handler
+return_to_handler:
+	PTR_SUBU	sp, PT_SIZE
+	PTR_S	v0, PT_R2(sp)
+
+	jal	ftrace_return_to_handler
+	 PTR_S	v1, PT_R3(sp)
+
+	/* restore the real parent address: v0 -> ra */
+	move	ra, v0
+
+	PTR_L	v0, PT_R2(sp)
+	PTR_L	v1, PT_R3(sp)
+	jr	ra
+	 PTR_ADDIU	sp, PT_SIZE
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+	.set at
+	.set reorder
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 225755d..1d04807 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -13,6 +13,7 @@
 #include <asm/checksum.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <asm/ftrace.h>
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -51,3 +52,7 @@
 EXPORT_SYMBOL(__csum_partial_copy_user);
 
 EXPORT_SYMBOL(invalid_pte_table);
+#ifdef CONFIG_FUNCTION_TRACER
+/* _mcount is defined in arch/mips/kernel/mcount.S */
+EXPORT_SYMBOL(_mcount);
+#endif
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 2b290d7..f9513f9 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -58,8 +58,12 @@
 
 struct boot_mem_map boot_mem_map;
 
-static char command_line[CL_SIZE];
-       char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE;
+static char __initdata command_line[COMMAND_LINE_SIZE];
+char __initdata arcs_cmdline[COMMAND_LINE_SIZE];
+
+#ifdef CONFIG_CMDLINE_BOOL
+static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
+#endif
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
@@ -166,26 +170,8 @@
 	 * already set up initrd_start and initrd_end. In these cases
 	 * perfom sanity checks and use them if all looks good.
 	 */
-	if (!initrd_start || initrd_end <= initrd_start) {
-#ifdef CONFIG_PROBE_INITRD_HEADER
-		u32 *initrd_header;
-
-		/*
-		 * See if initrd has been added to the kernel image by
-		 * arch/mips/boot/addinitrd.c. In that case a header is
-		 * prepended to initrd and is made up by 8 bytes. The first
-		 * word is a magic number and the second one is the size of
-		 * initrd.  Initrd start must be page aligned in any cases.
-		 */
-		initrd_header = __va(PAGE_ALIGN(__pa_symbol(&_end) + 8)) - 8;
-		if (initrd_header[0] != 0x494E5244)
-			goto disable;
-		initrd_start = (unsigned long)(initrd_header + 2);
-		initrd_end = initrd_start + initrd_header[1];
-#else
+	if (!initrd_start || initrd_end <= initrd_start)
 		goto disable;
-#endif
-	}
 
 	if (initrd_start & ~PAGE_MASK) {
 		pr_err("initrd start must be page aligned\n");
@@ -476,8 +462,20 @@
 	pr_info("Determined physical RAM map:\n");
 	print_memory_map();
 
-	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERRIDE
+	strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+#else
+	if (builtin_cmdline[0]) {
+		strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
+		strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+	}
+	strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+#else
+	strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 
 	*cmdline_p = command_line;
 
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 6254041..d0c68b5 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -35,6 +35,15 @@
 
 #include "signal-common.h"
 
+static int (*save_fp_context)(struct sigcontext __user *sc);
+static int (*restore_fp_context)(struct sigcontext __user *sc);
+
+extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
+
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
+
 /*
  * Horribly complicated - with the bloody RM9000 workarounds enabled
  * the signal trampolines is moving to the end of the structure so we can
@@ -709,3 +718,40 @@
 			key_replace_session_keyring();
 	}
 }
+
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext __user *sc)
+{
+	return raw_cpu_has_fpu
+	       ? _save_fp_context(sc)
+	       : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext __user *sc)
+{
+	return raw_cpu_has_fpu
+	       ? _restore_fp_context(sc)
+	       : fpu_emulator_restore_context(sc);
+}
+#endif
+
+static int signal_setup(void)
+{
+#ifdef CONFIG_SMP
+	/* For now just do the cpu_has_fpu check when the functions are invoked */
+	save_fp_context = smp_save_fp_context;
+	restore_fp_context = smp_restore_fp_context;
+#else
+	if (cpu_has_fpu) {
+		save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
+	} else {
+		save_fp_context = fpu_emulator_save_context;
+		restore_fp_context = fpu_emulator_restore_context;
+	}
+#endif
+
+	return 0;
+}
+
+arch_initcall(signal_setup);
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 2e74075..03abaf0 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -35,6 +35,15 @@
 
 #include "signal-common.h"
 
+static int (*save_fp_context32)(struct sigcontext32 __user *sc);
+static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
+
+extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
+
+extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
+extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
+
 /*
  * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
  */
@@ -828,3 +837,18 @@
 	info.si_code |= __SI_CHLD;
 	return copy_siginfo_to_user32(uinfo, &info);
 }
+
+static int signal32_init(void)
+{
+	if (cpu_has_fpu) {
+		save_fp_context32 = _save_fp_context32;
+		restore_fp_context32 = _restore_fp_context32;
+	} else {
+		save_fp_context32 = fpu_emulator_save_context32;
+		restore_fp_context32 = fpu_emulator_restore_context32;
+	}
+
+	return 0;
+}
+
+arch_initcall(signal32_init);
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index e72e684..6cdca19 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -32,6 +32,7 @@
 #include <linux/cpumask.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
+#include <linux/ftrace.h>
 
 #include <asm/atomic.h>
 #include <asm/cpu.h>
@@ -130,7 +131,7 @@
 /*
  * Call into both interrupt handlers, as we share the IPI for them
  */
-void smp_call_function_interrupt(void)
+void __irq_entry smp_call_function_interrupt(void)
 {
 	irq_enter();
 	generic_smp_call_function_single_interrupt();
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a38e3ee..23499b5 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/processor.h>
@@ -939,23 +940,29 @@
 
 DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
-void ipi_decode(struct smtc_ipi *pipi)
+static void __irq_entry smtc_clock_tick_interrupt(void)
 {
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
+	int irq = MIPS_CPU_IRQ_BASE + 1;
+
+	irq_enter();
+	kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+	cd = &per_cpu(mips_clockevent_device, cpu);
+	cd->event_handler(cd);
+	irq_exit();
+}
+
+void ipi_decode(struct smtc_ipi *pipi)
+{
 	void *arg_copy = pipi->arg;
 	int type_copy = pipi->type;
-	int irq = MIPS_CPU_IRQ_BASE + 1;
 
 	smtc_ipi_nq(&freeIPIq, pipi);
 
 	switch (type_copy) {
 	case SMTC_CLOCK_TICK:
-		irq_enter();
-		kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
-		cd = &per_cpu(mips_clockevent_device, cpu);
-		cd->event_handler(cd);
-		irq_exit();
+		smtc_clock_tick_interrupt();
 		break;
 
 	case LINUX_SMP_IPI:
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0a18b4c..308e434 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -25,10 +25,12 @@
 #include <linux/ptrace.h>
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
+#include <linux/notifier.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
 #include <asm/break.h>
+#include <asm/cop2.h>
 #include <asm/cpu.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
@@ -79,10 +81,6 @@
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 	struct mips_fpu_struct *ctx, int has_fpu);
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
-#endif
-
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
@@ -857,6 +855,44 @@
 #endif /* CONFIG_MIPS_MT_FPAFF */
 }
 
+/*
+ * No lock; only written during early bootup by CPU 0.
+ */
+static RAW_NOTIFIER_HEAD(cu2_chain);
+
+int __ref register_cu2_notifier(struct notifier_block *nb)
+{
+	return raw_notifier_chain_register(&cu2_chain, nb);
+}
+
+int cu2_notifier_call_chain(unsigned long val, void *v)
+{
+	return raw_notifier_call_chain(&cu2_chain, val, v);
+}
+
+static int default_cu2_call(struct notifier_block *nfb, unsigned long action,
+        void *data)
+{
+	struct pt_regs *regs = data;
+
+	switch (action) {
+	default:
+		die_if_kernel("Unhandled kernel unaligned access or invalid "
+			      "instruction", regs);
+		/* Fall through  */
+
+	case CU2_EXCEPTION:
+		force_sig(SIGILL, current);
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block default_cu2_notifier = {
+	.notifier_call	= default_cu2_call,
+	.priority	= 0x80000000,		/* Run last  */
+};
+
 asmlinkage void do_cpu(struct pt_regs *regs)
 {
 	unsigned int __user *epc;
@@ -920,17 +956,9 @@
 		return;
 
 	case 2:
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-		prefetch(&current->thread.cp2);
-		local_irq_save(flags);
-		KSTK_STATUS(current) |= ST0_CU2;
-		status = read_c0_status();
-		write_c0_status(status | ST0_CU2);
-		octeon_cop2_restore(&(current->thread.cp2));
-		write_c0_status(status & ~ST0_CU2);
-		local_irq_restore(flags);
-		return;
-#endif
+		raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
+		break;
+
 	case 3:
 		break;
 	}
@@ -1367,77 +1395,6 @@
 	return set_vi_srs_handler(n, addr, 0);
 }
 
-/*
- * This is used by native signal handling
- */
-asmlinkage int (*save_fp_context)(struct sigcontext __user *sc);
-asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc);
-
-extern asmlinkage int _save_fp_context(struct sigcontext __user *sc);
-extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
-
-extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
-extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
-
-#ifdef CONFIG_SMP
-static int smp_save_fp_context(struct sigcontext __user *sc)
-{
-	return raw_cpu_has_fpu
-	       ? _save_fp_context(sc)
-	       : fpu_emulator_save_context(sc);
-}
-
-static int smp_restore_fp_context(struct sigcontext __user *sc)
-{
-	return raw_cpu_has_fpu
-	       ? _restore_fp_context(sc)
-	       : fpu_emulator_restore_context(sc);
-}
-#endif
-
-static inline void signal_init(void)
-{
-#ifdef CONFIG_SMP
-	/* For now just do the cpu_has_fpu check when the functions are invoked */
-	save_fp_context = smp_save_fp_context;
-	restore_fp_context = smp_restore_fp_context;
-#else
-	if (cpu_has_fpu) {
-		save_fp_context = _save_fp_context;
-		restore_fp_context = _restore_fp_context;
-	} else {
-		save_fp_context = fpu_emulator_save_context;
-		restore_fp_context = fpu_emulator_restore_context;
-	}
-#endif
-}
-
-#ifdef CONFIG_MIPS32_COMPAT
-
-/*
- * This is used by 32-bit signal stuff on the 64-bit kernel
- */
-asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc);
-asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc);
-
-extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
-
-extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
-extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
-
-static inline void signal32_init(void)
-{
-	if (cpu_has_fpu) {
-		save_fp_context32 = _save_fp_context32;
-		restore_fp_context32 = _restore_fp_context32;
-	} else {
-		save_fp_context32 = fpu_emulator_save_context32;
-		restore_fp_context32 = fpu_emulator_restore_context32;
-	}
-}
-#endif
-
 extern void cpu_cache_init(void);
 extern void tlb_init(void);
 extern void flush_tlb_handlers(void);
@@ -1751,13 +1708,10 @@
 	else
 		memcpy((void *)(ebase + 0x080), &except_vec3_generic, 0x80);
 
-	signal_init();
-#ifdef CONFIG_MIPS32_COMPAT
-	signal32_init();
-#endif
-
 	local_flush_icache_range(ebase, ebase + 0x400);
 	flush_tlb_handlers();
 
 	sort_extable(__start___dbe_table, __stop___dbe_table);
+
+	register_cu2_notifier(&default_cu2_notifier);
 }
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 67bd626..69b039c 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -81,6 +81,7 @@
 #include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/byteorder.h>
+#include <asm/cop2.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -451,17 +452,27 @@
 		 */
 		goto sigbus;
 
+	/*
+	 * COP2 is available to implementor for application specific use.
+	 * It's up to applications to register a notifier chain and do
+	 * whatever they have to do, including possible sending of signals.
+	 */
 	case lwc2_op:
+		cu2_notifier_call_chain(CU2_LWC2_OP, regs);
+		break;
+
 	case ldc2_op:
+		cu2_notifier_call_chain(CU2_LDC2_OP, regs);
+		break;
+
 	case swc2_op:
+		cu2_notifier_call_chain(CU2_SWC2_OP, regs);
+		break;
+
 	case sdc2_op:
-		/*
-		 * These are the coprocessor 2 load/stores.  The current
-		 * implementations don't use cp2 and cp2 should always be
-		 * disabled in c0_status.  So send SIGILL.
-                 * (No longer true: The Sony Praystation uses cp2 for
-                 * 3D matrix operations.  Dunno if that thingy has a MMU ...)
-		 */
+		cu2_notifier_call_chain(CU2_SDC2_OP, regs);
+		break;
+
 	default:
 		/*
 		 * Pheeee...  We encountered an yet unknown instruction or
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 162b299..f25df73 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -46,6 +46,7 @@
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
 		*(.text.*)
 		*(.fixup)
 		*(.gnu.warning)
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
index 0bb6037..8e388da 100644
--- a/arch/mips/lasat/picvue_proc.c
+++ b/arch/mips/lasat/picvue_proc.c
@@ -4,12 +4,14 @@
  * Brian Murphy <brian.murphy@eicon.com>
  *
  */
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/interrupt.h>
 
 #include <linux/timer.h>
@@ -38,12 +40,9 @@
 
 static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
 
-static int pvc_proc_read_line(char *page, char **start,
-			     off_t off, int count,
-			     int *eof, void *data)
+static int pvc_line_proc_show(struct seq_file *m, void *v)
 {
-	char *origpage = page;
-	int lineno = *(int *)data;
+	int lineno = *(int *)m->private;
 
 	if (lineno < 0 || lineno > PVC_NLINES) {
 		printk(KERN_WARNING "proc_read_line: invalid lineno %d\n", lineno);
@@ -51,45 +50,66 @@
 	}
 
 	mutex_lock(&pvc_mutex);
-	page += sprintf(page, "%s\n", pvc_lines[lineno]);
+	seq_printf(m, "%s\n", pvc_lines[lineno]);
 	mutex_unlock(&pvc_mutex);
 
-	return page - origpage;
+	return 0;
 }
 
-static int pvc_proc_write_line(struct file *file, const char *buffer,
-			   unsigned long count, void *data)
+static int pvc_line_proc_open(struct inode *inode, struct file *file)
 {
-	int origcount = count;
-	int lineno = *(int *)data;
+	return single_open(file, pvc_line_proc_show, PDE(inode)->data);
+}
 
-	if (lineno < 0 || lineno > PVC_NLINES) {
-		printk(KERN_WARNING "proc_write_line: invalid lineno %d\n",
-		       lineno);
-		return origcount;
-	}
+static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
+				   size_t count, loff_t *pos)
+{
+	int lineno = *(int *)PDE(file->f_path.dentry->d_inode)->data;
+	char kbuf[PVC_LINELEN];
+	size_t len;
 
-	if (count > PVC_LINELEN)
-		count = PVC_LINELEN;
+	BUG_ON(lineno < 0 || lineno > PVC_NLINES);
 
-	if (buffer[count-1] == '\n')
-		count--;
+	len = min(count, sizeof(kbuf) - 1);
+	if (copy_from_user(kbuf, buf, len))
+		return -EFAULT;
+	kbuf[len] = '\0';
+
+	if (len > 0 && kbuf[len - 1] == '\n')
+		len--;
 
 	mutex_lock(&pvc_mutex);
-	strncpy(pvc_lines[lineno], buffer, count);
-	pvc_lines[lineno][count] = '\0';
+	strncpy(pvc_lines[lineno], kbuf, len);
+	pvc_lines[lineno][len] = '\0';
 	mutex_unlock(&pvc_mutex);
 
 	tasklet_schedule(&pvc_display_tasklet);
 
-	return origcount;
+	return count;
 }
 
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
-			   unsigned long count, void *data)
+static const struct file_operations pvc_line_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pvc_line_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= pvc_line_proc_write,
+};
+
+static ssize_t pvc_scroll_proc_write(struct file *file, const char __user *buf,
+				     size_t count, loff_t *pos)
 {
-	int origcount = count;
-	int cmd = simple_strtol(buffer, NULL, 10);
+	char kbuf[42];
+	size_t len;
+	int cmd;
+
+	len = min(count, sizeof(kbuf) - 1);
+	if (copy_from_user(kbuf, buf, len))
+		return -EFAULT;
+	kbuf[len] = '\0';
+
+	cmd = simple_strtol(kbuf, NULL, 10);
 
 	mutex_lock(&pvc_mutex);
 	if (scroll_interval != 0)
@@ -110,22 +130,31 @@
 	}
 	mutex_unlock(&pvc_mutex);
 
-	return origcount;
+	return count;
 }
 
-static int pvc_proc_read_scroll(char *page, char **start,
-			     off_t off, int count,
-			     int *eof, void *data)
+static int pvc_scroll_proc_show(struct seq_file *m, void *v)
 {
-	char *origpage = page;
-
 	mutex_lock(&pvc_mutex);
-	page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
+	seq_printf(m, "%d\n", scroll_dir * scroll_interval);
 	mutex_unlock(&pvc_mutex);
 
-	return page - origpage;
+	return 0;
 }
 
+static int pvc_scroll_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pvc_scroll_proc_show, NULL);
+}
+
+static const struct file_operations pvc_scroll_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pvc_scroll_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= pvc_scroll_proc_write,
+};
 
 void pvc_proc_timerfunc(unsigned long data)
 {
@@ -163,22 +192,16 @@
 		pvc_linedata[i] = i;
 	}
 	for (i = 0; i < PVC_NLINES; i++) {
-		proc_entry = create_proc_entry(pvc_linename[i], 0644,
-					       pvc_display_dir);
+		proc_entry = proc_create_data(pvc_linename[i], 0644, pvc_display_dir,
+					&pvc_line_proc_fops, &pvc_linedata[i]);
 		if (proc_entry == NULL)
 			goto error;
-
-		proc_entry->read_proc = pvc_proc_read_line;
-		proc_entry->write_proc = pvc_proc_write_line;
-		proc_entry->data = &pvc_linedata[i];
 	}
-	proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
+	proc_entry = proc_create("scroll", 0644, pvc_display_dir,
+				 &pvc_scroll_proc_fops);
 	if (proc_entry == NULL)
 		goto error;
 
-	proc_entry->write_proc = pvc_proc_write_scroll;
-	proc_entry->read_proc = pvc_proc_read_scroll;
-
 	init_timer(&timer);
 	timer.function = pvc_proc_timerfunc;
 
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
index 6acc6cb..20fde19 100644
--- a/arch/mips/lasat/prom.c
+++ b/arch/mips/lasat/prom.c
@@ -100,8 +100,8 @@
 
 	/* Get the command line */
 	if (argc > 0) {
-		strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
-		arcs_cmdline[CL_SIZE-1] = '\0';
+		strncpy(arcs_cmdline, argv[0], COMMAND_LINE_SIZE-1);
+		arcs_cmdline[COMMAND_LINE_SIZE-1] = '\0';
 	}
 
 	/* Set the I/O base address */
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 14b9a28..d87ffd0 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -204,7 +204,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_lasat_prid,
-.	},
+	},
 #ifdef CONFIG_INET
 	{
 		.procname	= "ipaddr",
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index d450925..3df1967 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -1,31 +1,85 @@
 choice
-    prompt "Machine Type"
-    depends on MACH_LOONGSON
+	prompt "Machine Type"
+	depends on MACH_LOONGSON
 
 config LEMOTE_FULOONG2E
-    bool "Lemote Fuloong(2e) mini-PC"
-    select ARCH_SPARSEMEM_ENABLE
-    select CEVT_R4K
-    select CSRC_R4K
-    select SYS_HAS_CPU_LOONGSON2E
-    select DMA_NONCOHERENT
-    select BOOT_ELF32
-    select BOARD_SCACHE
-    select HW_HAS_PCI
-    select I8259
-    select ISA
-    select IRQ_CPU
-    select SYS_SUPPORTS_32BIT_KERNEL
-    select SYS_SUPPORTS_64BIT_KERNEL
-    select SYS_SUPPORTS_LITTLE_ENDIAN
-    select SYS_SUPPORTS_HIGHMEM
-    select SYS_HAS_EARLY_PRINTK
-    select GENERIC_HARDIRQS_NO__DO_IRQ
-    select GENERIC_ISA_DMA_SUPPORT_BROKEN
-    select CPU_HAS_WB
-    help
-      Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
-      an FPGA northbridge
+	bool "Lemote Fuloong(2e) mini-PC"
+	select ARCH_SPARSEMEM_ENABLE
+	select CEVT_R4K
+	select CSRC_R4K
+	select SYS_HAS_CPU_LOONGSON2E
+	select DMA_NONCOHERENT
+	select BOOT_ELF32
+	select BOARD_SCACHE
+	select HW_HAS_PCI
+	select I8259
+	select ISA
+	select IRQ_CPU
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_HAS_EARLY_PRINTK
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_ISA_DMA_SUPPORT_BROKEN
+	select CPU_HAS_WB
+	help
+	  Lemote Fuloong(2e) mini-PC board based on the Chinese Loongson-2E CPU and
+	  an FPGA northbridge
 
-      Lemote Fuloong(2e) mini PC have a VIA686B south bridge.
+	  Lemote Fuloong(2e) mini PC have a VIA686B south bridge.
+
+config LEMOTE_MACH2F
+	bool "Lemote Loongson 2F family machines"
+	select ARCH_SPARSEMEM_ENABLE
+	select BOARD_SCACHE
+	select BOOT_ELF32
+	select CEVT_R4K if ! MIPS_EXTERNAL_TIMER
+	select CPU_HAS_WB
+	select CS5536
+	select CSRC_R4K if ! MIPS_EXTERNAL_TIMER
+	select DMA_NONCOHERENT
+	select GENERIC_HARDIRQS_NO__DO_IRQ
+	select GENERIC_ISA_DMA_SUPPORT_BROKEN
+	select HW_HAS_PCI
+	select I8259
+	select IRQ_CPU
+	select ISA
+	select SYS_HAS_CPU_LOONGSON2F
+	select SYS_HAS_EARLY_PRINTK
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_HIGHMEM
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  Lemote Loongson 2F family machines utilize the 2F revision of
+	  Loongson processor and the AMD CS5536 south bridge.
+
+	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
+	  LingLoong allinone PC and so forth.
 endchoice
+
+config CS5536
+	bool
+
+config CS5536_MFGPT
+	bool "CS5536 MFGPT Timer"
+	depends on CS5536
+	select MIPS_EXTERNAL_TIMER
+	help
+	  This option enables the mfgpt0 timer of AMD CS5536.
+
+	  If you want to enable the Loongson2 CPUFreq Driver, Please enable
+	  this option at first, otherwise, You will get wrong system time.
+
+	  If unsure, say Yes.
+
+config LOONGSON_SUSPEND
+	bool
+	default y
+	depends on CPU_SUPPORTS_CPUFREQ && SUSPEND
+
+config LOONGSON_UART_BASE
+	bool
+	default y
+	depends on EARLY_PRINTK || SERIAL_8250
diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
index 39048c4..2b76cb0 100644
--- a/arch/mips/loongson/Makefile
+++ b/arch/mips/loongson/Makefile
@@ -9,3 +9,9 @@
 #
 
 obj-$(CONFIG_LEMOTE_FULOONG2E)  += fuloong-2e/
+
+#
+# Lemote loongson2f family machines
+#
+
+obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
diff --git a/arch/mips/loongson/common/Makefile b/arch/mips/loongson/common/Makefile
index 656b3cc..7668c4d 100644
--- a/arch/mips/loongson/common/Makefile
+++ b/arch/mips/loongson/common/Makefile
@@ -3,9 +3,23 @@
 #
 
 obj-y += setup.o init.o cmdline.o env.o time.o reset.o irq.o \
-    pci.o bonito-irq.o mem.o machtype.o
+    pci.o bonito-irq.o mem.o machtype.o platform.o
 
 #
-# Early printk support
+# Serial port support
 #
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_SERIAL_8250) += serial.o
+obj-$(CONFIG_LOONGSON_UART_BASE) += uart_base.o
+
+#
+# Enable CS5536 Virtual Support Module(VSM) to virtulize the PCI configure
+# space
+#
+obj-$(CONFIG_CS5536) += cs5536/
+
+#
+# Suspend Support
+#
+
+obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
diff --git a/arch/mips/loongson/common/bonito-irq.c b/arch/mips/loongson/common/bonito-irq.c
index 3e31e7a..2dc2a4c 100644
--- a/arch/mips/loongson/common/bonito-irq.c
+++ b/arch/mips/loongson/common/bonito-irq.c
@@ -12,18 +12,19 @@
  *  option) any later version.
  */
 #include <linux/interrupt.h>
+#include <linux/compiler.h>
 
 #include <loongson.h>
 
 static inline void bonito_irq_enable(unsigned int irq)
 {
-	BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+	LOONGSON_INTENSET = (1 << (irq - LOONGSON_IRQ_BASE));
 	mmiowb();
 }
 
 static inline void bonito_irq_disable(unsigned int irq)
 {
-	BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+	LOONGSON_INTENCLR = (1 << (irq - LOONGSON_IRQ_BASE));
 	mmiowb();
 }
 
@@ -35,7 +36,7 @@
 	.unmask	= bonito_irq_enable,
 };
 
-static struct irqaction dma_timeout_irqaction = {
+static struct irqaction __maybe_unused dma_timeout_irqaction = {
 	.handler	= no_action,
 	.name		= "dma_timeout",
 };
@@ -44,8 +45,10 @@
 {
 	u32 i;
 
-	for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++)
+	for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
 		set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
 
-	setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+#ifdef CONFIG_CPU_LOONGSON2E
+	setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction);
+#endif
 }
diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c
index 75f1b24..7ad47f2 100644
--- a/arch/mips/loongson/common/cmdline.c
+++ b/arch/mips/loongson/common/cmdline.c
@@ -9,7 +9,7 @@
  * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
  * Author: Fuxin Zhang, zhangfx@lemote.com
  *
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Wu Zhangjin, wuzj@lemote.com
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -49,4 +49,6 @@
 		strcat(arcs_cmdline, " console=ttyS0,115200");
 	if ((strstr(arcs_cmdline, "root=")) == NULL)
 		strcat(arcs_cmdline, " root=/dev/hda1");
+
+	prom_init_machtype();
 }
diff --git a/arch/mips/loongson/common/cs5536/Makefile b/arch/mips/loongson/common/cs5536/Makefile
new file mode 100644
index 0000000..510d4cd
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for CS5536 support.
+#
+
+obj-$(CONFIG_CS5536) += cs5536_pci.o cs5536_ide.o cs5536_acc.o cs5536_ohci.o \
+			cs5536_isa.o cs5536_ehci.o
+
+#
+# Enable cs5536 mfgpt Timer
+#
+obj-$(CONFIG_CS5536_MFGPT) += cs5536_mfgpt.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/loongson/common/cs5536/cs5536_acc.c b/arch/mips/loongson/common/cs5536/cs5536_acc.c
new file mode 100644
index 0000000..b49485f
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_acc.c
@@ -0,0 +1,140 @@
+/*
+ * the ACC Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_acc_write_reg(int reg, u32 value)
+{
+	u32 hi = 0, lo = value;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		_rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+		if (value & PCI_COMMAND_MASTER)
+			lo |= (0x03 << 8);
+		else
+			lo &= ~(0x03 << 8);
+		_wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+		break;
+	case PCI_STATUS:
+		if (value & PCI_STATUS_PARITY) {
+			_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+			if (lo & SB_PARE_ERR_FLAG) {
+				lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+				_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+			}
+		}
+		break;
+	case PCI_BAR0_REG:
+		if (value == PCI_BAR_RANGE_MASK) {
+			_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+			lo |= SOFT_BAR_ACC_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else if (value & 0x01) {
+			value &= 0xfffffffc;
+			hi = 0xA0000000 | ((value & 0x000ff000) >> 12);
+			lo = 0x000fff80 | ((value & 0x00000fff) << 20);
+			_wrmsr(GLIU_MSR_REG(GLIU_IOD_BM1), hi, lo);
+		}
+		break;
+	case PCI_ACC_INT_REG:
+		_rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+		/* disable all the usb interrupt in PIC */
+		lo &= ~(0xf << PIC_YSEL_LOW_ACC_SHIFT);
+		if (value)	/* enable all the acc interrupt in PIC */
+			lo |= (CS5536_ACC_INTR << PIC_YSEL_LOW_ACC_SHIFT);
+		_wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+		break;
+	default:
+		break;
+	}
+}
+
+u32 pci_acc_read_reg(int reg)
+{
+	u32 hi, lo;
+	u32 conf_data = 0;
+
+	switch (reg) {
+	case PCI_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_ACC_DEVICE_ID, CS5536_VENDOR_ID);
+		break;
+	case PCI_COMMAND:
+		_rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+		if (((lo & 0xfff00000) || (hi & 0x000000ff))
+		    && ((hi & 0xf0000000) == 0xa0000000))
+			conf_data |= PCI_COMMAND_IO;
+		_rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+		if ((lo & 0x300) == 0x300)
+			conf_data |= PCI_COMMAND_MASTER;
+		break;
+	case PCI_STATUS:
+		conf_data |= PCI_STATUS_66MHZ;
+		conf_data |= PCI_STATUS_FAST_BACK;
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		if (lo & SB_PARE_ERR_FLAG)
+			conf_data |= PCI_STATUS_PARITY;
+		conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+		break;
+	case PCI_CLASS_REVISION:
+		_rdmsr(ACC_MSR_REG(ACC_CAP), &hi, &lo);
+		conf_data = lo & 0x000000ff;
+		conf_data |= (CS5536_ACC_CLASS_CODE << 8);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		conf_data =
+		    CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+					    PCI_NORMAL_LATENCY_TIMER);
+		break;
+	case PCI_BAR0_REG:
+		_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+		if (lo & SOFT_BAR_ACC_FLAG) {
+			conf_data = CS5536_ACC_RANGE |
+			    PCI_BASE_ADDRESS_SPACE_IO;
+			lo &= ~SOFT_BAR_ACC_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else {
+			_rdmsr(GLIU_MSR_REG(GLIU_IOD_BM1), &hi, &lo);
+			conf_data = (hi & 0x000000ff) << 12;
+			conf_data |= (lo & 0xfff00000) >> 20;
+			conf_data |= 0x01;
+			conf_data &= ~0x02;
+		}
+		break;
+	case PCI_CARDBUS_CIS:
+		conf_data = PCI_CARDBUS_CIS_POINTER;
+		break;
+	case PCI_SUBSYSTEM_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_ACC_SUB_ID, CS5536_SUB_VENDOR_ID);
+		break;
+	case PCI_ROM_ADDRESS:
+		conf_data = PCI_EXPANSION_ROM_BAR;
+		break;
+	case PCI_CAPABILITY_LIST:
+		conf_data = PCI_CAPLIST_USB_POINTER;
+		break;
+	case PCI_INTERRUPT_LINE:
+		conf_data =
+		    CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_ACC_INTR);
+		break;
+	default:
+		break;
+	}
+
+	return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ehci.c b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
new file mode 100644
index 0000000..74f9c59
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ehci.c
@@ -0,0 +1,158 @@
+/*
+ * the EHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ehci_write_reg(int reg, u32 value)
+{
+	u32 hi = 0, lo = value;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		if (value & PCI_COMMAND_MASTER)
+			hi |= PCI_COMMAND_MASTER;
+		else
+			hi &= ~PCI_COMMAND_MASTER;
+
+		if (value & PCI_COMMAND_MEMORY)
+			hi |= PCI_COMMAND_MEMORY;
+		else
+			hi &= ~PCI_COMMAND_MEMORY;
+		_wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+		break;
+	case PCI_STATUS:
+		if (value & PCI_STATUS_PARITY) {
+			_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+			if (lo & SB_PARE_ERR_FLAG) {
+				lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+				_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+			}
+		}
+		break;
+	case PCI_BAR0_REG:
+		if (value == PCI_BAR_RANGE_MASK) {
+			_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+			lo |= SOFT_BAR_EHCI_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else if ((value & 0x01) == 0x00) {
+			_wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+
+			value &= 0xfffffff0;
+			hi = 0x40000000 | ((value & 0xff000000) >> 24);
+			lo = 0x000fffff | ((value & 0x00fff000) << 8);
+			_wrmsr(GLIU_MSR_REG(GLIU_P2D_BM4), hi, lo);
+		}
+		break;
+	case PCI_EHCI_LEGSMIEN_REG:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		hi &= 0x003f0000;
+		hi |= (value & 0x3f) << 16;
+		_wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+		break;
+	case PCI_EHCI_FLADJ_REG:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		hi &= ~0x00003f00;
+		hi |= value & 0x00003f00;
+		_wrmsr(USB_MSR_REG(USB_EHCI), hi, lo);
+		break;
+	default:
+		break;
+	}
+}
+
+u32 pci_ehci_read_reg(int reg)
+{
+	u32 conf_data = 0;
+	u32 hi, lo;
+
+	switch (reg) {
+	case PCI_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_EHCI_DEVICE_ID, CS5536_VENDOR_ID);
+		break;
+	case PCI_COMMAND:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		if (hi & PCI_COMMAND_MASTER)
+			conf_data |= PCI_COMMAND_MASTER;
+		if (hi & PCI_COMMAND_MEMORY)
+			conf_data |= PCI_COMMAND_MEMORY;
+		break;
+	case PCI_STATUS:
+		conf_data |= PCI_STATUS_66MHZ;
+		conf_data |= PCI_STATUS_FAST_BACK;
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		if (lo & SB_PARE_ERR_FLAG)
+			conf_data |= PCI_STATUS_PARITY;
+		conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+		break;
+	case PCI_CLASS_REVISION:
+		_rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+		conf_data = lo & 0x000000ff;
+		conf_data |= (CS5536_EHCI_CLASS_CODE << 8);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		conf_data =
+		    CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+					    PCI_NORMAL_LATENCY_TIMER);
+		break;
+	case PCI_BAR0_REG:
+		_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+		if (lo & SOFT_BAR_EHCI_FLAG) {
+			conf_data = CS5536_EHCI_RANGE |
+			    PCI_BASE_ADDRESS_SPACE_MEMORY;
+			lo &= ~SOFT_BAR_EHCI_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else {
+			_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+			conf_data = lo & 0xfffff000;
+		}
+		break;
+	case PCI_CARDBUS_CIS:
+		conf_data = PCI_CARDBUS_CIS_POINTER;
+		break;
+	case PCI_SUBSYSTEM_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_EHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+		break;
+	case PCI_ROM_ADDRESS:
+		conf_data = PCI_EXPANSION_ROM_BAR;
+		break;
+	case PCI_CAPABILITY_LIST:
+		conf_data = PCI_CAPLIST_USB_POINTER;
+		break;
+	case PCI_INTERRUPT_LINE:
+		conf_data =
+		    CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+		break;
+	case PCI_EHCI_LEGSMIEN_REG:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		conf_data = (hi & 0x003f0000) >> 16;
+		break;
+	case PCI_EHCI_LEGSMISTS_REG:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		conf_data = (hi & 0x3f000000) >> 24;
+		break;
+	case PCI_EHCI_FLADJ_REG:
+		_rdmsr(USB_MSR_REG(USB_EHCI), &hi, &lo);
+		conf_data = hi & 0x00003f00;
+		break;
+	default:
+		break;
+	}
+
+	return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ide.c b/arch/mips/loongson/common/cs5536/cs5536_ide.c
new file mode 100644
index 0000000..3f61594
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ide.c
@@ -0,0 +1,179 @@
+/*
+ * the IDE Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ide_write_reg(int reg, u32 value)
+{
+	u32 hi = 0, lo = value;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		_rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+		if (value & PCI_COMMAND_MASTER)
+			lo |= (0x03 << 4);
+		else
+			lo &= ~(0x03 << 4);
+		_wrmsr(GLIU_MSR_REG(GLIU_PAE), hi, lo);
+		break;
+	case PCI_STATUS:
+		if (value & PCI_STATUS_PARITY) {
+			_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+			if (lo & SB_PARE_ERR_FLAG) {
+				lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+				_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+			}
+		}
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		value &= 0x0000ff00;
+		_rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+		hi &= 0xffffff00;
+		hi |= (value >> 8);
+		_wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+		break;
+	case PCI_BAR4_REG:
+		if (value == PCI_BAR_RANGE_MASK) {
+			_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+			lo |= SOFT_BAR_IDE_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else if (value & 0x01) {
+			lo = (value & 0xfffffff0) | 0x1;
+			_wrmsr(IDE_MSR_REG(IDE_IO_BAR), hi, lo);
+
+			value &= 0xfffffffc;
+			hi = 0x60000000 | ((value & 0x000ff000) >> 12);
+			lo = 0x000ffff0 | ((value & 0x00000fff) << 20);
+			_wrmsr(GLIU_MSR_REG(GLIU_IOD_BM2), hi, lo);
+		}
+		break;
+	case PCI_IDE_CFG_REG:
+		if (value == CS5536_IDE_FLASH_SIGNATURE) {
+			_rdmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), &hi, &lo);
+			lo |= 0x01;
+			_wrmsr(DIVIL_MSR_REG(DIVIL_BALL_OPTS), hi, lo);
+		} else
+			_wrmsr(IDE_MSR_REG(IDE_CFG), hi, lo);
+		break;
+	case PCI_IDE_DTC_REG:
+		_wrmsr(IDE_MSR_REG(IDE_DTC), hi, lo);
+		break;
+	case PCI_IDE_CAST_REG:
+		_wrmsr(IDE_MSR_REG(IDE_CAST), hi, lo);
+		break;
+	case PCI_IDE_ETC_REG:
+		_wrmsr(IDE_MSR_REG(IDE_ETC), hi, lo);
+		break;
+	case PCI_IDE_PM_REG:
+		_wrmsr(IDE_MSR_REG(IDE_INTERNAL_PM), hi, lo);
+		break;
+	default:
+		break;
+	}
+}
+
+u32 pci_ide_read_reg(int reg)
+{
+	u32 conf_data = 0;
+	u32 hi, lo;
+
+	switch (reg) {
+	case PCI_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_IDE_DEVICE_ID, CS5536_VENDOR_ID);
+		break;
+	case PCI_COMMAND:
+		_rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+		if (lo & 0xfffffff0)
+			conf_data |= PCI_COMMAND_IO;
+		_rdmsr(GLIU_MSR_REG(GLIU_PAE), &hi, &lo);
+		if ((lo & 0x30) == 0x30)
+			conf_data |= PCI_COMMAND_MASTER;
+		break;
+	case PCI_STATUS:
+		conf_data |= PCI_STATUS_66MHZ;
+		conf_data |= PCI_STATUS_FAST_BACK;
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		if (lo & SB_PARE_ERR_FLAG)
+			conf_data |= PCI_STATUS_PARITY;
+		conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+		break;
+	case PCI_CLASS_REVISION:
+		_rdmsr(IDE_MSR_REG(IDE_CAP), &hi, &lo);
+		conf_data = lo & 0x000000ff;
+		conf_data |= (CS5536_IDE_CLASS_CODE << 8);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		_rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+		hi &= 0x000000f8;
+		conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE, hi);
+		break;
+	case PCI_BAR4_REG:
+		_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+		if (lo & SOFT_BAR_IDE_FLAG) {
+			conf_data = CS5536_IDE_RANGE |
+			    PCI_BASE_ADDRESS_SPACE_IO;
+			lo &= ~SOFT_BAR_IDE_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else {
+			_rdmsr(IDE_MSR_REG(IDE_IO_BAR), &hi, &lo);
+			conf_data = lo & 0xfffffff0;
+			conf_data |= 0x01;
+			conf_data &= ~0x02;
+		}
+		break;
+	case PCI_CARDBUS_CIS:
+		conf_data = PCI_CARDBUS_CIS_POINTER;
+		break;
+	case PCI_SUBSYSTEM_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_IDE_SUB_ID, CS5536_SUB_VENDOR_ID);
+		break;
+	case PCI_ROM_ADDRESS:
+		conf_data = PCI_EXPANSION_ROM_BAR;
+		break;
+	case PCI_CAPABILITY_LIST:
+		conf_data = PCI_CAPLIST_POINTER;
+		break;
+	case PCI_INTERRUPT_LINE:
+		conf_data =
+		    CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_IDE_INTR);
+		break;
+	case PCI_IDE_CFG_REG:
+		_rdmsr(IDE_MSR_REG(IDE_CFG), &hi, &lo);
+		conf_data = lo;
+		break;
+	case PCI_IDE_DTC_REG:
+		_rdmsr(IDE_MSR_REG(IDE_DTC), &hi, &lo);
+		conf_data = lo;
+		break;
+	case PCI_IDE_CAST_REG:
+		_rdmsr(IDE_MSR_REG(IDE_CAST), &hi, &lo);
+		conf_data = lo;
+		break;
+	case PCI_IDE_ETC_REG:
+		_rdmsr(IDE_MSR_REG(IDE_ETC), &hi, &lo);
+		conf_data = lo;
+	case PCI_IDE_PM_REG:
+		_rdmsr(IDE_MSR_REG(IDE_INTERNAL_PM), &hi, &lo);
+		conf_data = lo;
+		break;
+	default:
+		break;
+	}
+
+	return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_isa.c b/arch/mips/loongson/common/cs5536/cs5536_isa.c
new file mode 100644
index 0000000..b6f17f5
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_isa.c
@@ -0,0 +1,316 @@
+/*
+ * the ISA Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* common variables for PCI_ISA_READ/WRITE_BAR */
+static const u32 divil_msr_reg[6] = {
+	DIVIL_MSR_REG(DIVIL_LBAR_SMB), DIVIL_MSR_REG(DIVIL_LBAR_GPIO),
+	DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), DIVIL_MSR_REG(DIVIL_LBAR_IRQ),
+	DIVIL_MSR_REG(DIVIL_LBAR_PMS), DIVIL_MSR_REG(DIVIL_LBAR_ACPI),
+};
+
+static const u32 soft_bar_flag[6] = {
+	SOFT_BAR_SMB_FLAG, SOFT_BAR_GPIO_FLAG, SOFT_BAR_MFGPT_FLAG,
+	SOFT_BAR_IRQ_FLAG, SOFT_BAR_PMS_FLAG, SOFT_BAR_ACPI_FLAG,
+};
+
+static const u32 sb_msr_reg[6] = {
+	SB_MSR_REG(SB_R0), SB_MSR_REG(SB_R1), SB_MSR_REG(SB_R2),
+	SB_MSR_REG(SB_R3), SB_MSR_REG(SB_R4), SB_MSR_REG(SB_R5),
+};
+
+static const u32 bar_space_range[6] = {
+	CS5536_SMB_RANGE, CS5536_GPIO_RANGE, CS5536_MFGPT_RANGE,
+	CS5536_IRQ_RANGE, CS5536_PMS_RANGE, CS5536_ACPI_RANGE,
+};
+
+static const int bar_space_len[6] = {
+	CS5536_SMB_LENGTH, CS5536_GPIO_LENGTH, CS5536_MFGPT_LENGTH,
+	CS5536_IRQ_LENGTH, CS5536_PMS_LENGTH, CS5536_ACPI_LENGTH,
+};
+
+/*
+ * enable the divil module bar space.
+ *
+ * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg
+ * and the RCONFx(0~5) reg to use the modules.
+ */
+static void divil_lbar_enable(void)
+{
+	u32 hi, lo;
+	int offset;
+
+	/*
+	 * The DIVIL IRQ is not used yet. and make the RCONF0 reserved.
+	 */
+
+	for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+		_rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+		hi |= 0x01;
+		_wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+	}
+}
+
+/*
+ * disable the divil module bar space.
+ */
+static void divil_lbar_disable(void)
+{
+	u32 hi, lo;
+	int offset;
+
+	for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) {
+		_rdmsr(DIVIL_MSR_REG(offset), &hi, &lo);
+		hi &= ~0x01;
+		_wrmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), hi, lo);
+	}
+}
+
+/*
+ * BAR write: write value to the n BAR
+ */
+
+void pci_isa_write_bar(int n, u32 value)
+{
+	u32 hi = 0, lo = value;
+
+	if (value == PCI_BAR_RANGE_MASK) {
+		_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+		lo |= soft_bar_flag[n];
+		_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+	} else if (value & 0x01) {
+		/* NATIVE reg */
+		hi = 0x0000f001;
+		lo &= bar_space_range[n];
+		_wrmsr(divil_msr_reg[n], hi, lo);
+
+		/* RCONFx is 4bytes in units for I/O space */
+		hi = ((value & 0x000ffffc) << 12) |
+		    ((bar_space_len[n] - 4) << 12) | 0x01;
+		lo = ((value & 0x000ffffc) << 12) | 0x01;
+		_wrmsr(sb_msr_reg[n], hi, lo);
+	}
+}
+
+/*
+ * BAR read: read the n BAR
+ */
+
+u32 pci_isa_read_bar(int n)
+{
+	u32 conf_data = 0;
+	u32 hi, lo;
+
+	_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+	if (lo & soft_bar_flag[n]) {
+		conf_data = bar_space_range[n] | PCI_BASE_ADDRESS_SPACE_IO;
+		lo &= ~soft_bar_flag[n];
+		_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+	} else {
+		_rdmsr(divil_msr_reg[n], &hi, &lo);
+		conf_data = lo & bar_space_range[n];
+		conf_data |= 0x01;
+		conf_data &= ~0x02;
+	}
+	return conf_data;
+}
+
+/*
+ * isa_write: ISA write transfer
+ *
+ * We assume that this is not a bus master transfer.
+ */
+void pci_isa_write_reg(int reg, u32 value)
+{
+	u32 hi = 0, lo = value;
+	u32 temp;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		if (value & PCI_COMMAND_IO)
+			divil_lbar_enable();
+		else
+			divil_lbar_disable();
+		break;
+	case PCI_STATUS:
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		temp = lo & 0x0000ffff;
+		if ((value & PCI_STATUS_SIG_TARGET_ABORT) &&
+		    (lo & SB_TAS_ERR_EN))
+			temp |= SB_TAS_ERR_FLAG;
+
+		if ((value & PCI_STATUS_REC_TARGET_ABORT) &&
+		    (lo & SB_TAR_ERR_EN))
+			temp |= SB_TAR_ERR_FLAG;
+
+		if ((value & PCI_STATUS_REC_MASTER_ABORT)
+		    && (lo & SB_MAR_ERR_EN))
+			temp |= SB_MAR_ERR_FLAG;
+
+		if ((value & PCI_STATUS_DETECTED_PARITY)
+		    && (lo & SB_PARE_ERR_EN))
+			temp |= SB_PARE_ERR_FLAG;
+
+		lo = temp;
+		_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		value &= 0x0000ff00;
+		_rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+		hi &= 0xffffff00;
+		hi |= (value >> 8);
+		_wrmsr(SB_MSR_REG(SB_CTRL), hi, lo);
+		break;
+	case PCI_BAR0_REG:
+		pci_isa_write_bar(0, value);
+		break;
+	case PCI_BAR1_REG:
+		pci_isa_write_bar(1, value);
+		break;
+	case PCI_BAR2_REG:
+		pci_isa_write_bar(2, value);
+		break;
+	case PCI_BAR3_REG:
+		pci_isa_write_bar(3, value);
+		break;
+	case PCI_BAR4_REG:
+		pci_isa_write_bar(4, value);
+		break;
+	case PCI_BAR5_REG:
+		pci_isa_write_bar(5, value);
+		break;
+	case PCI_UART1_INT_REG:
+		_rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+		/* disable uart1 interrupt in PIC */
+		lo &= ~(0xf << 24);
+		if (value)	/* enable uart1 interrupt in PIC */
+			lo |= (CS5536_UART1_INTR << 24);
+		_wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+		break;
+	case PCI_UART2_INT_REG:
+		_rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo);
+		/* disable uart2 interrupt in PIC */
+		lo &= ~(0xf << 28);
+		if (value)	/* enable uart2 interrupt in PIC */
+			lo |= (CS5536_UART2_INTR << 28);
+		_wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo);
+		break;
+	case PCI_ISA_FIXUP_REG:
+		if (value) {
+			/* enable the TARGET ABORT/MASTER ABORT etc. */
+			_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+			lo |= 0x00000063;
+			_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+		}
+
+	default:
+		/* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */
+		break;
+	}
+}
+
+/*
+ * isa_read: ISA read transfers
+ *
+ * We assume that this is not a bus master transfer.
+ */
+u32 pci_isa_read_reg(int reg)
+{
+	u32 conf_data = 0;
+	u32 hi, lo;
+
+	switch (reg) {
+	case PCI_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID, CS5536_VENDOR_ID);
+		break;
+	case PCI_COMMAND:
+		/* we just check the first LBAR for the IO enable bit, */
+		/* maybe we should changed later. */
+		_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo);
+		if (hi & 0x01)
+			conf_data |= PCI_COMMAND_IO;
+		break;
+	case PCI_STATUS:
+		conf_data |= PCI_STATUS_66MHZ;
+		conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+		conf_data |= PCI_STATUS_FAST_BACK;
+
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		if (lo & SB_TAS_ERR_FLAG)
+			conf_data |= PCI_STATUS_SIG_TARGET_ABORT;
+		if (lo & SB_TAR_ERR_FLAG)
+			conf_data |= PCI_STATUS_REC_TARGET_ABORT;
+		if (lo & SB_MAR_ERR_FLAG)
+			conf_data |= PCI_STATUS_REC_MASTER_ABORT;
+		if (lo & SB_PARE_ERR_FLAG)
+			conf_data |= PCI_STATUS_DETECTED_PARITY;
+		break;
+	case PCI_CLASS_REVISION:
+		_rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo);
+		conf_data = lo & 0x000000ff;
+		conf_data |= (CS5536_ISA_CLASS_CODE << 8);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		_rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo);
+		hi &= 0x000000f8;
+		conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE, hi);
+		break;
+		/*
+		 * we only use the LBAR of DIVIL, no RCONF used.
+		 * all of them are IO space.
+		 */
+	case PCI_BAR0_REG:
+		return pci_isa_read_bar(0);
+		break;
+	case PCI_BAR1_REG:
+		return pci_isa_read_bar(1);
+		break;
+	case PCI_BAR2_REG:
+		return pci_isa_read_bar(2);
+		break;
+	case PCI_BAR3_REG:
+		break;
+	case PCI_BAR4_REG:
+		return pci_isa_read_bar(4);
+		break;
+	case PCI_BAR5_REG:
+		return pci_isa_read_bar(5);
+		break;
+	case PCI_CARDBUS_CIS:
+		conf_data = PCI_CARDBUS_CIS_POINTER;
+		break;
+	case PCI_SUBSYSTEM_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID, CS5536_SUB_VENDOR_ID);
+		break;
+	case PCI_ROM_ADDRESS:
+		conf_data = PCI_EXPANSION_ROM_BAR;
+		break;
+	case PCI_CAPABILITY_LIST:
+		conf_data = PCI_CAPLIST_POINTER;
+		break;
+	case PCI_INTERRUPT_LINE:
+		/* no interrupt used here */
+		conf_data = CFG_PCI_INTERRUPT_LINE(0x00, 0x00);
+		break;
+	default:
+		break;
+	}
+
+	return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
new file mode 100644
index 0000000..6cb44db
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_mfgpt.c
@@ -0,0 +1,217 @@
+/*
+ * CS5536 General timer functions
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Yanhua, yanh@lemote.com
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu zhangjin, wuzj@lemote.com
+ *
+ * Reference: AMD Geode(TM) CS5536 Companion Device Data Book
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the 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/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+
+#include <asm/time.h>
+
+#include <cs5536/cs5536_mfgpt.h>
+
+DEFINE_SPINLOCK(mfgpt_lock);
+EXPORT_SYMBOL(mfgpt_lock);
+
+static u32 mfgpt_base;
+
+/*
+ * Initialize the MFGPT timer.
+ *
+ * This is also called after resume to bring the MFGPT into operation again.
+ */
+
+/* disable counter */
+void disable_mfgpt0_counter(void)
+{
+	outw(inw(MFGPT0_SETUP) & 0x7fff, MFGPT0_SETUP);
+}
+EXPORT_SYMBOL(disable_mfgpt0_counter);
+
+/* enable counter, comparator2 to event mode, 14.318MHz clock */
+void enable_mfgpt0_counter(void)
+{
+	outw(0xe310, MFGPT0_SETUP);
+}
+EXPORT_SYMBOL(enable_mfgpt0_counter);
+
+static void init_mfgpt_timer(enum clock_event_mode mode,
+			     struct clock_event_device *evt)
+{
+	spin_lock(&mfgpt_lock);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		outw(COMPARE, MFGPT0_CMP2);	/* set comparator2 */
+		outw(0, MFGPT0_CNT);	/* set counter to 0 */
+		enable_mfgpt0_counter();
+		break;
+
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		if (evt->mode == CLOCK_EVT_MODE_PERIODIC ||
+		    evt->mode == CLOCK_EVT_MODE_ONESHOT)
+			disable_mfgpt0_counter();
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* The oneshot mode have very high deviation, Not use it! */
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
+		break;
+	}
+	spin_unlock(&mfgpt_lock);
+}
+
+static struct clock_event_device mfgpt_clockevent = {
+	.name = "mfgpt",
+	.features = CLOCK_EVT_FEAT_PERIODIC,
+	.set_mode = init_mfgpt_timer,
+	.irq = CS5536_MFGPT_INTR,
+};
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	u32 basehi;
+
+	/*
+	 * get MFGPT base address
+	 *
+	 * NOTE: do not remove me, it's need for the value of mfgpt_base is
+	 * variable
+	 */
+	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base);
+
+	/* ack */
+	outw(inw(MFGPT0_SETUP) | 0x4000, MFGPT0_SETUP);
+
+	mfgpt_clockevent.event_handler(&mfgpt_clockevent);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq5 = {
+	.handler = timer_interrupt,
+	.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
+	.name = "timer"
+};
+
+/*
+ * Initialize the conversion factor and the min/max deltas of the clock event
+ * structure and register the clock event source with the framework.
+ */
+void __init setup_mfgpt0_timer(void)
+{
+	u32 basehi;
+	struct clock_event_device *cd = &mfgpt_clockevent;
+	unsigned int cpu = smp_processor_id();
+
+	cd->cpumask = cpumask_of(cpu);
+	clockevent_set_clock(cd, MFGPT_TICK_RATE);
+	cd->max_delta_ns = clockevent_delta2ns(0xffff, cd);
+	cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
+
+	/* Enable MFGPT0 Comparator 2 Output to the Interrupt Mapper */
+	_wrmsr(DIVIL_MSR_REG(MFGPT_IRQ), 0, 0x100);
+
+	/* Enable Interrupt Gate 5 */
+	_wrmsr(DIVIL_MSR_REG(PIC_ZSEL_LOW), 0, 0x50000);
+
+	/* get MFGPT base address */
+	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &basehi, &mfgpt_base);
+
+	clockevents_register_device(cd);
+
+	setup_irq(CS5536_MFGPT_INTR, &irq5);
+}
+
+/*
+ * Since the MFGPT overflows every tick, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static cycle_t mfgpt_read(struct clocksource *cs)
+{
+	unsigned long flags;
+	int count;
+	u32 jifs;
+	static int old_count;
+	static u32 old_jifs;
+
+	spin_lock_irqsave(&mfgpt_lock, flags);
+	/*
+	 * Although our caller may have the read side of xtime_lock,
+	 * this is now a seqlock, and we are cheating in this routine
+	 * by having side effects on state that we cannot undo if
+	 * there is a collision on the seqlock and our caller has to
+	 * retry.  (Namely, old_jifs and old_count.)  So we must treat
+	 * jiffies as volatile despite the lock.  We read jiffies
+	 * before latching the timer count to guarantee that although
+	 * the jiffies value might be older than the count (that is,
+	 * the counter may underflow between the last point where
+	 * jiffies was incremented and the point where we latch the
+	 * count), it cannot be newer.
+	 */
+	jifs = jiffies;
+	/* read the count */
+	count = inw(MFGPT0_CNT);
+
+	/*
+	 * It's possible for count to appear to go the wrong way for this
+	 * reason:
+	 *
+	 *  The timer counter underflows, but we haven't handled the resulting
+	 *  interrupt and incremented jiffies yet.
+	 *
+	 * Previous attempts to handle these cases intelligently were buggy, so
+	 * we just do the simple thing now.
+	 */
+	if (count < old_count && jifs == old_jifs)
+		count = old_count;
+
+	old_count = count;
+	old_jifs = jifs;
+
+	spin_unlock_irqrestore(&mfgpt_lock, flags);
+
+	return (cycle_t) (jifs * COMPARE) + count;
+}
+
+static struct clocksource clocksource_mfgpt = {
+	.name = "mfgpt",
+	.rating = 120, /* Functional for real use, but not desired */
+	.read = mfgpt_read,
+	.mask = CLOCKSOURCE_MASK(32),
+	.mult = 0,
+	.shift = 22,
+};
+
+int __init init_mfgpt_clocksource(void)
+{
+	if (num_possible_cpus() > 1)	/* MFGPT does not scale! */
+		return 0;
+
+	clocksource_mfgpt.mult = clocksource_hz2mult(MFGPT_TICK_RATE, 22);
+	return clocksource_register(&clocksource_mfgpt);
+}
+
+arch_initcall(init_mfgpt_clocksource);
diff --git a/arch/mips/loongson/common/cs5536/cs5536_ohci.c b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
new file mode 100644
index 0000000..8fdb02b
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_ohci.c
@@ -0,0 +1,147 @@
+/*
+ * the OHCI Virtual Support Module of AMD CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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 <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+void pci_ohci_write_reg(int reg, u32 value)
+{
+	u32 hi = 0, lo = value;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		_rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+		if (value & PCI_COMMAND_MASTER)
+			hi |= PCI_COMMAND_MASTER;
+		else
+			hi &= ~PCI_COMMAND_MASTER;
+
+		if (value & PCI_COMMAND_MEMORY)
+			hi |= PCI_COMMAND_MEMORY;
+		else
+			hi &= ~PCI_COMMAND_MEMORY;
+		_wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+		break;
+	case PCI_STATUS:
+		if (value & PCI_STATUS_PARITY) {
+			_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+			if (lo & SB_PARE_ERR_FLAG) {
+				lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
+				_wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
+			}
+		}
+		break;
+	case PCI_BAR0_REG:
+		if (value == PCI_BAR_RANGE_MASK) {
+			_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+			lo |= SOFT_BAR_OHCI_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else if ((value & 0x01) == 0x00) {
+			_wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
+
+			value &= 0xfffffff0;
+			hi = 0x40000000 | ((value & 0xff000000) >> 24);
+			lo = 0x000fffff | ((value & 0x00fff000) << 8);
+			_wrmsr(GLIU_MSR_REG(GLIU_P2D_BM3), hi, lo);
+		}
+		break;
+	case PCI_OHCI_INT_REG:
+		_rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+		lo &= ~(0xf << PIC_YSEL_LOW_USB_SHIFT);
+		if (value)	/* enable all the usb interrupt in PIC */
+			lo |= (CS5536_USB_INTR << PIC_YSEL_LOW_USB_SHIFT);
+		_wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
+		break;
+	default:
+		break;
+	}
+}
+
+u32 pci_ohci_read_reg(int reg)
+{
+	u32 conf_data = 0;
+	u32 hi, lo;
+
+	switch (reg) {
+	case PCI_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID);
+		break;
+	case PCI_COMMAND:
+		_rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+		if (hi & PCI_COMMAND_MASTER)
+			conf_data |= PCI_COMMAND_MASTER;
+		if (hi & PCI_COMMAND_MEMORY)
+			conf_data |= PCI_COMMAND_MEMORY;
+		break;
+	case PCI_STATUS:
+		conf_data |= PCI_STATUS_66MHZ;
+		conf_data |= PCI_STATUS_FAST_BACK;
+		_rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
+		if (lo & SB_PARE_ERR_FLAG)
+			conf_data |= PCI_STATUS_PARITY;
+		conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
+		break;
+	case PCI_CLASS_REVISION:
+		_rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
+		conf_data = lo & 0x000000ff;
+		conf_data |= (CS5536_OHCI_CLASS_CODE << 8);
+		break;
+	case PCI_CACHE_LINE_SIZE:
+		conf_data =
+		    CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
+					    PCI_NORMAL_LATENCY_TIMER);
+		break;
+	case PCI_BAR0_REG:
+		_rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
+		if (lo & SOFT_BAR_OHCI_FLAG) {
+			conf_data = CS5536_OHCI_RANGE |
+			    PCI_BASE_ADDRESS_SPACE_MEMORY;
+			lo &= ~SOFT_BAR_OHCI_FLAG;
+			_wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
+		} else {
+			_rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
+			conf_data = lo & 0xffffff00;
+			conf_data &= ~0x0000000f;	/* 32bit mem */
+		}
+		break;
+	case PCI_CARDBUS_CIS:
+		conf_data = PCI_CARDBUS_CIS_POINTER;
+		break;
+	case PCI_SUBSYSTEM_VENDOR_ID:
+		conf_data =
+		    CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
+		break;
+	case PCI_ROM_ADDRESS:
+		conf_data = PCI_EXPANSION_ROM_BAR;
+		break;
+	case PCI_CAPABILITY_LIST:
+		conf_data = PCI_CAPLIST_USB_POINTER;
+		break;
+	case PCI_INTERRUPT_LINE:
+		conf_data =
+		    CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
+		break;
+	case PCI_OHCI_INT_REG:
+		_rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
+		if ((lo & 0x00000f00) == CS5536_USB_INTR)
+			conf_data = 1;
+		break;
+	default:
+		break;
+	}
+
+	return conf_data;
+}
diff --git a/arch/mips/loongson/common/cs5536/cs5536_pci.c b/arch/mips/loongson/common/cs5536/cs5536_pci.c
new file mode 100644
index 0000000..e23f3d7
--- /dev/null
+++ b/arch/mips/loongson/common/cs5536/cs5536_pci.c
@@ -0,0 +1,87 @@
+/*
+ * read/write operation to the PCI config space of CS5536
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author : jlliu, liujl@lemote.com
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.com
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ *	the Virtual Support Module(VSM) for virtulizing the PCI
+ *	configure space are defined in cs5536_modulename.c respectively,
+ *
+ *	after this virtulizing, user can access the PCI configure space
+ *	directly as a normal multi-function PCI device which follows
+ *	the PCI-2.2 spec.
+ */
+
+#include <linux/types.h>
+#include <cs5536/cs5536_vsm.h>
+
+enum {
+	CS5536_FUNC_START = -1,
+	CS5536_ISA_FUNC,
+	reserved_func,
+	CS5536_IDE_FUNC,
+	CS5536_ACC_FUNC,
+	CS5536_OHCI_FUNC,
+	CS5536_EHCI_FUNC,
+	CS5536_FUNC_END,
+};
+
+static const cs5536_pci_vsm_write vsm_conf_write[] = {
+	[CS5536_ISA_FUNC]	pci_isa_write_reg,
+	[reserved_func]		NULL,
+	[CS5536_IDE_FUNC]	pci_ide_write_reg,
+	[CS5536_ACC_FUNC]	pci_acc_write_reg,
+	[CS5536_OHCI_FUNC]	pci_ohci_write_reg,
+	[CS5536_EHCI_FUNC]	pci_ehci_write_reg,
+};
+
+static const cs5536_pci_vsm_read vsm_conf_read[] = {
+	[CS5536_ISA_FUNC]	pci_isa_read_reg,
+	[reserved_func]		NULL,
+	[CS5536_IDE_FUNC]	pci_ide_read_reg,
+	[CS5536_ACC_FUNC]	pci_acc_read_reg,
+	[CS5536_OHCI_FUNC]	pci_ohci_read_reg,
+	[CS5536_EHCI_FUNC]	pci_ehci_read_reg,
+};
+
+/*
+ * write to PCI config space and transfer it to MSR write.
+ */
+void cs5536_pci_conf_write4(int function, int reg, u32 value)
+{
+	if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+		return;
+	if ((reg < 0) || (reg > 0x100) || ((reg & 0x03) != 0))
+		return;
+
+	if (vsm_conf_write[function] != NULL)
+		vsm_conf_write[function](reg, value);
+}
+
+/*
+ * read PCI config space and transfer it to MSR access.
+ */
+u32 cs5536_pci_conf_read4(int function, int reg)
+{
+	u32 data = 0;
+
+	if ((function <= CS5536_FUNC_START) || (function >= CS5536_FUNC_END))
+		return 0;
+	if ((reg < 0) || ((reg & 0x03) != 0))
+		return 0;
+	if (reg > 0x100)
+		return 0xffffffff;
+
+	if (vsm_conf_read[function] != NULL)
+		data = vsm_conf_read[function](reg);
+
+	return data;
+}
diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c
index bc73edc..23e7a8f 100644
--- a/arch/mips/loongson/common/early_printk.c
+++ b/arch/mips/loongson/common/early_printk.c
@@ -1,7 +1,7 @@
 /*  early printk support
  *
  *  Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
- *  Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ *  Copyright (c) 2009 Lemote Inc.
  *  Author: Wu Zhangjin, wuzj@lemote.com
  *
  *  This program is free software; you can redistribute  it and/or modify it
@@ -12,26 +12,29 @@
 #include <linux/serial_reg.h>
 
 #include <loongson.h>
-#include <machine.h>
 
 #define PORT(base, offset) (u8 *)(base + offset)
 
-static inline unsigned int serial_in(phys_addr_t base, int offset)
+static inline unsigned int serial_in(unsigned char *base, int offset)
 {
 	return readb(PORT(base, offset));
 }
 
-static inline void serial_out(phys_addr_t base, int offset, int value)
+static inline void serial_out(unsigned char *base, int offset, int value)
 {
 	writeb(value, PORT(base, offset));
 }
 
 void prom_putchar(char c)
 {
-	phys_addr_t uart_base =
-		(phys_addr_t) ioremap_nocache(LOONGSON_UART_BASE, 8);
+	int timeout;
+	unsigned char *uart_base;
 
-	while ((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0)
+	uart_base = (unsigned char *)_loongson_uart_base;
+	timeout = 1024;
+
+	while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) &&
+			(timeout-- > 0))
 		;
 
 	serial_out(uart_base, UART_TX, c);
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index b9ef503..196d947 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -17,11 +17,14 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
+#include <linux/module.h>
+
 #include <asm/bootinfo.h>
 
 #include <loongson.h>
 
 unsigned long bus_clock, cpu_clock_freq;
+EXPORT_SYMBOL(cpu_clock_freq);
 unsigned long memsize, highmemsize;
 
 /* pmon passes arguments in 32bit pointers */
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index 3abe927..a2abd93 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Wu Zhangjin, wuzj@lemote.com
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -10,19 +10,28 @@
 
 #include <linux/bootmem.h>
 
-#include <asm/bootinfo.h>
-
 #include <loongson.h>
 
+/* Loongson CPU address windows config space base address */
+unsigned long __maybe_unused _loongson_addrwincfg_base;
+
 void __init prom_init(void)
 {
-    /* init base address of io space */
+	/* init base address of io space */
 	set_io_port_base((unsigned long)
-		ioremap(BONITO_PCIIO_BASE, BONITO_PCIIO_SIZE));
+		ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
+
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+	_loongson_addrwincfg_base = (unsigned long)
+		ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
+#endif
 
 	prom_init_cmdline();
 	prom_init_env();
 	prom_init_memory();
+
+	/*init the uart base address */
+	prom_init_uart_base();
 }
 
 void __init prom_free_prom_memory(void)
diff --git a/arch/mips/loongson/common/irq.c b/arch/mips/loongson/common/irq.c
index b32b4a3..20e7328 100644
--- a/arch/mips/loongson/common/irq.c
+++ b/arch/mips/loongson/common/irq.c
@@ -20,21 +20,21 @@
 	int i;
 
 	/* workaround the IO dma problem: let cpu looping to allow DMA finish */
-	int_status = BONITO_INTISR;
+	int_status = LOONGSON_INTISR;
 	if (int_status & (1 << 10)) {
 		while (int_status & (1 << 10)) {
 			udelay(1);
-			int_status = BONITO_INTISR;
+			int_status = LOONGSON_INTISR;
 		}
 	}
 
 	/* Get pending sources, masked by current enables */
-	int_status = BONITO_INTISR & BONITO_INTEN;
+	int_status = LOONGSON_INTISR & LOONGSON_INTEN;
 
 	if (int_status != 0) {
 		i = __ffs(int_status);
 		int_status &= ~(1 << i);
-		do_IRQ(BONITO_IRQ_BASE + i);
+		do_IRQ(LOONGSON_IRQ_BASE + i);
 	}
 }
 
@@ -60,13 +60,13 @@
 	set_irq_trigger_mode();
 
 	/* no steer */
-	BONITO_INTSTEER = 0;
+	LOONGSON_INTSTEER = 0;
 
 	/*
 	 * Mask out all interrupt by writing "1" to all bit position in
 	 * the interrupt reset reg.
 	 */
-	BONITO_INTENCLR = ~0;
+	LOONGSON_INTENCLR = ~0;
 
 	/* machine specific irq init */
 	mach_init_irq();
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 7b34824..0ed52b3 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -15,6 +15,9 @@
 #include <loongson.h>
 #include <machine.h>
 
+/* please ensure the length of the machtype string is less than 50 */
+#define MACHTYPE_LEN 50
+
 static const char *system_types[] = {
 	[MACH_LOONGSON_UNKNOWN]         "unknown loongson machine",
 	[MACH_LEMOTE_FL2E]              "lemote-fuloong-2e-box",
@@ -22,29 +25,35 @@
 	[MACH_LEMOTE_ML2F7]             "lemote-mengloong-2f-7inches",
 	[MACH_LEMOTE_YL2F89]            "lemote-yeeloong-2f-8.9inches",
 	[MACH_DEXXON_GDIUM2F10]         "dexxon-gidum-2f-10inches",
+	[MACH_LEMOTE_NAS]		"lemote-nas-2f",
+	[MACH_LEMOTE_LL2F]              "lemote-lynloong-2f",
 	[MACH_LOONGSON_END]             NULL,
 };
 
 const char *get_system_type(void)
 {
-	if (mips_machtype == MACH_UNKNOWN)
-		mips_machtype = LOONGSON_MACHTYPE;
-
 	return system_types[mips_machtype];
 }
 
-static __init int machtype_setup(char *str)
+void __init prom_init_machtype(void)
 {
+	char *p, str[MACHTYPE_LEN];
 	int machtype = MACH_LEMOTE_FL2E;
 
-	if (!str)
-		return -EINVAL;
+	mips_machtype = LOONGSON_MACHTYPE;
+
+	p = strstr(arcs_cmdline, "machtype=");
+	if (!p)
+		return;
+	p += strlen("machtype=");
+	strncpy(str, p, MACHTYPE_LEN);
+	p = strstr(str, " ");
+	if (p)
+		*p = '\0';
 
 	for (; system_types[machtype]; machtype++)
 		if (strstr(system_types[machtype], str)) {
 			mips_machtype = machtype;
 			break;
 		}
-	return 0;
 }
-__setup("machtype=", machtype_setup);
diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c
index e94ef15..ceacd09 100644
--- a/arch/mips/loongson/common/mem.c
+++ b/arch/mips/loongson/common/mem.c
@@ -12,15 +12,40 @@
 
 #include <loongson.h>
 #include <mem.h>
+#include <pci.h>
 
 void __init prom_init_memory(void)
 {
     add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+
+    add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize <<
+			    20), BOOT_MEM_RESERVED);
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+	{
+		int bit;
+
+		bit = fls(memsize + highmemsize);
+		if (bit != ffs(memsize + highmemsize))
+			bit += 20;
+		else
+			bit = bit + 20 - 1;
+
+		/* set cpu window3 to map CPU to DDR: 2G -> 2G */
+		LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul,
+					  0x80000000ul, (1 << bit));
+		mmiowb();
+	}
+#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
+
 #ifdef CONFIG_64BIT
-    if (highmemsize > 0)
-	add_memory_region(LOONGSON_HIGHMEM_START,
-		highmemsize << 20, BOOT_MEM_RAM);
-#endif /* CONFIG_64BIT */
+	if (highmemsize > 0)
+		add_memory_region(LOONGSON_HIGHMEM_START,
+				  highmemsize << 20, BOOT_MEM_RAM);
+
+	add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
+			  LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
+
+#endif /* !CONFIG_64BIT */
 }
 
 /* override of arch/mips/mm/cache.c: __uncached_access */
@@ -33,3 +58,61 @@
 		((addr >= LOONGSON_MMIO_MEM_START) &&
 		 (addr < LOONGSON_MMIO_MEM_END));
 }
+
+#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
+
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+
+static unsigned long uca_start, uca_end;
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+			      unsigned long size, pgprot_t vma_prot)
+{
+	unsigned long offset = pfn << PAGE_SHIFT;
+	unsigned long end = offset + size;
+
+	if (__uncached_access(file, offset)) {
+		if (((uca_start && offset) >= uca_start) &&
+		    (end <= uca_end))
+			return __pgprot((pgprot_val(vma_prot) &
+					 ~_CACHE_MASK) |
+					_CACHE_UNCACHED_ACCELERATED);
+		else
+			return pgprot_noncached(vma_prot);
+	}
+	return vma_prot;
+}
+
+static int __init find_vga_mem_init(void)
+{
+	struct pci_dev *dev = 0;
+	struct resource *r;
+	int idx;
+
+	if (uca_start)
+		return 0;
+
+	for_each_pci_dev(dev) {
+		if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+			for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+				r = &dev->resource[idx];
+				if (!r->start && r->end)
+					continue;
+				if (r->flags & IORESOURCE_IO)
+					continue;
+				if (r->flags & IORESOURCE_MEM) {
+					uca_start = r->start;
+					uca_end = r->end;
+					return 0;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+
+late_initcall(find_vga_mem_init);
+#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */
diff --git a/arch/mips/loongson/common/pci.c b/arch/mips/loongson/common/pci.c
index a3a4abf..31d8c5e 100644
--- a/arch/mips/loongson/common/pci.c
+++ b/arch/mips/loongson/common/pci.c
@@ -27,7 +27,7 @@
 };
 
 static struct pci_controller  loongson_pci_controller = {
-	.pci_ops        = &bonito64_pci_ops,
+	.pci_ops        = &loongson_pci_ops,
 	.io_resource    = &loongson_pci_io_resource,
 	.mem_resource   = &loongson_pci_mem_resource,
 	.mem_offset     = 0x00000000UL,
@@ -44,15 +44,15 @@
 	 * pcimap: PCI_MAP2  PCI_Mem_Lo2 PCI_Mem_Lo1 PCI_Mem_Lo0
 	 * 	     [<2G]   [384M,448M] [320M,384M] [0M,64M]
 	 */
-	BONITO_PCIMAP = BONITO_PCIMAP_PCIMAP_2 |
-		BONITO_PCIMAP_WIN(2, BONITO_PCILO2_BASE) |
-		BONITO_PCIMAP_WIN(1, BONITO_PCILO1_BASE) |
-		BONITO_PCIMAP_WIN(0, 0);
+	LOONGSON_PCIMAP = LOONGSON_PCIMAP_PCIMAP_2 |
+		LOONGSON_PCIMAP_WIN(2, LOONGSON_PCILO2_BASE) |
+		LOONGSON_PCIMAP_WIN(1, LOONGSON_PCILO1_BASE) |
+		LOONGSON_PCIMAP_WIN(0, 0);
 
 	/*
 	 * PCI-DMA to local mapping: [2G,2G+256M] -> [0M,256M]
 	 */
-	BONITO_PCIBASE0 = 0x80000000ul;   /* base: 2G -> mmap: 0M */
+	LOONGSON_PCIBASE0 = 0x80000000ul;   /* base: 2G -> mmap: 0M */
 	/* size: 256M, burst transmission, pre-fetch enable, 64bit */
 	LOONGSON_PCI_HIT0_SEL_L = 0xc000000cul;
 	LOONGSON_PCI_HIT0_SEL_H = 0xfffffffful;
@@ -67,6 +67,14 @@
 	/* can not change gnt to break pci transfer when device's gnt not
 	deassert for some broken device */
 	LOONGSON_PXARB_CFG = 0x00fe0105ul;
+
+#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
+	/*
+	 * set cpu addr window2 to map CPU address space to PCI address space
+	 */
+	LOONGSON_ADDRWIN_CPUTOPCI(ADDRWIN_WIN2, LOONGSON_CPU_MEM_SRC,
+		LOONGSON_PCI_MEM_DST, MMAP_CPUTOPCI_SIZE);
+#endif
 }
 
 static int __init pcibios_init(void)
diff --git a/arch/mips/loongson/common/platform.c b/arch/mips/loongson/common/platform.c
new file mode 100644
index 0000000..be81777
--- /dev/null
+++ b/arch/mips/loongson/common/platform.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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/err.h>
+#include <linux/platform_device.h>
+
+static struct platform_device loongson2_cpufreq_device = {
+	.name = "loongson2_cpufreq",
+	.id = -1,
+};
+
+static int __init loongson2_cpufreq_init(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+
+	/* Only 2F revision and it's successors support CPUFreq */
+	if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON2F)
+		return platform_device_register(&loongson2_cpufreq_device);
+
+	return -ENODEV;
+}
+
+arch_initcall(loongson2_cpufreq_init);
diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c
new file mode 100644
index 0000000..b625fec
--- /dev/null
+++ b/arch/mips/loongson/common/pm.c
@@ -0,0 +1,161 @@
+/*
+ * loongson-specific suspend support
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzj@lemote.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/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+#include <loongson.h>
+
+static unsigned int __maybe_unused cached_master_mask;	/* i8259A */
+static unsigned int __maybe_unused cached_slave_mask;
+static unsigned int __maybe_unused cached_bonito_irq_mask; /* bonito */
+
+void arch_suspend_disable_irqs(void)
+{
+	/* disable all mips events */
+	local_irq_disable();
+
+#ifdef CONFIG_I8259
+	/* disable all events of i8259A */
+	cached_slave_mask = inb(PIC_SLAVE_IMR);
+	cached_master_mask = inb(PIC_MASTER_IMR);
+
+	outb(0xff, PIC_SLAVE_IMR);
+	inb(PIC_SLAVE_IMR);
+	outb(0xff, PIC_MASTER_IMR);
+	inb(PIC_MASTER_IMR);
+#endif
+	/* disable all events of bonito */
+	cached_bonito_irq_mask = LOONGSON_INTEN;
+	LOONGSON_INTENCLR = 0xffff;
+	(void)LOONGSON_INTENCLR;
+}
+
+void arch_suspend_enable_irqs(void)
+{
+	/* enable all mips events */
+	local_irq_enable();
+#ifdef CONFIG_I8259
+	/* only enable the cached events of i8259A */
+	outb(cached_slave_mask, PIC_SLAVE_IMR);
+	outb(cached_master_mask, PIC_MASTER_IMR);
+#endif
+	/* enable all cached events of bonito */
+	LOONGSON_INTENSET = cached_bonito_irq_mask;
+	(void)LOONGSON_INTENSET;
+}
+
+/*
+ * Setup the board-specific events for waking up loongson from wait mode
+ */
+void __weak setup_wakeup_events(void)
+{
+}
+
+/*
+ * Check wakeup events
+ */
+int __weak wakeup_loongson(void)
+{
+	return 1;
+}
+
+/*
+ * If the events are really what we want to wakeup the CPU, wake it up
+ * otherwise put the CPU asleep again.
+ */
+static void wait_for_wakeup_events(void)
+{
+	while (!wakeup_loongson())
+		LOONGSON_CHIPCFG0 &= ~0x7;
+}
+
+/*
+ * Stop all perf counters
+ *
+ * $24 is the control register of Loongson perf counter
+ */
+static inline void stop_perf_counters(void)
+{
+	__write_64bit_c0_register($24, 0, 0);
+}
+
+
+static void loongson_suspend_enter(void)
+{
+	static unsigned int cached_cpu_freq;
+
+	/* setup wakeup events via enabling the IRQs */
+	setup_wakeup_events();
+
+	stop_perf_counters();
+
+	cached_cpu_freq = LOONGSON_CHIPCFG0;
+
+	/* Put CPU into wait mode */
+	LOONGSON_CHIPCFG0 &= ~0x7;
+
+	/* wait for the given events to wakeup cpu from wait mode */
+	wait_for_wakeup_events();
+
+	LOONGSON_CHIPCFG0 = cached_cpu_freq;
+	mmiowb();
+}
+
+void __weak mach_suspend(void)
+{
+}
+
+void __weak mach_resume(void)
+{
+}
+
+static int loongson_pm_enter(suspend_state_t state)
+{
+	mach_suspend();
+
+	/* processor specific suspend */
+	loongson_suspend_enter();
+
+	mach_resume();
+
+	return 0;
+}
+
+static int loongson_pm_valid_state(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_ON:
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+static struct platform_suspend_ops loongson_pm_ops = {
+	.valid	= loongson_pm_valid_state,
+	.enter	= loongson_pm_enter,
+};
+
+static int __init loongson_pm_init(void)
+{
+	suspend_set_ops(&loongson_pm_ops);
+
+	return 0;
+}
+arch_initcall(loongson_pm_init);
diff --git a/arch/mips/loongson/common/reset.c b/arch/mips/loongson/common/reset.c
index 97e9182..d57f171 100644
--- a/arch/mips/loongson/common/reset.c
+++ b/arch/mips/loongson/common/reset.c
@@ -22,7 +22,7 @@
 	mach_prepare_reboot();
 
 	/* reboot via jumping to boot base address */
-	((void (*)(void))ioremap_nocache(BONITO_BOOT_BASE, 4)) ();
+	((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) ();
 }
 
 static void loongson_halt(void)
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
new file mode 100644
index 0000000..23b66a5
--- /dev/null
+++ b/arch/mips/loongson/common/serial.c
@@ -0,0 +1,76 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Copyright (C) 2009 Lemote, Inc.
+ * Author: Yan hua (yanhua@lemote.com)
+ * Author: Wu Zhangjin (wuzj@lemote.com)
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+#include <machine.h>
+
+#define PORT(int)			\
+{								\
+	.irq		= int,					\
+	.uartclk	= 1843200,				\
+	.iotype		= UPIO_PORT,				\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
+	.regshift	= 0,					\
+}
+
+#define PORT_M(int)				\
+{								\
+	.irq		= MIPS_CPU_IRQ_BASE + (int),		\
+	.uartclk	= 3686400,				\
+	.iotype		= UPIO_MEM,				\
+	.membase	= (void __iomem *)NULL,			\
+	.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,	\
+	.regshift	= 0,					\
+}
+
+static struct plat_serial8250_port uart8250_data[][2] = {
+	[MACH_LOONGSON_UNKNOWN]         {},
+	[MACH_LEMOTE_FL2E]              {PORT(4), {} },
+	[MACH_LEMOTE_FL2F]              {PORT(3), {} },
+	[MACH_LEMOTE_ML2F7]             {PORT_M(3), {} },
+	[MACH_LEMOTE_YL2F89]            {PORT_M(3), {} },
+	[MACH_DEXXON_GDIUM2F10]         {PORT_M(3), {} },
+	[MACH_LEMOTE_NAS]               {PORT_M(3), {} },
+	[MACH_LEMOTE_LL2F]              {PORT(3), {} },
+	[MACH_LOONGSON_END]             {},
+};
+
+static struct platform_device uart8250_device = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+};
+
+static int __init serial_init(void)
+{
+	unsigned char iotype;
+
+	iotype = uart8250_data[mips_machtype][0].iotype;
+
+	if (UPIO_MEM == iotype)
+		uart8250_data[mips_machtype][0].membase =
+			(void __iomem *)_loongson_uart_base;
+	else if (UPIO_PORT == iotype)
+		uart8250_data[mips_machtype][0].iobase =
+		    loongson_uart_base - LOONGSON_PCIIO_BASE;
+
+	uart8250_device.dev.platform_data = uart8250_data[mips_machtype];
+
+	return platform_device_register(&uart8250_device);
+}
+
+device_initcall(serial_init);
diff --git a/arch/mips/loongson/common/time.c b/arch/mips/loongson/common/time.c
index 6e08c82..35f0b66 100644
--- a/arch/mips/loongson/common/time.c
+++ b/arch/mips/loongson/common/time.c
@@ -14,11 +14,14 @@
 #include <asm/time.h>
 
 #include <loongson.h>
+#include <cs5536/cs5536_mfgpt.h>
 
 void __init plat_time_init(void)
 {
 	/* setup mips r4k timer */
 	mips_hpt_frequency = cpu_clock_freq / 2;
+
+	setup_mfgpt0_timer();
 }
 
 void read_persistent_clock(struct timespec *ts)
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
new file mode 100644
index 0000000..78ff66a
--- /dev/null
+++ b/arch/mips/loongson/common/uart_base.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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/module.h>
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+/* ioremapped */
+unsigned long _loongson_uart_base;
+EXPORT_SYMBOL(_loongson_uart_base);
+/* raw */
+unsigned long loongson_uart_base;
+EXPORT_SYMBOL(loongson_uart_base);
+
+void prom_init_loongson_uart_base(void)
+{
+	switch (mips_machtype) {
+	case MACH_LEMOTE_FL2E:
+		loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8;
+		break;
+	case MACH_LEMOTE_FL2F:
+	case MACH_LEMOTE_LL2F:
+		loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8;
+		break;
+	case MACH_LEMOTE_ML2F7:
+	case MACH_LEMOTE_YL2F89:
+	case MACH_DEXXON_GDIUM2F10:
+	case MACH_LEMOTE_NAS:
+	default:
+		/* The CPU provided serial port */
+		loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
+		break;
+	}
+
+	_loongson_uart_base =
+		(unsigned long)ioremap_nocache(loongson_uart_base, 8);
+}
diff --git a/arch/mips/loongson/fuloong-2e/irq.c b/arch/mips/loongson/fuloong-2e/irq.c
index 7888cf6..320e937 100644
--- a/arch/mips/loongson/fuloong-2e/irq.c
+++ b/arch/mips/loongson/fuloong-2e/irq.c
@@ -47,8 +47,8 @@
 void __init set_irq_trigger_mode(void)
 {
 	/* most bonito irq should be level triggered */
-	BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
-	    BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+	LOONGSON_INTEDGE = LOONGSON_ICU_SYSTEMERR | LOONGSON_ICU_MASTERERR |
+	    LOONGSON_ICU_RETRYERR | LOONGSON_ICU_MBOXES;
 }
 
 void __init mach_init_irq(void)
diff --git a/arch/mips/loongson/fuloong-2e/reset.c b/arch/mips/loongson/fuloong-2e/reset.c
index 677fe18..fc16c67 100644
--- a/arch/mips/loongson/fuloong-2e/reset.c
+++ b/arch/mips/loongson/fuloong-2e/reset.c
@@ -14,8 +14,8 @@
 
 void mach_prepare_reboot(void)
 {
-	BONITO_BONGENCFG &= ~(1 << 2);
-	BONITO_BONGENCFG |= (1 << 2);
+	LOONGSON_GENCFG &= ~(1 << 2);
+	LOONGSON_GENCFG |= (1 << 2);
 }
 
 void mach_prepare_shutdown(void)
diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile
new file mode 100644
index 0000000..4d84b27
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for lemote loongson2f family machines
+#
+
+obj-y += irq.o reset.o ec_kb3310b.o
+
+#
+# Suspend Support
+#
+
+obj-$(CONFIG_LOONGSON_SUSPEND) += pm.o
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
new file mode 100644
index 0000000..4d84111
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
@@ -0,0 +1,130 @@
+/*
+ * Basic KB3310B Embedded Controller support for the YeeLoong 2F netbook
+ *
+ *  Copyright (C) 2008 Lemote Inc.
+ *  Author: liujl <liujl@lemote.com>, 2008-04-20
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include "ec_kb3310b.h"
+
+static DEFINE_SPINLOCK(index_access_lock);
+static DEFINE_SPINLOCK(port_access_lock);
+
+unsigned char ec_read(unsigned short addr)
+{
+	unsigned char value;
+	unsigned long flags;
+
+	spin_lock_irqsave(&index_access_lock, flags);
+	outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
+	outb((addr & 0x00ff), EC_IO_PORT_LOW);
+	value = inb(EC_IO_PORT_DATA);
+	spin_unlock_irqrestore(&index_access_lock, flags);
+
+	return value;
+}
+EXPORT_SYMBOL_GPL(ec_read);
+
+void ec_write(unsigned short addr, unsigned char val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&index_access_lock, flags);
+	outb((addr & 0xff00) >> 8, EC_IO_PORT_HIGH);
+	outb((addr & 0x00ff), EC_IO_PORT_LOW);
+	outb(val, EC_IO_PORT_DATA);
+	/*  flush the write action */
+	inb(EC_IO_PORT_DATA);
+	spin_unlock_irqrestore(&index_access_lock, flags);
+
+	return;
+}
+EXPORT_SYMBOL_GPL(ec_write);
+
+/*
+ * This function is used for EC command writes and corresponding status queries.
+ */
+int ec_query_seq(unsigned char cmd)
+{
+	int timeout;
+	unsigned char status;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&port_access_lock, flags);
+
+	/* make chip goto reset mode */
+	udelay(EC_REG_DELAY);
+	outb(cmd, EC_CMD_PORT);
+	udelay(EC_REG_DELAY);
+
+	/* check if the command is received by ec */
+	timeout = EC_CMD_TIMEOUT;
+	status = inb(EC_STS_PORT);
+	while (timeout-- && (status & (1 << 1))) {
+		status = inb(EC_STS_PORT);
+		udelay(EC_REG_DELAY);
+	}
+
+	if (timeout <= 0) {
+		printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
+		ret = -EINVAL;
+	} else
+		printk(KERN_INFO
+			   "(%x/%d)ec issued command %d status : 0x%x\n",
+			   timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
+
+	spin_unlock_irqrestore(&port_access_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ec_query_seq);
+
+/*
+ * Send query command to EC to get the proper event number
+ */
+int ec_query_event_num(void)
+{
+	return ec_query_seq(CMD_GET_EVENT_NUM);
+}
+EXPORT_SYMBOL(ec_query_event_num);
+
+/*
+ * Get event number from EC
+ *
+ * NOTE: This routine must follow the query_event_num function in the
+ * interrupt.
+ */
+int ec_get_event_num(void)
+{
+	int timeout = 100;
+	unsigned char value;
+	unsigned char status;
+
+	udelay(EC_REG_DELAY);
+	status = inb(EC_STS_PORT);
+	udelay(EC_REG_DELAY);
+	while (timeout-- && !(status & (1 << 0))) {
+		status = inb(EC_STS_PORT);
+		udelay(EC_REG_DELAY);
+	}
+	if (timeout <= 0) {
+		pr_info("%s: get event number timeout.\n", __func__);
+
+		return -EINVAL;
+	}
+	value = inb(EC_DAT_PORT);
+	udelay(EC_REG_DELAY);
+
+	return value;
+}
+EXPORT_SYMBOL(ec_get_event_num);
diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.h b/arch/mips/loongson/lemote-2f/ec_kb3310b.h
new file mode 100644
index 0000000..1595a21
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.h
@@ -0,0 +1,188 @@
+/*
+ * KB3310B Embedded Controller
+ *
+ *  Copyright (C) 2008 Lemote Inc.
+ *  Author: liujl <liujl@lemote.com>, 2008-03-14
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _EC_KB3310B_H
+#define _EC_KB3310B_H
+
+extern unsigned char ec_read(unsigned short addr);
+extern void ec_write(unsigned short addr, unsigned char val);
+extern int ec_query_seq(unsigned char cmd);
+extern int ec_query_event_num(void);
+extern int ec_get_event_num(void);
+
+typedef int (*sci_handler) (int status);
+extern sci_handler yeeloong_report_lid_status;
+
+#define SCI_IRQ_NUM 0x0A
+
+/*
+ * The following registers are determined by the EC index configuration.
+ * 1, fill the PORT_HIGH as EC register high part.
+ * 2, fill the PORT_LOW as EC register low part.
+ * 3, fill the PORT_DATA as EC register write data or get the data from it.
+ */
+#define	EC_IO_PORT_HIGH	0x0381
+#define	EC_IO_PORT_LOW	0x0382
+#define	EC_IO_PORT_DATA	0x0383
+
+/*
+ * EC delay time is 500us for register and status access
+ */
+#define	EC_REG_DELAY	500	/* unit : us */
+#define	EC_CMD_TIMEOUT	0x1000
+
+/*
+ * EC access port for SCI communication
+ */
+#define	EC_CMD_PORT		0x66
+#define	EC_STS_PORT		0x66
+#define	EC_DAT_PORT		0x62
+#define	CMD_INIT_IDLE_MODE	0xdd
+#define	CMD_EXIT_IDLE_MODE	0xdf
+#define	CMD_INIT_RESET_MODE	0xd8
+#define	CMD_REBOOT_SYSTEM	0x8c
+#define	CMD_GET_EVENT_NUM	0x84
+#define	CMD_PROGRAM_PIECE	0xda
+
+/* temperature & fan registers */
+#define	REG_TEMPERATURE_VALUE	0xF458
+#define	REG_FAN_AUTO_MAN_SWITCH 0xF459
+#define	BIT_FAN_AUTO		0
+#define	BIT_FAN_MANUAL		1
+#define	REG_FAN_CONTROL		0xF4D2
+#define	BIT_FAN_CONTROL_ON	(1 << 0)
+#define	BIT_FAN_CONTROL_OFF	(0 << 0)
+#define	REG_FAN_STATUS		0xF4DA
+#define	BIT_FAN_STATUS_ON	(1 << 0)
+#define	BIT_FAN_STATUS_OFF	(0 << 0)
+#define	REG_FAN_SPEED_HIGH	0xFE22
+#define	REG_FAN_SPEED_LOW	0xFE23
+#define	REG_FAN_SPEED_LEVEL	0xF4CC
+/* fan speed divider */
+#define	FAN_SPEED_DIVIDER	480000	/* (60*1000*1000/62.5/2)*/
+
+/* battery registers */
+#define	REG_BAT_DESIGN_CAP_HIGH		0xF77D
+#define	REG_BAT_DESIGN_CAP_LOW		0xF77E
+#define	REG_BAT_FULLCHG_CAP_HIGH	0xF780
+#define	REG_BAT_FULLCHG_CAP_LOW		0xF781
+#define	REG_BAT_DESIGN_VOL_HIGH		0xF782
+#define	REG_BAT_DESIGN_VOL_LOW		0xF783
+#define	REG_BAT_CURRENT_HIGH		0xF784
+#define	REG_BAT_CURRENT_LOW		0xF785
+#define	REG_BAT_VOLTAGE_HIGH		0xF786
+#define	REG_BAT_VOLTAGE_LOW		0xF787
+#define	REG_BAT_TEMPERATURE_HIGH	0xF788
+#define	REG_BAT_TEMPERATURE_LOW		0xF789
+#define	REG_BAT_RELATIVE_CAP_HIGH	0xF492
+#define	REG_BAT_RELATIVE_CAP_LOW	0xF493
+#define	REG_BAT_VENDOR			0xF4C4
+#define	FLAG_BAT_VENDOR_SANYO		0x01
+#define	FLAG_BAT_VENDOR_SIMPLO		0x02
+#define	REG_BAT_CELL_COUNT		0xF4C6
+#define	FLAG_BAT_CELL_3S1P		0x03
+#define	FLAG_BAT_CELL_3S2P		0x06
+#define	REG_BAT_CHARGE			0xF4A2
+#define	FLAG_BAT_CHARGE_DISCHARGE	0x01
+#define	FLAG_BAT_CHARGE_CHARGE		0x02
+#define	FLAG_BAT_CHARGE_ACPOWER		0x00
+#define	REG_BAT_STATUS			0xF4B0
+#define	BIT_BAT_STATUS_LOW		(1 << 5)
+#define	BIT_BAT_STATUS_DESTROY		(1 << 2)
+#define	BIT_BAT_STATUS_FULL		(1 << 1)
+#define	BIT_BAT_STATUS_IN		(1 << 0)
+#define	REG_BAT_CHARGE_STATUS		0xF4B1
+#define	BIT_BAT_CHARGE_STATUS_OVERTEMP	(1 << 2)
+#define	BIT_BAT_CHARGE_STATUS_PRECHG	(1 << 1)
+#define	REG_BAT_STATE			0xF482
+#define	BIT_BAT_STATE_CHARGING		(1 << 1)
+#define	BIT_BAT_STATE_DISCHARGING	(1 << 0)
+#define	REG_BAT_POWER			0xF440
+#define	BIT_BAT_POWER_S3		(1 << 2)
+#define	BIT_BAT_POWER_ON		(1 << 1)
+#define	BIT_BAT_POWER_ACIN		(1 << 0)
+
+/* other registers */
+/* Audio: rd/wr */
+#define	REG_AUDIO_VOLUME	0xF46C
+#define	REG_AUDIO_MUTE		0xF4E7
+#define	REG_AUDIO_BEEP		0xF4D0
+/* USB port power or not: rd/wr */
+#define	REG_USB0_FLAG		0xF461
+#define	REG_USB1_FLAG		0xF462
+#define	REG_USB2_FLAG		0xF463
+#define	BIT_USB_FLAG_ON		1
+#define	BIT_USB_FLAG_OFF	0
+/* LID */
+#define	REG_LID_DETECT		0xF4BD
+#define	BIT_LID_DETECT_ON	1
+#define	BIT_LID_DETECT_OFF	0
+/* CRT */
+#define	REG_CRT_DETECT		0xF4AD
+#define	BIT_CRT_DETECT_PLUG	1
+#define	BIT_CRT_DETECT_UNPLUG	0
+/* LCD backlight brightness adjust: 9 levels */
+#define	REG_DISPLAY_BRIGHTNESS	0xF4F5
+/* Black screen Status */
+#define	BIT_DISPLAY_LCD_ON	1
+#define	BIT_DISPLAY_LCD_OFF	0
+/* LCD backlight control: off/restore */
+#define	REG_BACKLIGHT_CTRL	0xF7BD
+#define	BIT_BACKLIGHT_ON	1
+#define	BIT_BACKLIGHT_OFF	0
+/* Reset the machine auto-clear: rd/wr */
+#define	REG_RESET		0xF4EC
+#define	BIT_RESET_ON		1
+/* Light the led: rd/wr */
+#define	REG_LED			0xF4C8
+#define	BIT_LED_RED_POWER	(1 << 0)
+#define	BIT_LED_ORANGE_POWER	(1 << 1)
+#define	BIT_LED_GREEN_CHARGE	(1 << 2)
+#define	BIT_LED_RED_CHARGE	(1 << 3)
+#define	BIT_LED_NUMLOCK		(1 << 4)
+/* Test led mode, all led on/off */
+#define	REG_LED_TEST		0xF4C2
+#define	BIT_LED_TEST_IN		1
+#define	BIT_LED_TEST_OUT	0
+/* Camera on/off */
+#define	REG_CAMERA_STATUS	0xF46A
+#define	BIT_CAMERA_STATUS_ON	1
+#define	BIT_CAMERA_STATUS_OFF	0
+#define	REG_CAMERA_CONTROL	0xF7B7
+#define	BIT_CAMERA_CONTROL_OFF	0
+#define	BIT_CAMERA_CONTROL_ON	1
+/* Wlan Status */
+#define	REG_WLAN		0xF4FA
+#define	BIT_WLAN_ON		1
+#define	BIT_WLAN_OFF		0
+#define	REG_DISPLAY_LCD		0xF79F
+
+/* SCI Event Number from EC */
+enum {
+	EVENT_LID = 0x23,	/*  LID open/close */
+	EVENT_DISPLAY_TOGGLE,	/*  Fn+F3 for display switch */
+	EVENT_SLEEP,		/*  Fn+F1 for entering sleep mode */
+	EVENT_OVERTEMP,		/*  Over-temperature happened */
+	EVENT_CRT_DETECT,	/*  CRT is connected */
+	EVENT_CAMERA,		/*  Camera on/off */
+	EVENT_USB_OC2,		/*  USB2 Over Current occurred */
+	EVENT_USB_OC0,		/*  USB0 Over Current occurred */
+	EVENT_BLACK_SCREEN,	/*  Turn on/off backlight */
+	EVENT_AUDIO_MUTE,	/*  Mute on/off */
+	EVENT_DISPLAY_BRIGHTNESS,/* LCD backlight brightness adjust */
+	EVENT_AC_BAT,		/*  AC & Battery relative issue */
+	EVENT_AUDIO_VOLUME,	/*  Volume adjust */
+	EVENT_WLAN,		/*  Wlan on/off */
+	EVENT_END
+};
+
+#endif /* !_EC_KB3310B_H */
diff --git a/arch/mips/loongson/lemote-2f/irq.c b/arch/mips/loongson/lemote-2f/irq.c
new file mode 100644
index 0000000..77d32f9
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/irq.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2007 Lemote Inc.
+ * Author: Fuxin Zhang, zhangfx@lemote.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/interrupt.h>
+#include <linux/module.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+
+#include <loongson.h>
+#include <machine.h>
+
+#define LOONGSON_TIMER_IRQ	(MIPS_CPU_IRQ_BASE + 7)	/* cpu timer */
+#define LOONGSON_PERFCNT_IRQ	(MIPS_CPU_IRQ_BASE + 6)	/* cpu perf counter */
+#define LOONGSON_NORTH_BRIDGE_IRQ	(MIPS_CPU_IRQ_BASE + 6)	/* bonito */
+#define LOONGSON_UART_IRQ	(MIPS_CPU_IRQ_BASE + 3)	/* cpu serial port */
+#define LOONGSON_SOUTH_BRIDGE_IRQ	(MIPS_CPU_IRQ_BASE + 2)	/* i8259 */
+
+#define LOONGSON_INT_BIT_INT0		(1 << 11)
+#define LOONGSON_INT_BIT_INT1		(1 << 12)
+
+/*
+ * The generic i8259_irq() make the kernel hang on booting.  Since we cannot
+ * get the irq via the IRR directly, we access the ISR instead.
+ */
+int mach_i8259_irq(void)
+{
+	int irq, isr;
+
+	irq = -1;
+
+	if ((LOONGSON_INTISR & LOONGSON_INTEN) & LOONGSON_INT_BIT_INT0) {
+		spin_lock(&i8259A_lock);
+		isr = inb(PIC_MASTER_CMD) &
+			~inb(PIC_MASTER_IMR) & ~(1 << PIC_CASCADE_IR);
+		if (!isr)
+			isr = (inb(PIC_SLAVE_CMD) & ~inb(PIC_SLAVE_IMR)) << 8;
+		irq = ffs(isr) - 1;
+		if (unlikely(irq == 7)) {
+			/*
+			 * This may be a spurious interrupt.
+			 *
+			 * Read the interrupt status register (ISR). If the most
+			 * significant bit is not set then there is no valid
+			 * interrupt.
+			 */
+			outb(0x0B, PIC_MASTER_ISR);	/* ISR register */
+			if (~inb(PIC_MASTER_ISR) & 0x80)
+				irq = -1;
+		}
+		spin_unlock(&i8259A_lock);
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL(mach_i8259_irq);
+
+static void i8259_irqdispatch(void)
+{
+	int irq;
+
+	irq = mach_i8259_irq();
+	if (irq >= 0)
+		do_IRQ(irq);
+	else
+		spurious_interrupt();
+}
+
+void mach_irq_dispatch(unsigned int pending)
+{
+	if (pending & CAUSEF_IP7)
+		do_IRQ(LOONGSON_TIMER_IRQ);
+	else if (pending & CAUSEF_IP6) {	/* North Bridge, Perf counter */
+#ifdef CONFIG_OPROFILE
+		do_IRQ(LOONGSON2_PERFCNT_IRQ);
+#endif
+		bonito_irqdispatch();
+	} else if (pending & CAUSEF_IP3)	/* CPU UART */
+		do_IRQ(LOONGSON_UART_IRQ);
+	else if (pending & CAUSEF_IP2)	/* South Bridge */
+		i8259_irqdispatch();
+	else
+		spurious_interrupt();
+}
+
+void __init set_irq_trigger_mode(void)
+{
+	/* setup cs5536 as high level trigger */
+	LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1;
+	LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1);
+}
+
+static irqreturn_t ip6_action(int cpl, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+struct irqaction ip6_irqaction = {
+	.handler = ip6_action,
+	.name = "cascade",
+	.flags = IRQF_SHARED,
+};
+
+struct irqaction cascade_irqaction = {
+	.handler = no_action,
+	.name = "cascade",
+};
+
+void __init mach_init_irq(void)
+{
+	/* init all controller
+	 *   0-15         ------> i8259 interrupt
+	 *   16-23        ------> mips cpu interrupt
+	 *   32-63        ------> bonito irq
+	 */
+
+	/* Sets the first-level interrupt dispatcher. */
+	mips_cpu_irq_init();
+	init_i8259_irqs();
+	bonito_irq_init();
+
+	/* setup north bridge irq (bonito) */
+	setup_irq(LOONGSON_NORTH_BRIDGE_IRQ, &ip6_irqaction);
+	/* setup source bridge irq (i8259) */
+	setup_irq(LOONGSON_SOUTH_BRIDGE_IRQ, &cascade_irqaction);
+}
diff --git a/arch/mips/loongson/lemote-2f/pm.c b/arch/mips/loongson/lemote-2f/pm.c
new file mode 100644
index 0000000..d7af2e6
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/pm.c
@@ -0,0 +1,149 @@
+/*
+ *  Lemote loongson2f family machines' specific suspend support
+ *
+ *  Copyright (C) 2009 Lemote Inc.
+ *  Author: Wu Zhangjin <wuzj@lemote.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/suspend.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+#include <linux/i8042.h>
+#include <linux/module.h>
+
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+#include <cs5536/cs5536_mfgpt.h>
+#include "ec_kb3310b.h"
+
+#define I8042_KBD_IRQ		1
+#define I8042_CTR_KBDINT	0x01
+#define I8042_CTR_KBDDIS	0x10
+
+static unsigned char i8042_ctr;
+
+static int i8042_enable_kbd_port(void)
+{
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
+		pr_err("i8042.c: Can't read CTR while enabling i8042 kbd port."
+		       "\n");
+		return -EIO;
+	}
+
+	i8042_ctr &= ~I8042_CTR_KBDDIS;
+	i8042_ctr |= I8042_CTR_KBDINT;
+
+	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+		i8042_ctr &= ~I8042_CTR_KBDINT;
+		i8042_ctr |= I8042_CTR_KBDDIS;
+		pr_err("i8042.c: Failed to enable KBD port.\n");
+
+		return -EIO;
+	}
+
+	return 0;
+}
+
+void setup_wakeup_events(void)
+{
+	int irq_mask;
+
+	switch (mips_machtype) {
+	case MACH_LEMOTE_ML2F7:
+	case MACH_LEMOTE_YL2F89:
+		/* open the keyboard irq in i8259A */
+		outb((0xff & ~(1 << I8042_KBD_IRQ)), PIC_MASTER_IMR);
+		irq_mask = inb(PIC_MASTER_IMR);
+
+		/* enable keyboard port */
+		i8042_enable_kbd_port();
+
+		/* Wakeup CPU via SCI lid open event */
+		outb(irq_mask & ~(1 << PIC_CASCADE_IR), PIC_MASTER_IMR);
+		inb(PIC_MASTER_IMR);
+		outb(0xff & ~(1 << (SCI_IRQ_NUM - 8)), PIC_SLAVE_IMR);
+		inb(PIC_SLAVE_IMR);
+
+		break;
+
+	default:
+		break;
+	}
+}
+
+static struct delayed_work lid_task;
+static int initialized;
+/* yeeloong_report_lid_status will be implemented in yeeloong_laptop.c */
+sci_handler yeeloong_report_lid_status;
+EXPORT_SYMBOL(yeeloong_report_lid_status);
+static void yeeloong_lid_update_task(struct work_struct *work)
+{
+	if (yeeloong_report_lid_status)
+		yeeloong_report_lid_status(BIT_LID_DETECT_ON);
+}
+
+int wakeup_loongson(void)
+{
+	int irq;
+
+	/* query the interrupt number */
+	irq = mach_i8259_irq();
+	if (irq < 0)
+		return 0;
+
+	printk(KERN_INFO "%s: irq = %d\n", __func__, irq);
+
+	if (irq == I8042_KBD_IRQ)
+		return 1;
+	else if (irq == SCI_IRQ_NUM) {
+		int ret, sci_event;
+		/* query the event number */
+		ret = ec_query_seq(CMD_GET_EVENT_NUM);
+		if (ret < 0)
+			return 0;
+		sci_event = ec_get_event_num();
+		if (sci_event < 0)
+			return 0;
+		if (sci_event == EVENT_LID) {
+			int lid_status;
+			/* check the LID status */
+			lid_status = ec_read(REG_LID_DETECT);
+			/* wakeup cpu when people open the LID */
+			if (lid_status == BIT_LID_DETECT_ON) {
+				/* If we call it directly here, the WARNING
+				 * will be sent out by getnstimeofday
+				 * via "WARN_ON(timekeeping_suspended);"
+				 * because we can not schedule in suspend mode.
+				 */
+				if (initialized == 0) {
+					INIT_DELAYED_WORK(&lid_task,
+						yeeloong_lid_update_task);
+					initialized = 1;
+				}
+				schedule_delayed_work(&lid_task, 1);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void __weak mach_suspend(void)
+{
+	disable_mfgpt0_counter();
+}
+
+void __weak mach_resume(void)
+{
+	enable_mfgpt0_counter();
+}
diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c
new file mode 100644
index 0000000..51d1a60
--- /dev/null
+++ b/arch/mips/loongson/lemote-2f/reset.c
@@ -0,0 +1,159 @@
+/* Board-specific reboot/shutdown routines
+ *
+ * Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzj@lemote.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/io.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+
+#include <loongson.h>
+
+#include <cs5536/cs5536.h>
+#include "ec_kb3310b.h"
+
+static void reset_cpu(void)
+{
+	/*
+	 * reset cpu to full speed, this is needed when enabling cpu frequency
+	 * scalling
+	 */
+	LOONGSON_CHIPCFG0 |= 0x7;
+}
+
+/* reset support for fuloong2f */
+
+static void fl2f_reboot(void)
+{
+	reset_cpu();
+
+	/* send a reset signal to south bridge.
+	 *
+	 * NOTE: if enable "Power Management" in kernel, rtl8169 will not reset
+	 * normally with this reset operation and it will not work in PMON, but
+	 * you can type halt command and then reboot, seems the hardware reset
+	 * logic not work normally.
+	 */
+	{
+		u32 hi, lo;
+		_rdmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), &hi, &lo);
+		lo |= 0x00000001;
+		_wrmsr(DIVIL_MSR_REG(DIVIL_SOFT_RESET), hi, lo);
+	}
+}
+
+static void fl2f_shutdown(void)
+{
+	u32 hi, lo, val;
+	int gpio_base;
+
+	/* get gpio base */
+	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo);
+	gpio_base = lo & 0xff00;
+
+	/* make cs5536 gpio13 output enable */
+	val = inl(gpio_base + GPIOL_OUT_EN);
+	val &= ~(1 << (16 + 13));
+	val |= (1 << 13);
+	outl(val, gpio_base + GPIOL_OUT_EN);
+	mmiowb();
+	/* make cs5536 gpio13 output low level voltage. */
+	val = inl(gpio_base + GPIOL_OUT_VAL) & ~(1 << (13));
+	val |= (1 << (16 + 13));
+	outl(val, gpio_base + GPIOL_OUT_VAL);
+	mmiowb();
+}
+
+/* reset support for yeeloong2f and mengloong2f notebook */
+
+void ml2f_reboot(void)
+{
+	reset_cpu();
+
+	/* sending an reset signal to EC(embedded controller) */
+	ec_write(REG_RESET, BIT_RESET_ON);
+}
+
+#define yl2f89_reboot ml2f_reboot
+
+/* menglong(7inches) laptop has different shutdown logic from 8.9inches */
+#define EC_SHUTDOWN_IO_PORT_HIGH 0xff2d
+#define EC_SHUTDOWN_IO_PORT_LOW	 0xff2e
+#define EC_SHUTDOWN_IO_PORT_DATA 0xff2f
+#define REG_SHUTDOWN_HIGH        0xFC
+#define REG_SHUTDOWN_LOW         0x29
+#define BIT_SHUTDOWN_ON          (1 << 1)
+
+static void ml2f_shutdown(void)
+{
+	u8 val;
+	u64 i;
+
+	outb(REG_SHUTDOWN_HIGH, EC_SHUTDOWN_IO_PORT_HIGH);
+	outb(REG_SHUTDOWN_LOW, EC_SHUTDOWN_IO_PORT_LOW);
+	mmiowb();
+	val = inb(EC_SHUTDOWN_IO_PORT_DATA);
+	outb(val & (~BIT_SHUTDOWN_ON), EC_SHUTDOWN_IO_PORT_DATA);
+	mmiowb();
+	/* need enough wait here... how many microseconds needs? */
+	for (i = 0; i < 0x10000; i++)
+		delay();
+	outb(val | BIT_SHUTDOWN_ON, EC_SHUTDOWN_IO_PORT_DATA);
+	mmiowb();
+}
+
+static void yl2f89_shutdown(void)
+{
+	/* cpu-gpio0 output low */
+	LOONGSON_GPIODATA &= ~0x00000001;
+	/* cpu-gpio0 as output */
+	LOONGSON_GPIOIE &= ~0x00000001;
+}
+
+void mach_prepare_reboot(void)
+{
+	switch (mips_machtype) {
+	case MACH_LEMOTE_FL2F:
+	case MACH_LEMOTE_NAS:
+	case MACH_LEMOTE_LL2F:
+		fl2f_reboot();
+		break;
+	case MACH_LEMOTE_ML2F7:
+		ml2f_reboot();
+		break;
+	case MACH_LEMOTE_YL2F89:
+		yl2f89_reboot();
+		break;
+	default:
+		break;
+	}
+}
+
+void mach_prepare_shutdown(void)
+{
+	switch (mips_machtype) {
+	case MACH_LEMOTE_FL2F:
+	case MACH_LEMOTE_NAS:
+	case MACH_LEMOTE_LL2F:
+		fl2f_shutdown();
+		break;
+	case MACH_LEMOTE_ML2F7:
+		ml2f_shutdown();
+		break;
+	case MACH_LEMOTE_YL2F89:
+		yl2f89_shutdown();
+		break;
+	default:
+		break;
+	}
+}
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 454b539..8f2f8e9 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -35,6 +35,7 @@
  * better performance by compiling with -msoft-float!
  */
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/debugfs.h>
 
 #include <asm/inst.h>
@@ -68,7 +69,9 @@
 
 /* Further private data for which no space exists in mips_fpu_struct */
 
-struct mips_fpu_emulator_stats fpuemustats;
+#ifdef CONFIG_DEBUG_FS
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+#endif
 
 /* Control registers */
 
@@ -209,7 +212,7 @@
 	unsigned int cond;
 
 	if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
-		fpuemustats.errors++;
+		MIPS_FPU_EMU_INC_STATS(errors);
 		return SIGBUS;
 	}
 
@@ -240,7 +243,7 @@
 			return SIGILL;
 		}
 		if (get_user(ir, (mips_instruction __user *) emulpc)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		/* __compute_return_epc() will have updated cp0_epc */
@@ -253,16 +256,16 @@
 	}
 
       emul:
-	fpuemustats.emulated++;
+	MIPS_FPU_EMU_INC_STATS(emulated);
 	switch (MIPSInst_OPCODE(ir)) {
 	case ldc1_op:{
 		u64 __user *va = (u64 __user *) (xcp->regs[MIPSInst_RS(ir)] +
 			MIPSInst_SIMM(ir));
 		u64 val;
 
-		fpuemustats.loads++;
+		MIPS_FPU_EMU_INC_STATS(loads);
 		if (get_user(val, va)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		DITOREG(val, MIPSInst_RT(ir));
@@ -274,10 +277,10 @@
 			MIPSInst_SIMM(ir));
 		u64 val;
 
-		fpuemustats.stores++;
+		MIPS_FPU_EMU_INC_STATS(stores);
 		DIFROMREG(val, MIPSInst_RT(ir));
 		if (put_user(val, va)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		break;
@@ -288,9 +291,9 @@
 			MIPSInst_SIMM(ir));
 		u32 val;
 
-		fpuemustats.loads++;
+		MIPS_FPU_EMU_INC_STATS(loads);
 		if (get_user(val, va)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		SITOREG(val, MIPSInst_RT(ir));
@@ -302,10 +305,10 @@
 			MIPSInst_SIMM(ir));
 		u32 val;
 
-		fpuemustats.stores++;
+		MIPS_FPU_EMU_INC_STATS(stores);
 		SIFROMREG(val, MIPSInst_RT(ir));
 		if (put_user(val, va)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		break;
@@ -429,7 +432,7 @@
 
 				if (get_user(ir,
 				    (mips_instruction __user *) xcp->cp0_epc)) {
-					fpuemustats.errors++;
+					MIPS_FPU_EMU_INC_STATS(errors);
 					return SIGBUS;
 				}
 
@@ -595,7 +598,7 @@
 {
 	unsigned rcsr = 0;	/* resulting csr */
 
-	fpuemustats.cp1xops++;
+	MIPS_FPU_EMU_INC_STATS(cp1xops);
 
 	switch (MIPSInst_FMA_FFMT(ir)) {
 	case s_fmt:{		/* 0 */
@@ -610,9 +613,9 @@
 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemustats.loads++;
+			MIPS_FPU_EMU_INC_STATS(loads);
 			if (get_user(val, va)) {
-				fpuemustats.errors++;
+				MIPS_FPU_EMU_INC_STATS(errors);
 				return SIGBUS;
 			}
 			SITOREG(val, MIPSInst_FD(ir));
@@ -622,11 +625,11 @@
 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemustats.stores++;
+			MIPS_FPU_EMU_INC_STATS(stores);
 
 			SIFROMREG(val, MIPSInst_FS(ir));
 			if (put_user(val, va)) {
-				fpuemustats.errors++;
+				MIPS_FPU_EMU_INC_STATS(errors);
 				return SIGBUS;
 			}
 			break;
@@ -687,9 +690,9 @@
 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemustats.loads++;
+			MIPS_FPU_EMU_INC_STATS(loads);
 			if (get_user(val, va)) {
-				fpuemustats.errors++;
+				MIPS_FPU_EMU_INC_STATS(errors);
 				return SIGBUS;
 			}
 			DITOREG(val, MIPSInst_FD(ir));
@@ -699,10 +702,10 @@
 			va = (void __user *) (xcp->regs[MIPSInst_FR(ir)] +
 				xcp->regs[MIPSInst_FT(ir)]);
 
-			fpuemustats.stores++;
+			MIPS_FPU_EMU_INC_STATS(stores);
 			DIFROMREG(val, MIPSInst_FS(ir));
 			if (put_user(val, va)) {
-				fpuemustats.errors++;
+				MIPS_FPU_EMU_INC_STATS(errors);
 				return SIGBUS;
 			}
 			break;
@@ -769,7 +772,7 @@
 #endif
 	} rv;			/* resulting value */
 
-	fpuemustats.cp1ops++;
+	MIPS_FPU_EMU_INC_STATS(cp1ops);
 	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
 	case s_fmt:{		/* 0 */
 		union {
@@ -1240,7 +1243,7 @@
 		prevepc = xcp->cp0_epc;
 
 		if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
-			fpuemustats.errors++;
+			MIPS_FPU_EMU_INC_STATS(errors);
 			return SIGBUS;
 		}
 		if (insn == 0)
@@ -1276,33 +1279,50 @@
 }
 
 #ifdef CONFIG_DEBUG_FS
+
+static int fpuemu_stat_get(void *data, u64 *val)
+{
+	int cpu;
+	unsigned long sum = 0;
+	for_each_online_cpu(cpu) {
+		struct mips_fpu_emulator_stats *ps;
+		local_t *pv;
+		ps = &per_cpu(fpuemustats, cpu);
+		pv = (void *)ps + (unsigned long)data;
+		sum += local_read(pv);
+	}
+	*val = sum;
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_fpuemu_stat, fpuemu_stat_get, NULL, "%llu\n");
+
 extern struct dentry *mips_debugfs_dir;
 static int __init debugfs_fpuemu(void)
 {
 	struct dentry *d, *dir;
-	int i;
-	static struct {
-		const char *name;
-		unsigned int *v;
-	} vars[] __initdata = {
-		{ "emulated", &fpuemustats.emulated },
-		{ "loads",    &fpuemustats.loads },
-		{ "stores",   &fpuemustats.stores },
-		{ "cp1ops",   &fpuemustats.cp1ops },
-		{ "cp1xops",  &fpuemustats.cp1xops },
-		{ "errors",   &fpuemustats.errors },
-	};
 
 	if (!mips_debugfs_dir)
 		return -ENODEV;
 	dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
 	if (!dir)
 		return -ENOMEM;
-	for (i = 0; i < ARRAY_SIZE(vars); i++) {
-		d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
-		if (!d)
-			return -ENOMEM;
-	}
+
+#define FPU_STAT_CREATE(M)						\
+	do {								\
+		d = debugfs_create_file(#M , S_IRUGO, dir,		\
+			(void *)offsetof(struct mips_fpu_emulator_stats, M), \
+			&fops_fpuemu_stat);				\
+		if (!d)							\
+			return -ENOMEM;					\
+	} while (0)
+
+	FPU_STAT_CREATE(emulated);
+	FPU_STAT_CREATE(loads);
+	FPU_STAT_CREATE(stores);
+	FPU_STAT_CREATE(cp1ops);
+	FPU_STAT_CREATE(cp1xops);
+	FPU_STAT_CREATE(errors);
+
 	return 0;
 }
 __initcall(debugfs_fpuemu);
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index df7b9d9..36d975a 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -98,7 +98,7 @@
 	err |= __put_user(cpc, &fr->epc);
 
 	if (unlikely(err)) {
-		fpuemustats.errors++;
+		MIPS_FPU_EMU_INC_STATS(errors);
 		return SIGBUS;
 	}
 
@@ -136,7 +136,7 @@
 	err |= __get_user(cookie, &fr->cookie);
 
 	if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
-		fpuemustats.errors++;
+		MIPS_FPU_EMU_INC_STATS(errors);
 		return 0;
 	}
 
diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile
index 57f43c1..41b9657 100644
--- a/arch/mips/mipssim/Makefile
+++ b/arch/mips/mipssim/Makefile
@@ -17,8 +17,7 @@
 # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 #
 
-obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \
-	 sim_cmdline.o
+obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o
 
 obj-$(CONFIG_EARLY_PRINTK) += sim_console.o
 obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index 2877675..0824f6a 100644
--- a/arch/mips/mipssim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -61,7 +61,6 @@
 	set_io_port_base(0xbfd00000);
 
 	pr_info("\nLINUX started...\n");
-	prom_init_cmdline();
 	prom_meminit();
 
 #ifdef CONFIG_MIPS_MT_SMP
diff --git a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c
index 1bd1f18..3571090 100644
--- a/arch/mips/mm/cerr-sb1.c
+++ b/arch/mips/mm/cerr-sb1.c
@@ -567,13 +567,10 @@
 				datalo = ((unsigned long long)datalohi << 32) | datalolo;
 				ecc = dc_ecc(datalo);
 				if (ecc != datahi) {
-					int bits = 0;
+					int bits;
 					bad_ecc |= 1 << (3-offset);
 					ecc ^= datahi;
-					while (ecc) {
-						if (ecc & 1) bits++;
-						ecc >>= 1;
-					}
+					bits = hweight8(ecc);
 					res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
 				}
 				printk("  %02X-%016llX", datahi, datalo);
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 8d1f4f3..9e8d003 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -462,7 +462,9 @@
 			__pa_symbol(&__init_end));
 }
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 unsigned long pgd_current[NR_CPUS];
+#endif
 /*
  * On 64-bit we've got three-level pagetables with a slightly
  * different layout ...
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index bb1719a..3d0baa4 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -160,6 +160,12 @@
 static struct uasm_label labels[128] __cpuinitdata;
 static struct uasm_reloc relocs[128] __cpuinitdata;
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
+/*
+ * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
+ * we cannot do r3000 under these circumstances.
+ */
+
 /*
  * The R3000 TLB handler is simple.
  */
@@ -199,6 +205,7 @@
 
 	dump_handler((u32 *)ebase, 32);
 }
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
 /*
  * The R4000 TLB handler is much more complicated. We have two
@@ -497,8 +504,9 @@
 build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 		 unsigned int tmp, unsigned int ptr)
 {
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 	long pgdc = (long)pgd_current;
-
+#endif
 	/*
 	 * The vmalloc handling is not in the hotpath.
 	 */
@@ -506,7 +514,15 @@
 	uasm_il_bltz(p, r, tmp, label_vmalloc);
 	/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
+	/*
+	 * &pgd << 11 stored in CONTEXT [23..63].
+	 */
+	UASM_i_MFC0(p, ptr, C0_CONTEXT);
+	uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */
+	uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0  1 0 1  << 6  xkphys cached */
+	uasm_i_drotr(p, ptr, ptr, 11);
+#elif defined(CONFIG_SMP)
 # ifdef  CONFIG_MIPS_MT_SMTC
 	/*
 	 * SMTC uses TCBind value as "CPU" index
@@ -520,7 +536,7 @@
 	 */
 	uasm_i_dmfc0(p, ptr, C0_CONTEXT);
 	uasm_i_dsrl(p, ptr, ptr, 23);
-#endif
+# endif
 	UASM_i_LA_mostly(p, tmp, pgdc);
 	uasm_i_daddu(p, ptr, ptr, tmp);
 	uasm_i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1033,6 +1049,7 @@
 	iPTE_LW(p, pte, ptr);
 }
 
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 /*
  * R3000 style TLB load/store/modify handlers.
  */
@@ -1184,6 +1201,7 @@
 
 	dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm));
 }
+#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
 /*
  * R4000 style TLB load/store/modify handlers.
@@ -1400,6 +1418,7 @@
 	case CPU_TX3912:
 	case CPU_TX3922:
 	case CPU_TX3927:
+#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
 		build_r3000_tlb_refill_handler();
 		if (!run_once) {
 			build_r3000_tlb_load_handler();
@@ -1407,6 +1426,9 @@
 			build_r3000_tlb_modify_handler();
 			run_once++;
 		}
+#else
+		panic("No R3000 TLB refill handler");
+#endif
 		break;
 
 	case CPU_R6000:
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index f467199..0a165c5 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -60,11 +60,11 @@
 	insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
 	insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0,
 	insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
-	insn_dsrl32, insn_dsubu, insn_eret, insn_j, insn_jal, insn_jr,
-	insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
+	insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal,
+	insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
 	insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
 	insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
-	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori
+	insn_tlbp, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_dins
 };
 
 struct insn {
@@ -104,6 +104,7 @@
 	{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
 	{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
 	{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
+	{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
 	{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
 	{ insn_eret,  M(cop0_op, cop_op, 0, 0, 0, eret_op),  0 },
 	{ insn_j,  M(j_op, 0, 0, 0, 0, 0),  JIMM },
@@ -132,6 +133,7 @@
 	{ insn_tlbwr,  M(cop0_op, cop_op, 0, 0, 0, tlbwr_op),  0 },
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
 	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
+	{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
 	{ insn_invalid, 0, 0 }
 };
 
@@ -304,6 +306,12 @@
 	build_insn(buf, insn##op, b, a, c);		\
 }
 
+#define I_u2u1msbu3(op)					\
+Ip_u2u1msbu3(op)					\
+{							\
+	build_insn(buf, insn##op, b, a, c+d-1, c);	\
+}
+
 #define I_u1u2(op)					\
 Ip_u1u2(op)						\
 {							\
@@ -349,6 +357,7 @@
 I_u2u1u3(_dsra)
 I_u2u1u3(_dsrl)
 I_u2u1u3(_dsrl32)
+I_u2u1u3(_drotr)
 I_u3u1u2(_dsubu)
 I_0(_eret)
 I_u1(_j)
@@ -377,6 +386,7 @@
 I_0(_tlbwr)
 I_u3u1u2(_xor)
 I_u2u1u3(_xori)
+I_u2u1msbu3(_dins);
 
 /* Handle labels. */
 void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
diff --git a/arch/mips/mm/uasm.h b/arch/mips/mm/uasm.h
index c6d1e3d..3d153ed 100644
--- a/arch/mips/mm/uasm.h
+++ b/arch/mips/mm/uasm.h
@@ -34,6 +34,11 @@
 void __cpuinit								\
 uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
+#define Ip_u2u1msbu3(op)						\
+void __cpuinit								\
+uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c,	\
+	   unsigned int d)
+
 #define Ip_u1u2(op)							\
 void __cpuinit uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
 
@@ -65,6 +70,7 @@
 Ip_u2u1u3(_dsra);
 Ip_u2u1u3(_dsrl);
 Ip_u2u1u3(_dsrl32);
+Ip_u2u1u3(_drotr);
 Ip_u3u1u2(_dsubu);
 Ip_0(_eret);
 Ip_u1(_j);
@@ -93,6 +99,7 @@
 Ip_0(_tlbwr);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
+Ip_u2u1msbu3(_dins);
 
 /* Handle labels. */
 struct uasm_label {
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index 9035c64..b27419c 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -55,7 +55,7 @@
 	char *memsize_str;
 	unsigned int memsize;
 	char *ptr;
-	static char cmdline[CL_SIZE] __initdata;
+	static char cmdline[COMMAND_LINE_SIZE] __initdata;
 
 	/* otherwise look in the environment */
 	memsize_str = prom_getenv("memsize");
diff --git a/arch/mips/nxp/pnx833x/common/interrupts.c b/arch/mips/nxp/pnx833x/common/interrupts.c
index 30533ba..3a467c0 100644
--- a/arch/mips/nxp/pnx833x/common/interrupts.c
+++ b/arch/mips/nxp/pnx833x/common/interrupts.c
@@ -295,7 +295,7 @@
 }
 
 static struct irq_chip pnx833x_pic_irq_type = {
-	.typename = "PNX-PIC",
+	.name = "PNX-PIC",
 	.startup = pnx833x_startup_pic_irq,
 	.shutdown = pnx833x_shutdown_pic_irq,
 	.enable = pnx833x_enable_pic_irq,
@@ -305,7 +305,7 @@
 };
 
 static struct irq_chip pnx833x_gpio_irq_type = {
-	.typename = "PNX-GPIO",
+	.name = "PNX-GPIO",
 	.startup = pnx833x_startup_gpio_irq,
 	.shutdown = pnx833x_disable_gpio_irq,
 	.enable = pnx833x_enable_gpio_irq,
diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c
index 575cd14..475ff46 100644
--- a/arch/mips/oprofile/op_model_loongson2.c
+++ b/arch/mips/oprofile/op_model_loongson2.c
@@ -1,7 +1,7 @@
 /*
  * Loongson2 performance counter driver for oprofile
  *
- * Copyright (C) 2009 Lemote Inc. & Insititute of Computing Technology
+ * Copyright (C) 2009 Lemote Inc.
  * Author: Yanhua <yanh@lemote.com>
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
@@ -125,6 +125,9 @@
 	 */
 
 	/* Check whether the irq belongs to me */
+	enabled = read_c0_perfcnt() & LOONGSON2_PERFCNT_INT_EN;
+	if (!enabled)
+		return IRQ_NONE;
 	enabled = reg.cnt1_enabled | reg.cnt2_enabled;
 	if (!enabled)
 		return IRQ_NONE;
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 91bfe73..c9209ca 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -22,13 +22,13 @@
 #
 # These are still pretty much in the old state, watch, go blind.
 #
-obj-$(CONFIG_BASLER_EXCITE)	+= ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
 obj-$(CONFIG_SOC_AU1500)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
-obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-bonito64.o
+obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
+obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
 obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
 obj-$(CONFIG_PMC_MSP7120_EVAL)	+= fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
deleted file mode 100644
index cd64d9f..0000000
--- a/arch/mips/pci/fixup-excite.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/pci.h>
-#include <excite.h>
-
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-	if (pin == 0)
-		return -1;
-
-	return USB_IRQ;		/* USB controller is the only PCI device */
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/fixup-fuloong2e.c b/arch/mips/pci/fixup-fuloong2e.c
index 0c4c7a8..4f6d8da 100644
--- a/arch/mips/pci/fixup-fuloong2e.c
+++ b/arch/mips/pci/fixup-fuloong2e.c
@@ -13,7 +13,8 @@
  */
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <asm/mips-boards/bonito64.h>
+
+#include <loongson.h>
 
 /* South bridge slot number is set by the pci probe process */
 static u8 sb_slot = 5;
@@ -35,7 +36,7 @@
 			break;
 		}
 	} else {
-		irq = BONITO_IRQ_BASE + 25 + pin;
+		irq = LOONGSON_IRQ_BASE + 25 + pin;
 	}
 	return irq;
 
diff --git a/arch/mips/pci/fixup-lemote2f.c b/arch/mips/pci/fixup-lemote2f.c
new file mode 100644
index 0000000..caf2ede
--- /dev/null
+++ b/arch/mips/pci/fixup-lemote2f.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 Lemote Technology
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc.
+ * Author: Fuxin Zhang, zhangfx@lemote.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/init.h>
+#include <linux/pci.h>
+
+#include <loongson.h>
+#include <cs5536/cs5536.h>
+#include <cs5536/cs5536_pci.h>
+
+/* PCI interrupt pins
+ *
+ * These should not be changed, or you should consider loongson2f interrupt
+ * register and your pci card dispatch
+ */
+
+#define PCIA		4
+#define PCIB		5
+#define PCIC		6
+#define PCID		7
+
+/* all the pci device has the PCIA pin, check the datasheet. */
+static char irq_tab[][5] __initdata = {
+	/*      INTA    INTB    INTC    INTD */
+	{0, 0, 0, 0, 0},	/*  11: Unused */
+	{0, 0, 0, 0, 0},	/*  12: Unused */
+	{0, 0, 0, 0, 0},	/*  13: Unused */
+	{0, 0, 0, 0, 0},	/*  14: Unused */
+	{0, 0, 0, 0, 0},	/*  15: Unused */
+	{0, 0, 0, 0, 0},	/*  16: Unused */
+	{0, PCIA, 0, 0, 0},	/*  17: RTL8110-0 */
+	{0, PCIB, 0, 0, 0},	/*  18: RTL8110-1 */
+	{0, PCIC, 0, 0, 0},	/*  19: SiI3114 */
+	{0, PCID, 0, 0, 0},	/*  20: 3-ports nec usb */
+	{0, PCIA, PCIB, PCIC, PCID},	/*  21: PCI-SLOT */
+	{0, 0, 0, 0, 0},	/*  22: Unused */
+	{0, 0, 0, 0, 0},	/*  23: Unused */
+	{0, 0, 0, 0, 0},	/*  24: Unused */
+	{0, 0, 0, 0, 0},	/*  25: Unused */
+	{0, 0, 0, 0, 0},	/*  26: Unused */
+	{0, 0, 0, 0, 0},	/*  27: Unused */
+};
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int virq;
+
+	if ((PCI_SLOT(dev->devfn) != PCI_IDSEL_CS5536)
+	    && (PCI_SLOT(dev->devfn) < 32)) {
+		virq = irq_tab[slot][pin];
+		printk(KERN_INFO "slot: %d, pin: %d, irq: %d\n", slot, pin,
+		       virq + LOONGSON_IRQ_BASE);
+		if (virq != 0)
+			return LOONGSON_IRQ_BASE + virq;
+		else
+			return 0;
+	} else if (PCI_SLOT(dev->devfn) == PCI_IDSEL_CS5536) {	/*  cs5536 */
+		switch (PCI_FUNC(dev->devfn)) {
+		case 2:
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      CS5536_IDE_INTR);
+			return CS5536_IDE_INTR;	/*  for IDE */
+		case 3:
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      CS5536_ACC_INTR);
+			return CS5536_ACC_INTR;	/*  for AUDIO */
+		case 4:	/*  for OHCI */
+		case 5:	/*  for EHCI */
+		case 6:	/*  for UDC */
+		case 7:	/*  for OTG */
+			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					      CS5536_USB_INTR);
+			return CS5536_USB_INTR;
+		}
+		return dev->irq;
+	} else {
+		printk(KERN_INFO " strange pci slot number.\n");
+		return 0;
+	}
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+/* CS5536 SPEC. fixup */
+static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+{
+	/* the uart1 and uart2 interrupt in PIC is enabled as default */
+	pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
+	pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
+}
+
+static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+{
+	/* setting the mutex pin as IDE function */
+	pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
+			       CS5536_IDE_FLASH_SIGNATURE);
+}
+
+static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+{
+	/* enable the AUDIO interrupt in PIC  */
+	pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
+
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
+}
+
+static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+{
+	/* enable the OHCI interrupt in PIC */
+	/* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
+	pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
+}
+
+static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+{
+	u32 hi, lo;
+
+	/* Serial short detect enable */
+	_rdmsr(USB_MSR_REG(USB_CONFIG), &hi, &lo);
+	_wrmsr(USB_MSR_REG(USB_CONFIG), (1 << 1) | (1 << 2) | (1 << 3), lo);
+
+	/* setting the USB2.0 micro frame length */
+	pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
+}
+
+static void __init loongson_nec_fixup(struct pci_dev *pdev)
+{
+	unsigned int val;
+
+	pci_read_config_dword(pdev, 0xe0, &val);
+	/* Only 2 port be used */
+	pci_write_config_dword(pdev, 0xe0, (val & ~3) | 0x2);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA,
+			 loongson_cs5536_isa_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_OHC,
+			 loongson_cs5536_ohci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_EHC,
+			 loongson_cs5536_ehci_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
+			 loongson_cs5536_acc_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE,
+			 loongson_cs5536_ide_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+			 loongson_nec_fixup);
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index 54e55e7..1b3e03f 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,13 +29,8 @@
 #define PCI_ACCESS_READ  0
 #define PCI_ACCESS_WRITE 1
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
-#define ID_SEL_BEGIN 11
-#else
 #define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
 #define ID_SEL_BEGIN 10
-#endif
 #define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
 
 
@@ -77,10 +72,8 @@
 	addrp = CFG_SPACE_REG(addr & 0xffff);
 	if (access_type == PCI_ACCESS_WRITE) {
 		writel(cpu_to_le32(*data), addrp);
-#ifndef CONFIG_LEMOTE_FULOONG2E
 		/* Wait till done */
 		while (BONITO_PCIMSTAT & 0xF);
-#endif
 	} else {
 		*data = le32_to_cpu(readl(addrp));
 	}
diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c
new file mode 100644
index 0000000..aa5d3da
--- /dev/null
+++ b/arch/mips/pci/ops-loongson2.c
@@ -0,0 +1,208 @@
+/*
+ * fuloong2e specific PCI support.
+ *
+ * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
+ *
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin <wuzj@lemote.com>
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <loongson.h>
+
+#ifdef CONFIG_CS5536
+#include <cs5536/cs5536_pci.h>
+#include <cs5536/cs5536.h>
+#endif
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#define CFG_SPACE_REG(offset) \
+	(void *)CKSEG1ADDR(LOONGSON_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
+
+
+static int loongson_pcibios_config_access(unsigned char access_type,
+				      struct pci_bus *bus,
+				      unsigned int devfn, int where,
+				      u32 *data)
+{
+	u32 busnum = bus->number;
+	u32 addr, type;
+	u32 dummy;
+	void *addrp;
+	int device = PCI_SLOT(devfn);
+	int function = PCI_FUNC(devfn);
+	int reg = where & ~3;
+
+	if (busnum == 0) {
+		/* board-specific part,currently,only fuloong2f,yeeloong2f
+		 * use CS5536, fuloong2e use via686b, gdium has no
+		 * south bridge
+		 */
+#ifdef CONFIG_CS5536
+		/* cs5536_pci_conf_read4/write4() will call _rdmsr/_wrmsr() to
+		 * access the regsters PCI_MSR_ADDR, PCI_MSR_DATA_LO,
+		 * PCI_MSR_DATA_HI, which is bigger than PCI_MSR_CTRL, so, it
+		 * will not go this branch, but the others. so, no calling dead
+		 * loop here.
+		 */
+		if ((PCI_IDSEL_CS5536 == device) && (reg < PCI_MSR_CTRL)) {
+			switch (access_type) {
+			case PCI_ACCESS_READ:
+				*data = cs5536_pci_conf_read4(function, reg);
+				break;
+			case PCI_ACCESS_WRITE:
+				cs5536_pci_conf_write4(function, reg, *data);
+				break;
+			}
+			return 0;
+		}
+#endif
+		/* Type 0 configuration for onboard PCI bus */
+		if (device > MAX_DEV_NUM)
+			return -1;
+
+		addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+		type = 0;
+	} else {
+		/* Type 1 configuration for offboard PCI bus */
+		addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+		type = 0x10000;
+	}
+
+	/* Clear aborts */
+	LOONGSON_PCICMD |= LOONGSON_PCICMD_MABORT_CLR | \
+				LOONGSON_PCICMD_MTABORT_CLR;
+
+	LOONGSON_PCIMAP_CFG = (addr >> 16) | type;
+
+	/* Flush Bonito register block */
+	dummy = LOONGSON_PCIMAP_CFG;
+	mmiowb();
+
+	addrp = CFG_SPACE_REG(addr & 0xffff);
+	if (access_type == PCI_ACCESS_WRITE)
+		writel(cpu_to_le32(*data), addrp);
+	else
+		*data = le32_to_cpu(readl(addrp));
+
+	/* Detect Master/Target abort */
+	if (LOONGSON_PCICMD & (LOONGSON_PCICMD_MABORT_CLR |
+			     LOONGSON_PCICMD_MTABORT_CLR)) {
+		/* Error occurred */
+
+		/* Clear bits */
+		LOONGSON_PCICMD |= (LOONGSON_PCICMD_MABORT_CLR |
+				  LOONGSON_PCICMD_MTABORT_CLR);
+
+		return -1;
+	}
+
+	return 0;
+
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int loongson_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+			     int where, int size, u32 *val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
+				       &data))
+		return -1;
+
+	if (size == 1)
+		*val = (data >> ((where & 3) << 3)) & 0xff;
+	else if (size == 2)
+		*val = (data >> ((where & 3) << 3)) & 0xffff;
+	else
+		*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int loongson_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+			      int where, int size, u32 val)
+{
+	u32 data = 0;
+
+	if ((size == 2) && (where & 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	else if ((size == 4) && (where & 3))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (size == 4)
+		data = val;
+	else {
+		if (loongson_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+					where, &data))
+			return -1;
+
+		if (size == 1)
+			data = (data & ~(0xff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+		else if (size == 2)
+			data = (data & ~(0xffff << ((where & 3) << 3))) |
+				(val << ((where & 3) << 3));
+	}
+
+	if (loongson_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
+				       &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops loongson_pci_ops = {
+	.read = loongson_pcibios_read,
+	.write = loongson_pcibios_write
+};
+
+#ifdef CONFIG_CS5536
+void _rdmsr(u32 msr, u32 *hi, u32 *lo)
+{
+	struct pci_bus bus = {
+		.number = PCI_BUS_CS5536
+	};
+	u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+	loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+	loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+	loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_rdmsr);
+
+void _wrmsr(u32 msr, u32 hi, u32 lo)
+{
+	struct pci_bus bus = {
+		.number = PCI_BUS_CS5536
+	};
+	u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
+	loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
+	loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
+	loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
+}
+EXPORT_SYMBOL(_wrmsr);
+#endif
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
deleted file mode 100644
index 8a56876..0000000
--- a/arch/mips/pci/pci-excite.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
- *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/rm9k-ocd.h>
-#include <excite.h>
-
-
-extern struct pci_ops titan_pci_ops;
-
-
-static struct resource
-	mem_resource = 	{
-		.name	= "PCI memory",
-		.start	= EXCITE_PHYS_PCI_MEM,
-		.end	= EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1,
-		.flags	= IORESOURCE_MEM
-	},
-	io_resource = {
-		.name	= "PCI I/O",
-		.start	= EXCITE_PHYS_PCI_IO,
-		.end	= EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1,
-		.flags	= IORESOURCE_IO
-	};
-
-
-static struct pci_controller bx_controller = {
-	.pci_ops	= &titan_pci_ops,
-	.mem_resource	= &mem_resource,
-	.mem_offset	= 0x00000000UL,
-	.io_resource	= &io_resource,
-	.io_offset	= 0x00000000UL
-};
-
-
-static char
-	iopage_failed[] __initdata   = "Cannot allocate PCI I/O page",
-	modebits_no_pci[] __initdata = "PCI is not configured in mode bits";
-
-#define RM9000x2_OCD_HTSC	0x0604
-#define RM9000x2_OCD_HTBHL	0x060c
-#define RM9000x2_OCD_PCIHRST	0x078c
-
-#define RM9K_OCD_MODEBIT1	0x00d4 /* (MODEBIT1) Mode Bit 1 */
-#define RM9K_OCD_CPHDCR		0x00f4 /* CPU-PCI/HT Data Control. */
-
-#define PCISC_FB2B 		0x00000200
-#define PCISC_MWICG		0x00000010
-#define PCISC_EMC		0x00000004
-#define PCISC_ERMA		0x00000002
-
-
-
-static int __init basler_excite_pci_setup(void)
-{
-	const unsigned int fullbars = memsize / (256 << 20);
-	unsigned int i;
-
-	/* Check modebits to see if PCI is really enabled. */
-	if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1))
-		panic(modebits_no_pci);
-
-	if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO,
-				       "Memory-mapped PCI I/O page"))
-		panic(iopage_failed);
-
-	/* Enable PCI 0 as master for config cycles */
-	ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC);
-
-
-	/* Set up latency timer */
-	ocd_writel(0x8008, RM9000x2_OCD_HTBHL);
-
-	/*  Setup host IO and Memory space */
-	ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7);
-	ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7);
-	ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8);
-	ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8);
-
-	/* Set up PCI BARs to map all installed memory */
-	for (i = 0; i < 6; i++) {
-		const unsigned int bar = 0x610 + i * 4;
-
-	     	if (i < fullbars) {
-			ocd_writel(0x10000000 * i, bar);
-			ocd_writel(0x01000000 * i, bar + 0x140);
-			ocd_writel(0x0ffff029, bar + 0x100);
-			continue;
-		}
-
-	     	if (i == fullbars) {
-			int o;
-			u32 mask;
-
-			const unsigned long rem = memsize - i * 0x10000000;
-			if (!rem) {
-				ocd_writel(0x00000000, bar + 0x100);
-				continue;
-			}
-
-			o = ffs(rem) - 1;
-			if (rem & ~(0x1 << o))
-				o++;
-			mask = ((0x1 << o) & 0x0ffff000) - 0x1000;
-			ocd_writel(0x10000000 * i, bar);
-			ocd_writel(0x01000000 * i, bar + 0x140);
-			ocd_writel(0x00000029 | mask, bar + 0x100);
-			continue;
-		}
-
-		ocd_writel(0x00000000, bar + 0x100);
-	}
-
-	/* Finally, enable the PCI interrupt */
-#if USB_IRQ > 7
-	set_c0_intcontrol(1 << USB_IRQ);
-#else
-	set_c0_status(1 << (USB_IRQ + 8));
-#endif
-
-	ioport_resource.start = EXCITE_PHYS_PCI_IO;
-	ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1;
-	set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO));
-	register_pci_controller(&bx_controller);
-	return 0;
-}
-
-
-arch_initcall(basler_excite_pci_setup);
diff --git a/arch/mips/powertv/Kconfig b/arch/mips/powertv/Kconfig
new file mode 100644
index 0000000..ff0e7e3
--- /dev/null
+++ b/arch/mips/powertv/Kconfig
@@ -0,0 +1,21 @@
+source "arch/mips/powertv/asic/Kconfig"
+
+config BOOTLOADER_DRIVER
+	bool "PowerTV Bootloader Driver Support"
+	default n
+	depends on POWERTV
+	help
+	  Use this option if you want to load bootloader driver.
+
+config BOOTLOADER_FAMILY
+	string "POWERTV Bootloader Family string"
+	default "85"
+	depends on POWERTV && !BOOTLOADER_DRIVER
+	help
+	  This value should be specified when the bootloader driver is disabled
+	  and must be exactly two characters long. Families supported are:
+	    R1 - RNG-100  R2 - RNG-200
+	    A1 - Class A  B1 - Class B
+	    E1 - Class E  F1 - Class F
+	    44 - 45xx     46 - 46xx
+	    85 - 85xx     86 - 86xx
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
new file mode 100644
index 0000000..2c51671
--- /dev/null
+++ b/arch/mips/powertv/Makefile
@@ -0,0 +1,28 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+# Portions copyright (C)  2009 Cisco Systems, Inc.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the Cisco PowerTV-specific kernel interface routines
+# under Linux.
+#
+
+obj-y += cmdline.o init.o memory.o reset.o time.o powertv_setup.o asic/ pci/
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/asic/Kconfig b/arch/mips/powertv/asic/Kconfig
new file mode 100644
index 0000000..2016bfe
--- /dev/null
+++ b/arch/mips/powertv/asic/Kconfig
@@ -0,0 +1,28 @@
+config MIN_RUNTIME_RESOURCES
+	bool "Support for minimum runtime resources"
+	default n
+	depends on POWERTV
+	help
+	  Enables support for minimizing the number of (SA asic) runtime
+	  resources that are preallocated by the kernel.
+
+config MIN_RUNTIME_DOCSIS
+	bool "Support for minimum DOCSIS resource"
+	default y
+	depends on MIN_RUNTIME_RESOURCES
+	help
+	  Enables support for the preallocated DOCSIS resource.
+
+config MIN_RUNTIME_PMEM
+	bool "Support for minimum PMEM resource"
+	default y
+	depends on MIN_RUNTIME_RESOURCES
+	help
+	  Enables support for the preallocated Memory resource.
+
+config MIN_RUNTIME_TFTP
+	bool "Support for minimum TFTP resource"
+	default y
+	depends on MIN_RUNTIME_RESOURCES
+	help
+	  Enables support for the preallocated TFTP resource.
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
new file mode 100644
index 0000000..bebfdcf
--- /dev/null
+++ b/arch/mips/powertv/asic/Makefile
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2009  Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+obj-y += asic-calliope.o asic-cronus.o asic-zeus.o asic_devices.o asic_int.o \
+	 irq_asic.o prealloc-calliope.o prealloc-cronus.o \
+	 prealloc-cronuslite.o prealloc-zeus.o
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/asic/asic-calliope.c b/arch/mips/powertv/asic/asic-calliope.c
new file mode 100644
index 0000000..03d3884
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-calliope.c
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Calliope ASIC.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map calliope_register_map = {
+	.eic_slow0_strt_add = 0x800000,
+	.eic_cfg_bits = 0x800038,
+	.eic_ready_status = 0x80004c,
+
+	.chipver3 = 0xA00800,
+	.chipver2 = 0xA00804,
+	.chipver1 = 0xA00808,
+	.chipver0 = 0xA0080c,
+
+	/* The registers of IRBlaster */
+	.uart1_intstat = 0xA01800,
+	.uart1_inten = 0xA01804,
+	.uart1_config1 = 0xA01808,
+	.uart1_config2 = 0xA0180C,
+	.uart1_divisorhi = 0xA01810,
+	.uart1_divisorlo = 0xA01814,
+	.uart1_data = 0xA01818,
+	.uart1_status = 0xA0181C,
+
+	.int_stat_3 = 0xA02800,
+	.int_stat_2 = 0xA02804,
+	.int_stat_1 = 0xA02808,
+	.int_stat_0 = 0xA0280c,
+	.int_config = 0xA02810,
+	.int_int_scan = 0xA02818,
+	.ien_int_3 = 0xA02830,
+	.ien_int_2 = 0xA02834,
+	.ien_int_1 = 0xA02838,
+	.ien_int_0 = 0xA0283c,
+	.int_level_3_3 = 0xA02880,
+	.int_level_3_2 = 0xA02884,
+	.int_level_3_1 = 0xA02888,
+	.int_level_3_0 = 0xA0288c,
+	.int_level_2_3 = 0xA02890,
+	.int_level_2_2 = 0xA02894,
+	.int_level_2_1 = 0xA02898,
+	.int_level_2_0 = 0xA0289c,
+	.int_level_1_3 = 0xA028a0,
+	.int_level_1_2 = 0xA028a4,
+	.int_level_1_1 = 0xA028a8,
+	.int_level_1_0 = 0xA028ac,
+	.int_level_0_3 = 0xA028b0,
+	.int_level_0_2 = 0xA028b4,
+	.int_level_0_1 = 0xA028b8,
+	.int_level_0_0 = 0xA028bc,
+	.int_docsis_en = 0xA028F4,
+
+	.mips_pll_setup = 0x980000,
+	.usb_fs = 0x980030,     	/* -default 72800028- */
+	.test_bus = 0x9800CC,
+	.crt_spare = 0x9800d4,
+	.usb2_ohci_int_mask = 0x9A000c,
+	.usb2_strap = 0x9A0014,
+	.ehci_hcapbase = 0x9BFE00,
+	.ohci_hc_revision = 0x9BFC00,
+	.bcm1_bs_lmi_steer = 0x9E0004,
+	.usb2_control = 0x9E0054,
+	.usb2_stbus_obc = 0x9BFF00,
+	.usb2_stbus_mess_size = 0x9BFF04,
+	.usb2_stbus_chunk_size = 0x9BFF08,
+
+	.pcie_regs = 0x000000,      	/* -doesn't exist- */
+	.tim_ch = 0xA02C10,
+	.tim_cl = 0xA02C14,
+	.gpio_dout = 0xA02c20,
+	.gpio_din = 0xA02c24,
+	.gpio_dir = 0xA02c2C,
+	.watchdog = 0xA02c30,
+	.front_panel = 0x000000,    	/* -not used- */
+};
diff --git a/arch/mips/powertv/asic/asic-cronus.c b/arch/mips/powertv/asic/asic-cronus.c
new file mode 100644
index 0000000..5f4589c
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-cronus.c
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Cronus ASIC
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map cronus_register_map = {
+	.eic_slow0_strt_add = 0x000000,
+	.eic_cfg_bits = 0x000038,
+	.eic_ready_status = 0x00004C,
+
+	.chipver3 = 0x2A0800,
+	.chipver2 = 0x2A0804,
+	.chipver1 = 0x2A0808,
+	.chipver0 = 0x2A080C,
+
+	/* The registers of IRBlaster */
+	.uart1_intstat = 0x2A1800,
+	.uart1_inten = 0x2A1804,
+	.uart1_config1 = 0x2A1808,
+	.uart1_config2 = 0x2A180C,
+	.uart1_divisorhi = 0x2A1810,
+	.uart1_divisorlo = 0x2A1814,
+	.uart1_data = 0x2A1818,
+	.uart1_status = 0x2A181C,
+
+	.int_stat_3 = 0x2A2800,
+	.int_stat_2 = 0x2A2804,
+	.int_stat_1 = 0x2A2808,
+	.int_stat_0 = 0x2A280C,
+	.int_config = 0x2A2810,
+	.int_int_scan = 0x2A2818,
+	.ien_int_3 = 0x2A2830,
+	.ien_int_2 = 0x2A2834,
+	.ien_int_1 = 0x2A2838,
+	.ien_int_0 = 0x2A283C,
+	.int_level_3_3 = 0x2A2880,
+	.int_level_3_2 = 0x2A2884,
+	.int_level_3_1 = 0x2A2888,
+	.int_level_3_0 = 0x2A288C,
+	.int_level_2_3 = 0x2A2890,
+	.int_level_2_2 = 0x2A2894,
+	.int_level_2_1 = 0x2A2898,
+	.int_level_2_0 = 0x2A289C,
+	.int_level_1_3 = 0x2A28A0,
+	.int_level_1_2 = 0x2A28A4,
+	.int_level_1_1 = 0x2A28A8,
+	.int_level_1_0 = 0x2A28AC,
+	.int_level_0_3 = 0x2A28B0,
+	.int_level_0_2 = 0x2A28B4,
+	.int_level_0_1 = 0x2A28B8,
+	.int_level_0_0 = 0x2A28BC,
+	.int_docsis_en = 0x2A28F4,
+
+	.mips_pll_setup = 0x1C0000,
+	.usb_fs = 0x1C0018,
+	.test_bus = 0x1C00CC,
+	.crt_spare = 0x1c00d4,
+	.usb2_ohci_int_mask = 0x20000C,
+	.usb2_strap = 0x200014,
+	.ehci_hcapbase = 0x21FE00,
+	.ohci_hc_revision = 0x1E0000,
+	.bcm1_bs_lmi_steer = 0x2E0008,
+	.usb2_control = 0x2E004C,
+	.usb2_stbus_obc = 0x21FF00,
+	.usb2_stbus_mess_size = 0x21FF04,
+	.usb2_stbus_chunk_size = 0x21FF08,
+
+	.pcie_regs = 0x220000,
+	.tim_ch = 0x2A2C10,
+	.tim_cl = 0x2A2C14,
+	.gpio_dout = 0x2A2C20,
+	.gpio_din = 0x2A2C24,
+	.gpio_dir = 0x2A2C2C,
+	.watchdog = 0x2A2C30,
+	.front_panel = 0x2A3800,
+};
diff --git a/arch/mips/powertv/asic/asic-zeus.c b/arch/mips/powertv/asic/asic-zeus.c
new file mode 100644
index 0000000..1469daa
--- /dev/null
+++ b/arch/mips/powertv/asic/asic-zeus.c
@@ -0,0 +1,98 @@
+/*
+ * Locations of devices in the Zeus ASIC
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ */
+
+#include <asm/mach-powertv/asic.h>
+
+const struct register_map zeus_register_map = {
+	.eic_slow0_strt_add = 0x000000,
+	.eic_cfg_bits = 0x000038,
+	.eic_ready_status = 0x00004c,
+
+	.chipver3 = 0x280800,
+	.chipver2 = 0x280804,
+	.chipver1 = 0x280808,
+	.chipver0 = 0x28080c,
+
+	/* The registers of IRBlaster */
+	.uart1_intstat = 0x281800,
+	.uart1_inten = 0x281804,
+	.uart1_config1 = 0x281808,
+	.uart1_config2 = 0x28180C,
+	.uart1_divisorhi = 0x281810,
+	.uart1_divisorlo = 0x281814,
+	.uart1_data = 0x281818,
+	.uart1_status = 0x28181C,
+
+	.int_stat_3 = 0x282800,
+	.int_stat_2 = 0x282804,
+	.int_stat_1 = 0x282808,
+	.int_stat_0 = 0x28280c,
+	.int_config = 0x282810,
+	.int_int_scan = 0x282818,
+	.ien_int_3 = 0x282830,
+	.ien_int_2 = 0x282834,
+	.ien_int_1 = 0x282838,
+	.ien_int_0 = 0x28283c,
+	.int_level_3_3 = 0x282880,
+	.int_level_3_2 = 0x282884,
+	.int_level_3_1 = 0x282888,
+	.int_level_3_0 = 0x28288c,
+	.int_level_2_3 = 0x282890,
+	.int_level_2_2 = 0x282894,
+	.int_level_2_1 = 0x282898,
+	.int_level_2_0 = 0x28289c,
+	.int_level_1_3 = 0x2828a0,
+	.int_level_1_2 = 0x2828a4,
+	.int_level_1_1 = 0x2828a8,
+	.int_level_1_0 = 0x2828ac,
+	.int_level_0_3 = 0x2828b0,
+	.int_level_0_2 = 0x2828b4,
+	.int_level_0_1 = 0x2828b8,
+	.int_level_0_0 = 0x2828bc,
+	.int_docsis_en = 0x2828F4,
+
+	.mips_pll_setup = 0x1a0000,
+	.usb_fs = 0x1a0018,
+	.test_bus = 0x1a0238,
+	.crt_spare = 0x1a0090,
+	.usb2_ohci_int_mask = 0x1e000c,
+	.usb2_strap = 0x1e0014,
+	.ehci_hcapbase = 0x1FFE00,
+	.ohci_hc_revision = 0x1FFC00,
+	.bcm1_bs_lmi_steer = 0x2C0008,
+	.usb2_control = 0x2c01a0,
+	.usb2_stbus_obc = 0x1FFF00,
+	.usb2_stbus_mess_size = 0x1FFF04,
+	.usb2_stbus_chunk_size = 0x1FFF08,
+
+	.pcie_regs = 0x200000,
+	.tim_ch = 0x282C10,
+	.tim_cl = 0x282C14,
+	.gpio_dout = 0x282c20,
+	.gpio_din = 0x282c24,
+	.gpio_dir = 0x282c2C,
+	.watchdog = 0x282c30,
+	.front_panel = 0x283800,
+};
diff --git a/arch/mips/powertv/asic/asic_devices.c b/arch/mips/powertv/asic/asic_devices.c
new file mode 100644
index 0000000..bae8288
--- /dev/null
+++ b/arch/mips/powertv/asic/asic_devices.c
@@ -0,0 +1,787 @@
+/*
+ *                   ASIC Device List Intialization
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ *
+ * Description:  Defines the platform resources for the SA settop.
+ *
+ * NOTE: The bootloader allocates persistent memory at an address which is
+ * 16 MiB below the end of the highest address in KSEG0. All fixed
+ * address memory reservations must avoid this region.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/resource.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <asm/page.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/mach-powertv/asic.h>
+#include <asm/mach-powertv/asic_regs.h>
+#include <asm/mach-powertv/interrupts.h>
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+#include <asm/mach-powertv/kbldr.h>
+#endif
+#include <asm/bootinfo.h>
+
+#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
+
+/*
+ * Forward Prototypes
+ */
+static void pmem_setup_resource(void);
+
+/*
+ * Global Variables
+ */
+enum asic_type asic;
+
+unsigned int platform_features;
+unsigned int platform_family;
+const struct register_map  *register_map;
+EXPORT_SYMBOL(register_map);			/* Exported for testing */
+unsigned long asic_phy_base;
+unsigned long asic_base;
+EXPORT_SYMBOL(asic_base);			/* Exported for testing */
+struct resource *gp_resources;
+static bool usb_configured;
+
+/*
+ * Don't recommend to use it directly, it is usually used by kernel internally.
+ * Portable code should be using interfaces such as ioremp, dma_map_single, etc.
+ */
+unsigned long phys_to_bus_offset;
+EXPORT_SYMBOL(phys_to_bus_offset);
+
+/*
+ *
+ * IO Resource Definition
+ *
+ */
+
+struct resource asic_resource = {
+	.name  = "ASIC Resource",
+	.start = 0,
+	.end   = ASIC_IO_SIZE,
+	.flags = IORESOURCE_MEM,
+};
+
+/*
+ *
+ * USB Host Resource Definition
+ *
+ */
+
+static struct resource ehci_resources[] = {
+	{
+		.parent = &asic_resource,
+		.start  = 0,
+		.end    = 0xff,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = irq_usbehci,
+		.end    = irq_usbehci,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ehci_device = {
+	.name = "powertv-ehci",
+	.id = 0,
+	.num_resources = 2,
+	.resource = ehci_resources,
+	.dev = {
+		.dma_mask = &ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource ohci_resources[] = {
+	{
+		.parent = &asic_resource,
+		.start  = 0,
+		.end    = 0xff,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = irq_usbohci,
+		.end    = irq_usbohci,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ohci_device = {
+	.name = "powertv-ohci",
+	.id = 0,
+	.num_resources = 2,
+	.resource = ohci_resources,
+	.dev = {
+		.dma_mask = &ohci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+static struct platform_device *platform_devices[] = {
+	&ehci_device,
+	&ohci_device,
+};
+
+/*
+ *
+ * Platform Configuration and Device Initialization
+ *
+ */
+static void __init fs_update(int pe, int md, int sdiv, int disable_div_by_3)
+{
+	int en_prg, byp, pwr, nsb, val;
+	int sout;
+
+	sout = 1;
+	en_prg = 1;
+	byp = 0;
+	nsb = 1;
+	pwr = 1;
+
+	val = ((sdiv << 29) | (md << 24) | (pe<<8) | (sout<<3) | (byp<<2) |
+		(nsb<<1) | (disable_div_by_3<<5));
+
+	asic_write(val, usb_fs);
+	asic_write(val | (en_prg<<4), usb_fs);
+	asic_write(val | (en_prg<<4) | pwr, usb_fs);
+}
+
+/*
+ * Allow override of bootloader-specified model
+ */
+static char __initdata cmdline[COMMAND_LINE_SIZE];
+
+#define	FORCEFAMILY_PARAM	"forcefamily"
+
+static __init int check_forcefamily(unsigned char forced_family[2])
+{
+	const char *p;
+
+	forced_family[0] = '\0';
+	forced_family[1] = '\0';
+
+	/* Check the command line for a forcefamily directive */
+	strncpy(cmdline, arcs_cmdline, COMMAND_LINE_SIZE - 1);
+	p = strstr(cmdline, FORCEFAMILY_PARAM);
+	if (p && (p != cmdline) && (*(p - 1) != ' '))
+		p = strstr(p, " " FORCEFAMILY_PARAM "=");
+
+	if (p) {
+		p += strlen(FORCEFAMILY_PARAM "=");
+
+		if (*p == '\0' || *(p + 1) == '\0' ||
+			(*(p + 2) != '\0' && *(p + 2) != ' '))
+			pr_err(FORCEFAMILY_PARAM " must be exactly two "
+				"characters long, ignoring value\n");
+
+		else {
+			forced_family[0] = *p;
+			forced_family[1] = *(p + 1);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * platform_set_family - determine major platform family type.
+ *
+ * Returns family type; -1 if none
+ * Returns the family type; -1 if none
+ *
+ */
+static __init noinline void platform_set_family(void)
+{
+#define BOOTLDRFAMILY(byte1, byte0) (((byte1) << 8) | (byte0))
+
+	unsigned char forced_family[2];
+	unsigned short bootldr_family;
+
+	check_forcefamily(forced_family);
+
+	if (forced_family[0] != '\0' && forced_family[1] != '\0')
+		bootldr_family = BOOTLDRFAMILY(forced_family[0],
+			forced_family[1]);
+	else {
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+		bootldr_family = (unsigned short) kbldr_GetSWFamily();
+#else
+#if defined(CONFIG_BOOTLOADER_FAMILY)
+		bootldr_family = (unsigned short) BOOTLDRFAMILY(
+			CONFIG_BOOTLOADER_FAMILY[0],
+			CONFIG_BOOTLOADER_FAMILY[1]);
+#else
+#error "Unknown Bootloader Family"
+#endif
+#endif
+	}
+
+	pr_info("Bootloader Family = 0x%04X\n", bootldr_family);
+
+	switch (bootldr_family) {
+	case BOOTLDRFAMILY('R', '1'):
+		platform_family = FAMILY_1500;
+		break;
+	case BOOTLDRFAMILY('4', '4'):
+		platform_family = FAMILY_4500;
+		break;
+	case BOOTLDRFAMILY('4', '6'):
+		platform_family = FAMILY_4600;
+		break;
+	case BOOTLDRFAMILY('A', '1'):
+		platform_family = FAMILY_4600VZA;
+		break;
+	case BOOTLDRFAMILY('8', '5'):
+		platform_family = FAMILY_8500;
+		break;
+	case BOOTLDRFAMILY('R', '2'):
+		platform_family = FAMILY_8500RNG;
+		break;
+	case BOOTLDRFAMILY('8', '6'):
+		platform_family = FAMILY_8600;
+		break;
+	case BOOTLDRFAMILY('B', '1'):
+		platform_family = FAMILY_8600VZB;
+		break;
+	case BOOTLDRFAMILY('E', '1'):
+		platform_family = FAMILY_1500VZE;
+		break;
+	case BOOTLDRFAMILY('F', '1'):
+		platform_family = FAMILY_1500VZF;
+		break;
+	default:
+		platform_family = -1;
+	}
+}
+
+unsigned int platform_get_family(void)
+{
+	return platform_family;
+}
+EXPORT_SYMBOL(platform_get_family);
+
+/*
+ * \brief usb_eye_configure() for optimizing the USB eye on Calliope.
+ *
+ * \param     unsigned int value saved to the register.
+ *
+ * \return    none
+ *
+ */
+static void __init usb_eye_configure(unsigned int value)
+{
+	asic_write(asic_read(crt_spare) | value, crt_spare);
+}
+
+/*
+ * platform_get_asic - determine the ASIC type.
+ *
+ * \param     none
+ *
+ * \return    ASIC type; ASIC_UNKNOWN if none
+ *
+ */
+enum asic_type platform_get_asic(void)
+{
+	return asic;
+}
+EXPORT_SYMBOL(platform_get_asic);
+
+/*
+ * platform_configure_usb - usb configuration based on platform type.
+ * @bcm1_usb2_ctl:	value for the BCM1_USB2_CTL register, which is
+ *			quirky
+ */
+static void __init platform_configure_usb(void)
+{
+	u32 bcm1_usb2_ctl;
+
+	if (usb_configured)
+		return;
+
+	switch (asic) {
+	case ASIC_ZEUS:
+		fs_update(0x0000, 0x11, 0x02, 0);
+		bcm1_usb2_ctl = 0x803;
+		break;
+
+	case ASIC_CRONUS:
+	case ASIC_CRONUSLITE:
+		fs_update(0x0000, 0x11, 0x02, 0);
+		bcm1_usb2_ctl = 0x803;
+		break;
+
+	case ASIC_CALLIOPE:
+		fs_update(0x0000, 0x11, 0x02, 1);
+
+		switch (platform_family) {
+		case FAMILY_1500VZE:
+			break;
+
+		case FAMILY_1500VZF:
+			usb_eye_configure(0x003c0000);
+			break;
+
+		default:
+			usb_eye_configure(0x00300000);
+			break;
+		}
+
+		bcm1_usb2_ctl = 0x803;
+		break;
+
+	default:
+		pr_err("Unknown ASIC type: %d\n", asic);
+		break;
+	}
+
+	/* turn on USB power */
+	asic_write(0, usb2_strap);
+	/* Enable all OHCI interrupts */
+	asic_write(bcm1_usb2_ctl, usb2_control);
+	/* USB2_STBUS_OBC store32/load32 */
+	asic_write(3, usb2_stbus_obc);
+	/* USB2_STBUS_MESS_SIZE 2 packets */
+	asic_write(1, usb2_stbus_mess_size);
+	/* USB2_STBUS_CHUNK_SIZE 2 packets */
+	asic_write(1, usb2_stbus_chunk_size);
+
+	usb_configured = true;
+}
+
+/*
+ * Set up the USB EHCI interface
+ */
+void platform_configure_usb_ehci()
+{
+	platform_configure_usb();
+}
+
+/*
+ * Set up the USB OHCI interface
+ */
+void platform_configure_usb_ohci()
+{
+	platform_configure_usb();
+}
+
+/*
+ * Shut the USB EHCI interface down--currently a NOP
+ */
+void platform_unconfigure_usb_ehci()
+{
+}
+
+/*
+ * Shut the USB OHCI interface down--currently a NOP
+ */
+void platform_unconfigure_usb_ohci()
+{
+}
+
+/**
+ * configure_platform - configuration based on platform type.
+ */
+void __init configure_platform(void)
+{
+	platform_set_family();
+
+	switch (platform_family) {
+	case FAMILY_1500:
+	case FAMILY_1500VZE:
+	case FAMILY_1500VZF:
+		platform_features = FFS_CAPABLE;
+		asic = ASIC_CALLIOPE;
+		asic_phy_base = CALLIOPE_IO_BASE;
+		register_map = &calliope_register_map;
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+
+		if (platform_family == FAMILY_1500VZE) {
+			gp_resources = non_dvr_vze_calliope_resources;
+			pr_info("Platform: 1500/Vz Class E - "
+				"CALLIOPE, NON_DVR_CAPABLE\n");
+		} else if (platform_family == FAMILY_1500VZF) {
+			gp_resources = non_dvr_vzf_calliope_resources;
+			pr_info("Platform: 1500/Vz Class F - "
+				"CALLIOPE, NON_DVR_CAPABLE\n");
+		} else {
+			gp_resources = non_dvr_calliope_resources;
+			pr_info("Platform: 1500/RNG100 - CALLIOPE, "
+				"NON_DVR_CAPABLE\n");
+		}
+		break;
+
+	case FAMILY_4500:
+		platform_features = FFS_CAPABLE | PCIE_CAPABLE |
+			DISPLAY_CAPABLE;
+		asic = ASIC_ZEUS;
+		asic_phy_base = ZEUS_IO_BASE;
+		register_map = &zeus_register_map;
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+		gp_resources = non_dvr_zeus_resources;
+
+		pr_info("Platform: 4500 - ZEUS, NON_DVR_CAPABLE\n");
+		break;
+
+	case FAMILY_4600:
+	{
+		unsigned int chipversion = 0;
+
+		/* The settop has PCIE but it isn't used, so don't advertise
+		 * it*/
+		platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
+		asic_phy_base = CRONUS_IO_BASE;   /* same as Cronus */
+		register_map = &cronus_register_map;   /* same as Cronus */
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+		gp_resources = non_dvr_cronuslite_resources;
+
+		/* ASIC version will determine if this is a real CronusLite or
+		 * Castrati(Cronus) */
+		chipversion  = asic_read(chipver3) << 24;
+		chipversion |= asic_read(chipver2) << 16;
+		chipversion |= asic_read(chipver1) << 8;
+		chipversion |= asic_read(chipver0);
+
+		if ((chipversion == CRONUS_10) || (chipversion == CRONUS_11))
+			asic = ASIC_CRONUS;
+		else
+			asic = ASIC_CRONUSLITE;
+
+		pr_info("Platform: 4600 - %s, NON_DVR_CAPABLE, "
+			"chipversion=0x%08X\n",
+			(asic == ASIC_CRONUS) ? "CRONUS" : "CRONUS LITE",
+			chipversion);
+		break;
+	}
+	case FAMILY_4600VZA:
+		platform_features = FFS_CAPABLE | DISPLAY_CAPABLE;
+		asic = ASIC_CRONUS;
+		asic_phy_base = CRONUS_IO_BASE;
+		register_map = &cronus_register_map;
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+		gp_resources = non_dvr_cronus_resources;
+
+		pr_info("Platform: Vz Class A - CRONUS, NON_DVR_CAPABLE\n");
+		break;
+
+	case FAMILY_8500:
+	case FAMILY_8500RNG:
+		platform_features = DVR_CAPABLE | PCIE_CAPABLE |
+			DISPLAY_CAPABLE;
+		asic = ASIC_ZEUS;
+		asic_phy_base = ZEUS_IO_BASE;
+		register_map = &zeus_register_map;
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+		gp_resources = dvr_zeus_resources;
+
+		pr_info("Platform: 8500/RNG200 - ZEUS, DVR_CAPABLE\n");
+		break;
+
+	case FAMILY_8600:
+	case FAMILY_8600VZB:
+		platform_features = DVR_CAPABLE | PCIE_CAPABLE |
+			DISPLAY_CAPABLE;
+		asic = ASIC_CRONUS;
+		asic_phy_base = CRONUS_IO_BASE;
+		register_map = &cronus_register_map;
+		asic_base = (unsigned long)ioremap_nocache(asic_phy_base,
+			ASIC_IO_SIZE);
+		gp_resources = dvr_cronus_resources;
+
+		pr_info("Platform: 8600/Vz Class B - CRONUS, "
+			"DVR_CAPABLE\n");
+		break;
+
+	default:
+		pr_crit("Platform:  UNKNOWN PLATFORM\n");
+		break;
+	}
+
+	switch (asic) {
+	case ASIC_ZEUS:
+		phys_to_bus_offset = 0x30000000;
+		break;
+	case ASIC_CALLIOPE:
+		phys_to_bus_offset = 0x10000000;
+		break;
+	case ASIC_CRONUSLITE:
+		/* Fall through */
+	case ASIC_CRONUS:
+		/*
+		 * TODO: We suppose 0x10000000 aliases into 0x20000000-
+		 * 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
+		 * 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
+		 */
+		phys_to_bus_offset = 0x10000000;
+		break;
+	default:
+		phys_to_bus_offset = 0x00000000;
+		break;
+	}
+}
+
+/**
+ * platform_devices_init - sets up USB device resourse.
+ */
+static int __init platform_devices_init(void)
+{
+	pr_notice("%s: ----- Initializing USB resources -----\n", __func__);
+
+	asic_resource.start = asic_phy_base;
+	asic_resource.end += asic_resource.start;
+
+	ehci_resources[0].start = asic_reg_phys_addr(ehci_hcapbase);
+	ehci_resources[0].end += ehci_resources[0].start;
+
+	ohci_resources[0].start = asic_reg_phys_addr(ohci_hc_revision);
+	ohci_resources[0].end += ohci_resources[0].start;
+
+	set_io_port_base(0);
+
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+	return 0;
+}
+
+arch_initcall(platform_devices_init);
+
+/*
+ *
+ * BOOTMEM ALLOCATION
+ *
+ */
+/*
+ * Allocates/reserves the Platform memory resources early in the boot process.
+ * This ignores any resources that are designated IORESOURCE_IO
+ */
+void __init platform_alloc_bootmem(void)
+{
+	int i;
+	int total = 0;
+
+	/* Get persistent memory data from command line before allocating
+	 * resources. This need to happen before normal command line parsing
+	 * has been done */
+	pmem_setup_resource();
+
+	/* Loop through looking for resources that want a particular address */
+	for (i = 0; gp_resources[i].flags != 0; i++) {
+		int size = gp_resources[i].end - gp_resources[i].start + 1;
+		if ((gp_resources[i].start != 0) &&
+			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
+			reserve_bootmem(bus_to_phys(gp_resources[i].start),
+				size, 0);
+			total += gp_resources[i].end -
+				gp_resources[i].start + 1;
+			pr_info("reserve resource %s at %08x (%u bytes)\n",
+				gp_resources[i].name, gp_resources[i].start,
+				gp_resources[i].end -
+					gp_resources[i].start + 1);
+		}
+	}
+
+	/* Loop through assigning addresses for those that are left */
+	for (i = 0; gp_resources[i].flags != 0; i++) {
+		int size = gp_resources[i].end - gp_resources[i].start + 1;
+		if ((gp_resources[i].start == 0) &&
+			((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
+			void *mem = alloc_bootmem_pages(size);
+
+			if (mem == NULL)
+				pr_err("Unable to allocate bootmem pages "
+					"for %s\n", gp_resources[i].name);
+
+			else {
+				gp_resources[i].start =
+					phys_to_bus(virt_to_phys(mem));
+				gp_resources[i].end =
+					gp_resources[i].start + size - 1;
+				total += size;
+				pr_info("allocate resource %s at %08x "
+						"(%u bytes)\n",
+					gp_resources[i].name,
+					gp_resources[i].start, size);
+			}
+		}
+	}
+
+	pr_info("Total Platform driver memory allocation: 0x%08x\n", total);
+
+	/* indicate resources that are platform I/O related */
+	for (i = 0; gp_resources[i].flags != 0; i++) {
+		if ((gp_resources[i].start != 0) &&
+			((gp_resources[i].flags & IORESOURCE_IO) != 0)) {
+			pr_info("reserved platform resource %s at %08x\n",
+				gp_resources[i].name, gp_resources[i].start);
+		}
+	}
+}
+
+/*
+ *
+ * PERSISTENT MEMORY (PMEM) CONFIGURATION
+ *
+ */
+static unsigned long pmemaddr __initdata;
+
+static int __init early_param_pmemaddr(char *p)
+{
+	pmemaddr = (unsigned long)simple_strtoul(p, NULL, 0);
+	return 0;
+}
+early_param("pmemaddr", early_param_pmemaddr);
+
+static long pmemlen __initdata;
+
+static int __init early_param_pmemlen(char *p)
+{
+/* TODO: we can use this code when and if the bootloader ever changes this */
+#if 0
+	pmemlen = (unsigned long)simple_strtoul(p, NULL, 0);
+#else
+	pmemlen = 0x20000;
+#endif
+	return 0;
+}
+early_param("pmemlen", early_param_pmemlen);
+
+/*
+ * Set up persistent memory. If we were given values, we patch the array of
+ * resources. Otherwise, persistent memory may be allocated anywhere at all.
+ */
+static void __init pmem_setup_resource(void)
+{
+	struct resource *resource;
+	resource = asic_resource_get("DiagPersistentMemory");
+
+	if (resource && pmemaddr && pmemlen) {
+		/* The address provided by bootloader is in kseg0. Convert to
+		 * a bus address. */
+		resource->start = phys_to_bus(pmemaddr - 0x80000000);
+		resource->end = resource->start + pmemlen - 1;
+
+		pr_info("persistent memory: start=0x%x  end=0x%x\n",
+			resource->start, resource->end);
+	}
+}
+
+/*
+ *
+ * RESOURCE ACCESS FUNCTIONS
+ *
+ */
+
+/**
+ * asic_resource_get - retrieves parameters for a platform resource.
+ * @name:	string to match resource
+ *
+ * Returns a pointer to a struct resource corresponding to the given name.
+ *
+ * CANNOT BE NAMED platform_resource_get, which would be the obvious choice,
+ * as this function name is already declared
+ */
+struct resource *asic_resource_get(const char *name)
+{
+	int i;
+
+	for (i = 0; gp_resources[i].flags != 0; i++) {
+		if (strcmp(gp_resources[i].name, name) == 0)
+			return &gp_resources[i];
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(asic_resource_get);
+
+/**
+ * platform_release_memory - release pre-allocated memory
+ * @ptr:	pointer to memory to release
+ * @size:	size of resource
+ *
+ * This must only be called for memory allocated or reserved via the boot
+ * memory allocator.
+ */
+void platform_release_memory(void *ptr, int size)
+{
+	unsigned long addr;
+	unsigned long end;
+
+	addr = ((unsigned long)ptr + (PAGE_SIZE - 1)) & PAGE_MASK;
+	end = ((unsigned long)ptr + size) & PAGE_MASK;
+
+	for (; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(__va(addr)));
+		init_page_count(virt_to_page(__va(addr)));
+		free_page((unsigned long)__va(addr));
+	}
+}
+EXPORT_SYMBOL(platform_release_memory);
+
+/*
+ *
+ * FEATURE AVAILABILITY FUNCTIONS
+ *
+ */
+int platform_supports_dvr(void)
+{
+	return (platform_features & DVR_CAPABLE) != 0;
+}
+
+int platform_supports_ffs(void)
+{
+	return (platform_features & FFS_CAPABLE) != 0;
+}
+
+int platform_supports_pcie(void)
+{
+	return (platform_features & PCIE_CAPABLE) != 0;
+}
+
+int platform_supports_display(void)
+{
+	return (platform_features & DISPLAY_CAPABLE) != 0;
+}
diff --git a/arch/mips/powertv/asic/asic_int.c b/arch/mips/powertv/asic/asic_int.c
new file mode 100644
index 0000000..80b2eed
--- /dev/null
+++ b/arch/mips/powertv/asic/asic_int.c
@@ -0,0 +1,125 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ * Portions copyright (C) 2009  Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the PowerTV
+ * platform.
+ *
+ * The interrupt controller is located in the South Bridge a PIIX4 device
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+
+#include <asm/irq_cpu.h>
+#include <linux/io.h>
+#include <asm/irq_regs.h>
+#include <asm/mips-boards/generic.h>
+
+#include <asm/mach-powertv/asic_regs.h>
+
+static DEFINE_SPINLOCK(asic_irq_lock);
+
+static inline int get_int(void)
+{
+	unsigned long flags;
+	int irq;
+
+	spin_lock_irqsave(&asic_irq_lock, flags);
+
+	irq = (asic_read(int_int_scan) >> 4) - 1;
+
+	if (irq == 0 || irq >= NR_IRQS)
+		irq = -1;
+
+	spin_unlock_irqrestore(&asic_irq_lock, flags);
+
+	return irq;
+}
+
+static void asic_irqdispatch(void)
+{
+	int irq;
+
+	irq = get_int();
+	if (irq < 0)
+		return;  /* interrupt has already been cleared */
+
+	do_IRQ(irq);
+}
+
+static inline int clz(unsigned long x)
+{
+	__asm__(
+	"	.set	push					\n"
+	"	.set	mips32					\n"
+	"	clz	%0, %1					\n"
+	"	.set	pop					\n"
+	: "=r" (x)
+	: "r" (x));
+
+	return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+	return fls(pending) - 1 + CAUSEB_IP;
+}
+
+/*
+ * TODO: check how it works under EIC mode.
+ */
+asmlinkage void plat_irq_dispatch(void)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+	int irq;
+
+	irq = irq_ffs(pending);
+
+	if (irq == CAUSEF_IP3)
+		asic_irqdispatch();
+	else if (irq >= 0)
+		do_IRQ(irq);
+	else
+		spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+	int i;
+
+	asic_irq_init();
+
+	/*
+	 * Initialize interrupt exception vectors.
+	 */
+	if (cpu_has_veic || cpu_has_vint) {
+		int nvec = cpu_has_veic ? 64 : 8;
+		for (i = 0; i < nvec; i++)
+			set_vi_handler(i, asic_irqdispatch);
+	}
+}
diff --git a/arch/mips/powertv/asic/irq_asic.c b/arch/mips/powertv/asic/irq_asic.c
new file mode 100644
index 0000000..b54d244
--- /dev/null
+++ b/arch/mips/powertv/asic/irq_asic.c
@@ -0,0 +1,116 @@
+/*
+ * Portions copyright (C) 2005-2009 Scientific Atlanta
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ * Modified from arch/mips/kernel/irq-rm7000.c:
+ * Copyright (C) 2003 Ralf Baechle
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/mach-powertv/asic_regs.h>
+
+static inline void unmask_asic_irq(unsigned int irq)
+{
+	unsigned long enable_bit;
+
+	enable_bit = (1 << (irq & 0x1f));
+
+	switch (irq >> 5) {
+	case 0:
+		asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
+		break;
+	case 1:
+		asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
+		break;
+	case 2:
+		asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
+		break;
+	case 3:
+		asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static inline void mask_asic_irq(unsigned int irq)
+{
+	unsigned long disable_mask;
+
+	disable_mask = ~(1 << (irq & 0x1f));
+
+	switch (irq >> 5) {
+	case 0:
+		asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
+		break;
+	case 1:
+		asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
+		break;
+	case 2:
+		asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
+		break;
+	case 3:
+		asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static struct irq_chip asic_irq_chip = {
+	.name = "ASIC Level",
+	.ack = mask_asic_irq,
+	.mask = mask_asic_irq,
+	.mask_ack = mask_asic_irq,
+	.unmask = unmask_asic_irq,
+	.eoi = unmask_asic_irq,
+};
+
+void __init asic_irq_init(void)
+{
+	int i;
+
+	/* set priority to 0 */
+	write_c0_status(read_c0_status() & ~(0x0000fc00));
+
+	asic_write(0, ien_int_0);
+	asic_write(0, ien_int_1);
+	asic_write(0, ien_int_2);
+	asic_write(0, ien_int_3);
+
+	asic_write(0x0fffffff, int_level_3_3);
+	asic_write(0xffffffff, int_level_3_2);
+	asic_write(0xffffffff, int_level_3_1);
+	asic_write(0xffffffff, int_level_3_0);
+	asic_write(0xffffffff, int_level_2_3);
+	asic_write(0xffffffff, int_level_2_2);
+	asic_write(0xffffffff, int_level_2_1);
+	asic_write(0xffffffff, int_level_2_0);
+	asic_write(0xffffffff, int_level_1_3);
+	asic_write(0xffffffff, int_level_1_2);
+	asic_write(0xffffffff, int_level_1_1);
+	asic_write(0xffffffff, int_level_1_0);
+	asic_write(0xffffffff, int_level_0_3);
+	asic_write(0xffffffff, int_level_0_2);
+	asic_write(0xffffffff, int_level_0_1);
+	asic_write(0xffffffff, int_level_0_0);
+
+	asic_write(0xf, int_int_scan);
+
+	/*
+	 * Initialize interrupt handlers.
+	 */
+	for (i = 0; i < NR_IRQS; i++)
+		set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
+}
diff --git a/arch/mips/powertv/asic/prealloc-calliope.c b/arch/mips/powertv/asic/prealloc-calliope.c
new file mode 100644
index 0000000..cd5b76a
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-calliope.c
@@ -0,0 +1,620 @@
+/*
+ * Memory pre-allocations for Calliope boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * NON_DVR_CAPABLE CALLIOPE RESOURCES
+ */
+struct resource non_dvr_calliope_resources[] __initdata =
+{
+	/*
+	 * VIDEO / LX1
+	 */
+	{
+		.name   = "ST231aImage",     	/* Delta-Mu 1 image and ram */
+		.start  = 0x24000000,
+		.end    = 0x24200000 - 1,	/*2MiB */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",   /*8KiB block ST231a monitor */
+		.start  = 0x24200000,
+		.end    = 0x24202000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x24202000,
+		.end    = 0x26700000 - 1, /*~36.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Sysaudio Driver
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * STAVEM driver/STAPI
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x00000000,
+		.end    = 0x00600000 - 1,	/* 6 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DOCSIS Subsystem
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x22000000,
+		.end    = 0x22700000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * GHW HAL Driver
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x22700000,
+		.end    = 0x23500000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * multi com buffer area
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x23700000,
+		.end    = 0x23720000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DMA Ring buffer (don't need recording buffers)
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit0
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,		/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * AVFS: player HAL memory
+	 *
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x00000000,
+		.end    = 0x002c4c00 - 1,	/* 945K * 3 for playback */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * PMEM
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Smartcard
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE + 0x400 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Synopsys GMAC Memory Region
+	 */
+	{
+		.name   = "GMAC",
+		.start  = 0x00000000,
+		.end    = 0x00010000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Add other resources here
+	 *
+	 */
+	{ },
+};
+
+struct resource non_dvr_vz_calliope_resources[] __initdata =
+{
+	/*
+	 * VIDEO / LX1
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x24000000,
+		.end    = 0x24200000 - 1, /*2 Meg */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8k block ST231a monitor */
+		.start  = 0x24200000,
+		.end    = 0x24202000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x22202000,
+		.end    = 0x22C20B85 - 1,	/* 10.12 Meg */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Sysaudio Driver
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * STAVEM driver/STAPI
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x20300000,
+		.end    = 0x20620000-1,  /*3.125 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * GHW HAL Driver
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x20100000,
+		.end    = 0x20300000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * multi com buffer area
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x23900000,
+		.end    = 0x23920000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DMA Ring buffer
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit0
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * PMEM
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Smartcard
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE+0x400 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Synopsys GMAC Memory Region
+	 */
+	{
+		.name   = "GMAC",
+		.start  = 0x00000000,
+		.end    = 0x00010000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
+
+struct resource non_dvr_vze_calliope_resources[] __initdata =
+{
+	/*
+	 * VIDEO / LX1
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x22000000,
+		.end    = 0x22200000 - 1,	/*2  Meg */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8k block ST231a monitor */
+		.start  = 0x22200000,
+		.end    = 0x22202000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x22202000,
+		.end    = 0x22C20B85 - 1,	/* 10.12 Meg */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Sysaudio Driver
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * STAVEM driver/STAPI
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x20396000,
+		.end    = 0x206B6000 - 1,		/* 3.125 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * GHW HAL Driver
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x20100000,
+		.end    = 0x20396000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * multi com buffer area
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x206B6000,
+		.end    = 0x206D6000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DMA Ring buffer
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit0
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * PMEM
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Smartcard
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE+0x400 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Synopsys GMAC Memory Region
+	 */
+	{
+		.name   = "GMAC",
+		.start  = 0x00000000,
+		.end    = 0x00010000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
+
+struct resource non_dvr_vzf_calliope_resources[] __initdata =
+{
+	/*
+	 * VIDEO / LX1
+	 */
+	{
+		.name   = "ST231aImage",	/*Delta-Mu 1 image and ram */
+		.start  = 0x24000000,
+		.end    = 0x24200000 - 1,	/*2MiB */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",	/*8KiB block ST231a monitor */
+		.start  = 0x24200000,
+		.end    = 0x24202000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x24202000,
+		/* ~19.4 (21.5MiB - (2MiB + 8KiB)) */
+		.end    = 0x25580000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Sysaudio Driver
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * STAVEM driver/STAPI
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x00000000,
+		.end    = 0x00480000 - 1,  /* 4.5 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * GHW HAL Driver
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x22700000,
+		.end    = 0x23500000 - 1, /* 14 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * multi com buffer area
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x23700000,
+		.end    = 0x23720000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DMA Ring buffer (don't need recording buffers)
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit0
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,  /* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit1
+	 */
+	{
+		.name   = "DisplayBins1",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,  /* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * AVFS: player HAL memory
+	 *
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x00000000,
+		.end    = 0x002c4c00 - 1,  /* 945K * 3 for playback */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * PMEM
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Smartcard
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE + 0x400 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Synopsys GMAC Memory Region
+	 */
+	{
+		.name   = "GMAC",
+		.start  = 0x00000000,
+		.end    = 0x00010000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
diff --git a/arch/mips/powertv/asic/prealloc-cronus.c b/arch/mips/powertv/asic/prealloc-cronus.c
new file mode 100644
index 0000000..45a5c3e
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-cronus.c
@@ -0,0 +1,608 @@
+/*
+ * Memory pre-allocations for Cronus boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * DVR_CAPABLE CRONUS RESOURCES
+ */
+struct resource dvr_cronus_resources[] __initdata =
+{
+	/*
+	 *
+	 * VIDEO1 / LX1
+	 *
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x24000000,
+		.end    = 0x241FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
+		.start  = 0x24200000,
+		.end    = 0x24201FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x24202000,
+		.end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * VIDEO2 / LX2
+	 *
+	 */
+	{
+		.name   = "ST231bImage",	/* Delta-Mu 2 image and ram */
+		.start  = 0x60000000,
+		.end    = 0x601FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231bMonitor",	/* 8KiB block ST231b monitor */
+		.start  = 0x60200000,
+		.end    = 0x60201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory2",
+		.start  = 0x60202000,
+		.end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * Sysaudio Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  DSP_Image_Buff - DSP code and data images (1MB)
+	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+	 *
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * STAVEM driver/STAPI
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  This memory area is used for allocating buffers for Video decoding
+	 *  purposes.  Allocation/De-allocation within this buffer is managed
+	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
+	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+	 *  video decoding purposes, for any video decoders on Zeus.
+	 *
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x63580000,
+		.end    = 0x64180000 - 1,  /* 12 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * DOCSIS Subsystem
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x62000000,
+		.end    = 0x62700000 - 1,	/* 7 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * GHW HAL Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  GraphicsHeap - PowerTV Graphics Heap
+	 *
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x62700000,
+		.end    = 0x63500000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * multi com buffer area
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x26000000,
+		.end    = 0x26020000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * DMA Ring buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x00280000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer for unit0
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit0
+	 *
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,		/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit1
+	 *
+	 */
+	{
+		.name   = "DisplayBins1",
+		.start  = 0x64AD4000,
+		.end    = 0x64AD5000 - 1,  /* 4 KB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * ITFS
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "ITFS",
+		.start  = 0x64180000,
+		/* 815,104 bytes each for 2 ITFS partitions. */
+		.end    = 0x6430DFFF,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * AVFS
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x6430E000,
+		/* (945K * 8) = (128K *3) 5 playbacks / 3 server */
+		.end    = 0x64AD0000 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "AvfsFileSys",
+		.start  = 0x64AD0000,
+		.end    = 0x64AD1000 - 1,  /* 4K */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * PMEM
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Persistent memory for diagnostics.
+	 *
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Smartcard
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Read and write buffers for Internal/External cards
+	 *
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x64AD1000,
+		.end    = 0x64AD3800 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * KAVNET
+	 *    NP Reset Vector - must be of the form xxCxxxxx
+	 *	   NP Image - must be video bank 1
+	 *	   NP IPC - must be video bank 2
+	 */
+	{
+		.name   = "NP_Reset_Vector",
+		.start  = 0x27c00000,
+		.end    = 0x27c01000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_Image",
+		.start  = 0x27020000,
+		.end    = 0x27060000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_IPC",
+		.start  = 0x63500000,
+		.end    = 0x63580000 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
+
+/*
+ * NON_DVR_CAPABLE CRONUS RESOURCES
+ */
+struct resource non_dvr_cronus_resources[] __initdata =
+{
+	/*
+	 *
+	 * VIDEO1 / LX1
+	 *
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x24000000,
+		.end    = 0x241FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
+		.start  = 0x24200000,
+		.end    = 0x24201FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x24202000,
+		.end    = 0x25FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * VIDEO2 / LX2
+	 *
+	 */
+	{
+		.name   = "ST231bImage",	/* Delta-Mu 2 image and ram */
+		.start  = 0x60000000,
+		.end    = 0x601FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231bMonitor",	/* 8KiB block ST231b monitor */
+		.start  = 0x60200000,
+		.end    = 0x60201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory2",
+		.start  = 0x60202000,
+		.end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * Sysaudio Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  DSP_Image_Buff - DSP code and data images (1MB)
+	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+	 *
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * STAVEM driver/STAPI
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  This memory area is used for allocating buffers for Video decoding
+	 *  purposes.  Allocation/De-allocation within this buffer is managed
+	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
+	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+	 *  video decoding purposes, for any video decoders on Zeus.
+	 *
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x63580000,
+		.end    = 0x64180000 - 1,  /* 12 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * DOCSIS Subsystem
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x62000000,
+		.end    = 0x62700000 - 1,	/* 7 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * GHW HAL Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  GraphicsHeap - PowerTV Graphics Heap
+	 *
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x62700000,
+		.end    = 0x63500000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * multi com buffer area
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x26000000,
+		.end    = 0x26020000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * DMA Ring buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer for unit0
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit0
+	 *
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,		/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit1
+	 *
+	 */
+	{
+		.name   = "DisplayBins1",
+		.start  = 0x64AD4000,
+		.end    = 0x64AD5000 - 1,  /* 4 KB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * AVFS: player HAL memory
+	 *
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x6430E000,
+		.end    = 0x645D2C00 - 1,  /* 945K * 3 for playback */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * PMEM
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Persistent memory for diagnostics.
+	 *
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Smartcard
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Read and write buffers for Internal/External cards
+	 *
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x64AD1000,
+		.end    = 0x64AD3800 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * KAVNET
+	 *    NP Reset Vector - must be of the form xxCxxxxx
+	 *	   NP Image - must be video bank 1
+	 *	   NP IPC - must be video bank 2
+	 */
+	{
+		.name   = "NP_Reset_Vector",
+		.start  = 0x27c00000,
+		.end    = 0x27c01000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_Image",
+		.start  = 0x27020000,
+		.end    = 0x27060000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_IPC",
+		.start  = 0x63500000,
+		.end    = 0x63580000 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	{ },
+};
diff --git a/arch/mips/powertv/asic/prealloc-cronuslite.c b/arch/mips/powertv/asic/prealloc-cronuslite.c
new file mode 100644
index 0000000..23a9056
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-cronuslite.c
@@ -0,0 +1,290 @@
+/*
+ * Memory pre-allocations for Cronus Lite boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * NON_DVR_CAPABLE CRONUSLITE RESOURCES
+ */
+struct resource non_dvr_cronuslite_resources[] __initdata =
+{
+	/*
+	 *
+	 * VIDEO2 / LX2
+	 *
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 2 image and ram */
+		.start  = 0x60000000,
+		.end    = 0x601FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8KiB block ST231b monitor */
+		.start  = 0x60200000,
+		.end    = 0x60201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x60202000,
+		.end    = 0x61FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * Sysaudio Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  DSP_Image_Buff - DSP code and data images (1MB)
+	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+	 *
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * STAVEM driver/STAPI
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  This memory area is used for allocating buffers for Video decoding
+	 *  purposes.  Allocation/De-allocation within this buffer is managed
+	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
+	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+	 *  video decoding purposes, for any video decoders on Zeus.
+	 *
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x63580000,
+		.end    = 0x63B80000 - 1,  /* 6 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * DOCSIS Subsystem
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x62000000,
+		.end    = 0x62700000 - 1,	/* 7 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * GHW HAL Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  GraphicsHeap - PowerTV Graphics Heap
+	 *
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x62700000,
+		.end    = 0x63500000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * multi com buffer area
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x26000000,
+		.end    = 0x26020000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * DMA Ring buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x000AA000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer for unit0
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit0
+	 *
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,		/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit1
+	 *
+	 */
+	{
+		.name   = "DisplayBins1",
+		.start  = 0x63B83000,
+		.end    = 0x63B84000 - 1,  /* 4 KB total */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * AVFS: player HAL memory
+	 *
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x63B84000,
+		.end    = 0x63E48C00 - 1,  /* 945K * 3 for playback */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * PMEM
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Persistent memory for diagnostics.
+	 *
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Smartcard
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Read and write buffers for Internal/External cards
+	 *
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x63B80000,
+		.end    = 0x63B82800 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * KAVNET
+	 *    NP Reset Vector - must be of the form xxCxxxxx
+	 *	   NP Image - must be video bank 1
+	 *	   NP IPC - must be video bank 2
+	 */
+	{
+		.name   = "NP_Reset_Vector",
+		.start  = 0x27c00000,
+		.end    = 0x27c01000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_Image",
+		.start  = 0x27020000,
+		.end    = 0x27060000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "NP_IPC",
+		.start  = 0x63500000,
+		.end    = 0x63580000 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE + 0x400 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
diff --git a/arch/mips/powertv/asic/prealloc-zeus.c b/arch/mips/powertv/asic/prealloc-zeus.c
new file mode 100644
index 0000000..018d451
--- /dev/null
+++ b/arch/mips/powertv/asic/prealloc-zeus.c
@@ -0,0 +1,459 @@
+/*
+ * Memory pre-allocations for Zeus boxes.
+ *
+ * Copyright (C) 2005-2009 Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:       Ken Eppinett
+ *               David Schleef <ds@schleef.org>
+ */
+
+#include <linux/init.h>
+#include <asm/mach-powertv/asic.h>
+
+/*
+ * DVR_CAPABLE RESOURCES
+ */
+struct resource dvr_zeus_resources[] __initdata =
+{
+	/*
+	 *
+	 * VIDEO1 / LX1
+	 *
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x20000000,
+		.end    = 0x201FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
+		.start  = 0x20200000,
+		.end    = 0x20201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x20202000,
+		.end    = 0x21FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * VIDEO2 / LX2
+	 *
+	 */
+	{
+		.name   = "ST231bImage",	/* Delta-Mu 2 image and ram */
+		.start  = 0x30000000,
+		.end    = 0x301FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231bMonitor",	/* 8KiB block ST231b monitor */
+		.start  = 0x30200000,
+		.end    = 0x30201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory2",
+		.start  = 0x30202000,
+		.end    = 0x31FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 *
+	 * Sysaudio Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  DSP_Image_Buff - DSP code and data images (1MB)
+	 *  ADSC_CPU_PCM_Buff - ADSC CPU PCM buffer (40KB)
+	 *  ADSC_AUX_Buff - ADSC AUX buffer (16KB)
+	 *  ADSC_Main_Buff - ADSC Main buffer (16KB)
+	 *
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * STAVEM driver/STAPI
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  This memory area is used for allocating buffers for Video decoding
+	 *  purposes.  Allocation/De-allocation within this buffer is managed
+	 *  by the STAVMEM driver of the STAPI.  They could be Decimated
+	 *  Picture Buffers, Intermediate Buffers, as deemed necessary for
+	 *  video decoding purposes, for any video decoders on Zeus.
+	 *
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x00000000,
+		.end    = 0x00c00000 - 1,	/* 12 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * DOCSIS Subsystem
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x40100000,
+		.end    = 0x407fffff,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * GHW HAL Driver
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  GraphicsHeap - PowerTV Graphics Heap
+	 *
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x46900000,
+		.end    = 0x47700000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * multi com buffer area
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x47900000,
+		.end    = 0x47920000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * DMA Ring buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x00280000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer for unit0
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit0
+	 *
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,	/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Display bins buffer
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Display Bins for unit1
+	 *
+	 */
+	{
+		.name   = "DisplayBins1",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,	/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * ITFS
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "ITFS",
+		.start  = 0x00000000,
+		/* 815,104 bytes each for 2 ITFS partitions. */
+		.end    = 0x0018DFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * AVFS
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Docsis -
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x00000000,
+		/* (945K * 8) = (128K * 3) 5 playbacks / 3 server */
+		.end    = 0x007c2000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "AvfsFileSys",
+		.start  = 0x00000000,
+		.end    = 0x00001000 - 1,  /* 4K */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * PMEM
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Persistent memory for diagnostics.
+	 *
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * Smartcard
+	 *
+	 * This driver requires:
+	 *
+	 * Arbitrary Based Buffers:
+	 *  Read and write buffers for Internal/External cards
+	 *
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
+
+/*
+ * NON_DVR_CAPABLE ZEUS RESOURCES
+ */
+struct resource non_dvr_zeus_resources[] __initdata =
+{
+	/*
+	 * VIDEO1 / LX1
+	 */
+	{
+		.name   = "ST231aImage",	/* Delta-Mu 1 image and ram */
+		.start  = 0x20000000,
+		.end    = 0x201FFFFF,		/* 2MiB */
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "ST231aMonitor",	/* 8KiB block ST231a monitor */
+		.start  = 0x20200000,
+		.end    = 0x20201FFF,
+		.flags  = IORESOURCE_IO,
+	},
+	{
+		.name   = "MediaMemory1",
+		.start  = 0x20202000,
+		.end    = 0x21FFFFFF, /*~29.9MiB (32MiB - (2MiB + 8KiB)) */
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Sysaudio Driver
+	 */
+	{
+		.name   = "DSP_Image_Buff",
+		.start  = 0x00000000,
+		.end    = 0x000FFFFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_CPU_PCM_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00009FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_AUX_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "ADSC_Main_Buff",
+		.start  = 0x00000000,
+		.end    = 0x00003FFF,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * STAVEM driver/STAPI
+	 */
+	{
+		.name   = "AVMEMPartition0",
+		.start  = 0x00000000,
+		.end    = 0x00600000 - 1,	/* 6 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DOCSIS Subsystem
+	 */
+	{
+		.name   = "Docsis",
+		.start  = 0x40100000,
+		.end    = 0x407fffff,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * GHW HAL Driver
+	 */
+	{
+		.name   = "GraphicsHeap",
+		.start  = 0x46900000,
+		.end    = 0x47700000 - 1,	/* 14 MB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * multi com buffer area
+	 */
+	{
+		.name   = "MulticomSHM",
+		.start  = 0x47900000,
+		.end    = 0x47920000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * DMA Ring buffer
+	 */
+	{
+		.name   = "BMM_Buffer",
+		.start  = 0x00000000,
+		.end    = 0x00280000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Display bins buffer for unit0
+	 */
+	{
+		.name   = "DisplayBins0",
+		.start  = 0x00000000,
+		.end    = 0x00000FFF,		/* 4 KB total */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 *
+	 * AVFS: player HAL memory
+	 *
+	 *
+	 */
+	{
+		.name   = "AvfsDmaMem",
+		.start  = 0x00000000,
+		.end    = 0x002c4c00 - 1,	/* 945K * 3 for playback */
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * PMEM
+	 */
+	{
+		.name   = "DiagPersistentMemory",
+		.start  = 0x00000000,
+		.end    = 0x10000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * Smartcard
+	 */
+	{
+		.name   = "SmartCardInfo",
+		.start  = 0x00000000,
+		.end    = 0x2800 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * NAND Flash
+	 */
+	{
+		.name   = "NandFlash",
+		.start  = NAND_FLASH_BASE,
+		.end    = NAND_FLASH_BASE + 0x400 - 1,
+		.flags  = IORESOURCE_IO,
+	},
+	/*
+	 * Add other resources here
+	 */
+	{ },
+};
diff --git a/arch/mips/powertv/cmdline.c b/arch/mips/powertv/cmdline.c
new file mode 100644
index 0000000..98d73cb
--- /dev/null
+++ b/arch/mips/powertv/cmdline.c
@@ -0,0 +1,52 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "init.h"
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+void  __init prom_init_cmdline(void)
+{
+	int len;
+
+	if (prom_argc != 1)
+		return;
+
+	len = strlen(arcs_cmdline);
+
+	arcs_cmdline[len] = ' ';
+
+	strlcpy(arcs_cmdline + len + 1, (char *)_prom_argv,
+		COMMAND_LINE_SIZE - len - 1);
+}
diff --git a/arch/mips/powertv/init.c b/arch/mips/powertv/init.c
new file mode 100644
index 0000000..5f4e4c3
--- /dev/null
+++ b/arch/mips/powertv/init.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
+ *	All rights reserved.
+ *	Authors: Carsten Langgaard <carstenl@mips.com>
+ *		 Maciej W. Rozycki <macro@mips.com>
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/bootinfo.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mach-powertv/asic.h>
+
+#include "init.h"
+
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+unsigned long _prom_memsize;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
+
+char *prom_getenv(char *envname)
+{
+	char *result = NULL;
+
+	if (_prom_envp != NULL) {
+		/*
+		 * Return a pointer to the given environment variable.
+		 * In 64-bit mode: we're using 64-bit pointers, but all pointers
+		 * in the PROM structures are only 32-bit, so we need some
+		 * workarounds, if we are running in 64-bit mode.
+		 */
+		int i, index = 0;
+
+		i = strlen(envname);
+
+		while (prom_envp(index)) {
+			if (strncmp(envname, prom_envp(index), i) == 0) {
+				result = prom_envp(index + 1);
+				break;
+			}
+			index += 2;
+		}
+	}
+
+	return result;
+}
+
+/* TODO: Verify on linux-mips mailing list that the following two  */
+/* functions are correct                                           */
+/* TODO: Copy NMI and EJTAG exception vectors to memory from the   */
+/* BootROM exception vectors. Flush their cache entries. test it.  */
+
+static void __init mips_nmi_setup(void)
+{
+	void *base;
+#if defined(CONFIG_CPU_MIPS32_R1)
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa80) :
+		(void *)(CAC_BASE + 0x380);
+#elif defined(CONFIG_CPU_MIPS32_R2)
+	base = (void *)0xbfc00000;
+#else
+#error NMI exception handler address not defined
+#endif
+}
+
+static void __init mips_ejtag_setup(void)
+{
+	void *base;
+
+#if defined(CONFIG_CPU_MIPS32_R1)
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa00) :
+		(void *)(CAC_BASE + 0x300);
+#elif defined(CONFIG_CPU_MIPS32_R2)
+	base = (void *)0xbfc00480;
+#else
+#error EJTAG exception handler address not defined
+#endif
+}
+
+void __init prom_init(void)
+{
+	prom_argc = fw_arg0;
+	_prom_argv = (int *) fw_arg1;
+	_prom_envp = (int *) fw_arg2;
+	_prom_memsize = (unsigned long) fw_arg3;
+
+	board_nmi_handler_setup = mips_nmi_setup;
+	board_ejtag_handler_setup = mips_ejtag_setup;
+
+	pr_info("\nLINUX started...\n");
+	prom_init_cmdline();
+	configure_platform();
+	prom_meminit();
+
+#ifndef CONFIG_BOOTLOADER_DRIVER
+	pr_info("\nBootloader driver isn't loaded...\n");
+#endif
+}
diff --git a/arch/mips/powertv/init.h b/arch/mips/powertv/init.h
new file mode 100644
index 0000000..7af6bf2
--- /dev/null
+++ b/arch/mips/powertv/init.h
@@ -0,0 +1,28 @@
+/*
+ * Definitions from powertv init.c file
+ *
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_INIT_H
+#define _POWERTV_INIT_H
+extern int prom_argc;
+extern int *_prom_argv;
+extern unsigned long _prom_memsize;
+#endif
diff --git a/arch/mips/powertv/memory.c b/arch/mips/powertv/memory.c
new file mode 100644
index 0000000..28d0660
--- /dev/null
+++ b/arch/mips/powertv/memory.c
@@ -0,0 +1,186 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Apparently originally from arch/mips/malta-memory.c. Modified to work
+ * with the PowerTV bootloader.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/pfn.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mips-boards/prom.h>
+
+#include "init.h"
+
+/* Memory constants */
+#define KIBIBYTE(n)		((n) * 1024)	/* Number of kibibytes */
+#define MEBIBYTE(n)		((n) * KIBIBYTE(1024)) /* Number of mebibytes */
+#define DEFAULT_MEMSIZE		MEBIBYTE(256)	/* If no memsize provided */
+#define LOW_MEM_MAX		MEBIBYTE(252)	/* Max usable low mem */
+#define RES_BOOTLDR_MEMSIZE	MEBIBYTE(1)	/* Memory reserved for bldr */
+#define BOOT_MEM_SIZE		KIBIBYTE(256)	/* Memory reserved for bldr */
+#define PHYS_MEM_START		0x10000000	/* Start of physical memory */
+
+unsigned long ptv_memsize;
+
+char __initdata cmdline[COMMAND_LINE_SIZE];
+
+void __init prom_meminit(void)
+{
+	char *memsize_str;
+	unsigned long memsize = 0;
+	unsigned int physend;
+	char *ptr;
+	int low_mem;
+	int high_mem;
+
+	/* Check the command line first for a memsize directive */
+	strcpy(cmdline, arcs_cmdline);
+	ptr = strstr(cmdline, "memsize=");
+	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
+		ptr = strstr(ptr, " memsize=");
+
+	if (ptr) {
+		memsize = memparse(ptr + 8, &ptr);
+	} else {
+		/* otherwise look in the environment */
+		memsize_str = prom_getenv("memsize");
+
+		if (memsize_str != NULL) {
+			pr_info("prom memsize = %s\n", memsize_str);
+			memsize = simple_strtol(memsize_str, NULL, 0);
+		}
+
+		if (memsize == 0) {
+			if (_prom_memsize != 0) {
+				memsize = _prom_memsize;
+				pr_info("_prom_memsize = 0x%lx\n", memsize);
+				/* add in memory that the bootloader doesn't
+				 * report */
+				memsize += BOOT_MEM_SIZE;
+			} else {
+				memsize = DEFAULT_MEMSIZE;
+				pr_info("Memsize not passed by bootloader, "
+					"defaulting to 0x%lx\n", memsize);
+			}
+		}
+	}
+
+	/* Store memsize for diagnostic purposes */
+	ptv_memsize = memsize;
+
+	physend = PFN_ALIGN(&_end) - 0x80000000;
+	if (memsize > LOW_MEM_MAX) {
+		low_mem = LOW_MEM_MAX;
+		high_mem = memsize - low_mem;
+	} else {
+		low_mem = memsize;
+		high_mem = 0;
+	}
+
+/*
+ * TODO: We will use the hard code for memory configuration until
+ * the bootloader releases their device tree to us.
+ */
+	/*
+	 * Add the memory reserved for use by the bootloader to the
+	 * memory map.
+	 */
+	add_memory_region(PHYS_MEM_START, RES_BOOTLDR_MEMSIZE,
+		BOOT_MEM_RESERVED);
+#ifdef CONFIG_HIGHMEM_256_128
+	/*
+	 * Add memory in low for general use by the kernel and its friends
+	 * (like drivers, applications, etc).
+	 */
+	add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+		LOW_MEM_MAX - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+	/*
+	 * Add the memory reserved for reset vector.
+	 */
+	add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED);
+	/*
+	 * Add the memory reserved.
+	 */
+	add_memory_region(0x20000000, MEBIBYTE(1024 + 75), BOOT_MEM_RESERVED);
+	/*
+	 * Add memory in high for general use by the kernel and its friends
+	 * (like drivers, applications, etc).
+	 *
+	 * 75MB is reserved for devices which are using the memory in high.
+	 */
+	add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75),
+		BOOT_MEM_RAM);
+#elif defined CONFIG_HIGHMEM_128_128
+	/*
+	 * Add memory in low for general use by the kernel and its friends
+	 * (like drivers, applications, etc).
+	 */
+	add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+		MEBIBYTE(128) - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+	/*
+	 * Add the memory reserved.
+	 */
+	add_memory_region(PHYS_MEM_START + MEBIBYTE(128),
+		MEBIBYTE(128 + 1024 + 75), BOOT_MEM_RESERVED);
+	/*
+	 * Add memory in high for general use by the kernel and its friends
+	 * (like drivers, applications, etc).
+	 *
+	 * 75MB is reserved for devices which are using the memory in high.
+	 */
+	add_memory_region(0x60000000 + MEBIBYTE(75), MEBIBYTE(128 - 75),
+		BOOT_MEM_RAM);
+#else
+	/* Add low memory regions for either:
+	 *   - no-highmemory configuration case -OR-
+	 *   - highmemory "HIGHMEM_LOWBANK_ONLY" case
+	 */
+	/*
+	 * Add memory for general use by the kernel and its friends
+	 * (like drivers, applications, etc).
+	 */
+	add_memory_region(PHYS_MEM_START + RES_BOOTLDR_MEMSIZE,
+		low_mem - RES_BOOTLDR_MEMSIZE, BOOT_MEM_RAM);
+	/*
+	 * Add the memory reserved for reset vector.
+	 */
+	add_memory_region(0x1fc00000, MEBIBYTE(4), BOOT_MEM_RESERVED);
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+	unsigned long addr;
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		free_init_pages("prom memory",
+				addr, addr + boot_mem_map.map[i].size);
+	}
+}
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
new file mode 100644
index 0000000..f5c6246
--- /dev/null
+++ b/arch/mips/powertv/pci/Makefile
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2009  Scientific-Atlanta, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+obj-$(CONFIG_PCI)	+= fixup-powertv.o
+
+EXTRA_CFLAGS += -Wall -Werror
diff --git a/arch/mips/powertv/pci/fixup-powertv.c b/arch/mips/powertv/pci/fixup-powertv.c
new file mode 100644
index 0000000..726bc2e
--- /dev/null
+++ b/arch/mips/powertv/pci/fixup-powertv.c
@@ -0,0 +1,36 @@
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mach-powertv/interrupts.h>
+#include "powertv-pci.h"
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return asic_pcie_map_irq(dev, slot, pin);
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
+
+/*
+ * asic_pcie_map_irq
+ *
+ * Parameters:
+ * *dev - pointer to a pci_dev structure  (not used)
+ * slot - slot number  (not used)
+ * pin - pin number  (not used)
+ *
+ * Return Value:
+ * Returns: IRQ number (always the PCI Express IRQ number)
+ *
+ * Description:
+ * asic_pcie_map_irq will return the IRQ number of the PCI Express interrupt.
+ *
+ */
+int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_pciexp;
+}
+EXPORT_SYMBOL(asic_pcie_map_irq);
diff --git a/arch/mips/powertv/pci/powertv-pci.h b/arch/mips/powertv/pci/powertv-pci.h
new file mode 100644
index 0000000..1b5886b
--- /dev/null
+++ b/arch/mips/powertv/pci/powertv-pci.h
@@ -0,0 +1,31 @@
+/*
+ *				powertv-pci.c
+ *
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/*
+ * Local definitions for the powertv PCI code
+ */
+
+#ifndef _POWERTV_PCI_POWERTV_PCI_H_
+#define _POWERTV_PCI_POWERTV_PCI_H_
+extern int asic_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
+extern int asic_pcie_init(void);
+extern int asic_pcie_init(void);
+
+extern int log_level;
+#endif
diff --git a/arch/mips/powertv/powertv-clock.h b/arch/mips/powertv/powertv-clock.h
new file mode 100644
index 0000000..d94c543
--- /dev/null
+++ b/arch/mips/powertv/powertv-clock.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_POWERTV_CLOCK_H
+#define _POWERTV_POWERTV_CLOCK_H
+extern int powertv_clockevent_init(void);
+extern void powertv_clocksource_init(void);
+extern unsigned int mips_get_pll_freq(void);
+#endif
diff --git a/arch/mips/powertv/powertv_setup.c b/arch/mips/powertv/powertv_setup.c
new file mode 100644
index 0000000..bd8ebf1
--- /dev/null
+++ b/arch/mips/powertv/powertv_setup.c
@@ -0,0 +1,351 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/screen_info.h>
+#include <linux/notifier.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/ctype.h>
+
+#include <linux/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/dma.h>
+#include <linux/time.h>
+#include <asm/traps.h>
+#include <asm/asm-offsets.h>
+#include "reset.h"
+
+#define VAL(n)		STR(n)
+
+/*
+ * Macros for loading addresses and storing registers:
+ * PTR_LA	Load the address into a register
+ * LONG_S	Store the full width of the given register.
+ * LONG_L	Load the full width of the given register
+ * PTR_ADDIU	Add a constant value to a register used as a pointer
+ * REG_SIZE	Number of 8-bit bytes in a full width register
+ */
+#ifdef CONFIG_64BIT
+#warning TODO: 64-bit code needs to be verified
+#define PTR_LA		"dla	"
+#define LONG_S		"sd	"
+#define LONG_L		"ld	"
+#define PTR_ADDIU	"daddiu	"
+#define REG_SIZE	"8"		/* In bytes */
+#endif
+
+#ifdef CONFIG_32BIT
+#define PTR_LA		"la	"
+#define LONG_S		"sw	"
+#define LONG_L		"lw	"
+#define PTR_ADDIU	"addiu	"
+#define REG_SIZE	"4"		/* In bytes */
+#endif
+
+static struct pt_regs die_regs;
+static bool have_die_regs;
+
+static void register_panic_notifier(void);
+static int panic_handler(struct notifier_block *notifier_block,
+	unsigned long event, void *cause_string);
+
+const char *get_system_type(void)
+{
+	return "PowerTV";
+}
+
+void __init plat_mem_setup(void)
+{
+	panic_on_oops = 1;
+	register_panic_notifier();
+
+#if 0
+	mips_pcibios_init();
+#endif
+	mips_reboot_setup();
+}
+
+/*
+ * Install a panic notifier for platform-specific diagnostics
+ */
+static void register_panic_notifier()
+{
+	static struct notifier_block panic_notifier = {
+		.notifier_call = panic_handler,
+		.next = NULL,
+		.priority	= INT_MAX
+	};
+	atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier);
+}
+
+static int panic_handler(struct notifier_block *notifier_block,
+	unsigned long event, void *cause_string)
+{
+	struct pt_regs	my_regs;
+
+	/* Save all of the registers */
+	{
+		unsigned long	at, v0, v1; /* Must be on the stack */
+
+		/* Start by saving $at and v0 on the stack. We use $at
+		 * ourselves, but it looks like the compiler may use v0 or v1
+		 * to load the address of the pt_regs structure. We'll come
+		 * back later to store the registers in the pt_regs
+		 * structure. */
+		__asm__ __volatile__ (
+			".set	noat\n"
+			LONG_S		"$at, %[at]\n"
+			LONG_S		"$2, %[v0]\n"
+			LONG_S		"$3, %[v1]\n"
+		:
+			[at] "=m" (at),
+			[v0] "=m" (v0),
+			[v1] "=m" (v1)
+		:
+		:	"at"
+		);
+
+		__asm__ __volatile__ (
+			".set	noat\n"
+			"move		$at, %[pt_regs]\n"
+
+			/* Argument registers */
+			LONG_S		"$4, " VAL(PT_R4) "($at)\n"
+			LONG_S		"$5, " VAL(PT_R5) "($at)\n"
+			LONG_S		"$6, " VAL(PT_R6) "($at)\n"
+			LONG_S		"$7, " VAL(PT_R7) "($at)\n"
+
+			/* Temporary regs */
+			LONG_S		"$8, " VAL(PT_R8) "($at)\n"
+			LONG_S		"$9, " VAL(PT_R9) "($at)\n"
+			LONG_S		"$10, " VAL(PT_R10) "($at)\n"
+			LONG_S		"$11, " VAL(PT_R11) "($at)\n"
+			LONG_S		"$12, " VAL(PT_R12) "($at)\n"
+			LONG_S		"$13, " VAL(PT_R13) "($at)\n"
+			LONG_S		"$14, " VAL(PT_R14) "($at)\n"
+			LONG_S		"$15, " VAL(PT_R15) "($at)\n"
+
+			/* "Saved" registers */
+			LONG_S		"$16, " VAL(PT_R16) "($at)\n"
+			LONG_S		"$17, " VAL(PT_R17) "($at)\n"
+			LONG_S		"$18, " VAL(PT_R18) "($at)\n"
+			LONG_S		"$19, " VAL(PT_R19) "($at)\n"
+			LONG_S		"$20, " VAL(PT_R20) "($at)\n"
+			LONG_S		"$21, " VAL(PT_R21) "($at)\n"
+			LONG_S		"$22, " VAL(PT_R22) "($at)\n"
+			LONG_S		"$23, " VAL(PT_R23) "($at)\n"
+
+			/* Add'l temp regs */
+			LONG_S		"$24, " VAL(PT_R24) "($at)\n"
+			LONG_S		"$25, " VAL(PT_R25) "($at)\n"
+
+			/* Kernel temp regs */
+			LONG_S		"$26, " VAL(PT_R26) "($at)\n"
+			LONG_S		"$27, " VAL(PT_R27) "($at)\n"
+
+			/* Global pointer, stack pointer, frame pointer and
+			 * return address */
+			LONG_S		"$gp, " VAL(PT_R28) "($at)\n"
+			LONG_S		"$sp, " VAL(PT_R29) "($at)\n"
+			LONG_S		"$fp, " VAL(PT_R30) "($at)\n"
+			LONG_S		"$ra, " VAL(PT_R31) "($at)\n"
+
+			/* Now we can get the $at and v0 registers back and
+			 * store them */
+			LONG_L		"$8, %[at]\n"
+			LONG_S		"$8, " VAL(PT_R1) "($at)\n"
+			LONG_L		"$8, %[v0]\n"
+			LONG_S		"$8, " VAL(PT_R2) "($at)\n"
+			LONG_L		"$8, %[v1]\n"
+			LONG_S		"$8, " VAL(PT_R3) "($at)\n"
+		:
+		:
+			[at] "m" (at),
+			[v0] "m" (v0),
+			[v1] "m" (v1),
+			[pt_regs] "r" (&my_regs)
+		:	"at", "t0"
+		);
+
+		/* Set the current EPC value to be the current location in this
+		 * function */
+		__asm__ __volatile__ (
+			".set	noat\n"
+		"1:\n"
+			PTR_LA		"$at, 1b\n"
+			LONG_S		"$at, %[cp0_epc]\n"
+		:
+			[cp0_epc] "=m" (my_regs.cp0_epc)
+		:
+		:	"at"
+		);
+
+		my_regs.cp0_cause = read_c0_cause();
+		my_regs.cp0_status = read_c0_status();
+	}
+
+#ifdef CONFIG_DIAGNOSTICS
+	failure_report((char *) cause_string,
+		have_die_regs ? &die_regs : &my_regs);
+	have_die_regs = false;
+#else
+	pr_crit("I'm feeling a bit sleepy. hmmmmm... perhaps a nap would... "
+		"zzzz... \n");
+#endif
+
+	return NOTIFY_DONE;
+}
+
+/**
+ * Platform-specific handling of oops
+ * @str:	Pointer to the oops string
+ * @regs:	Pointer to the oops registers
+ * All we do here is to save the registers for subsequent printing through
+ * the panic notifier.
+ */
+void platform_die(const char *str, const struct pt_regs *regs)
+{
+	/* If we already have saved registers, don't overwrite them as they
+	 * they apply to the initial fault */
+
+	if (!have_die_regs) {
+		have_die_regs = true;
+		die_regs = *regs;
+	}
+}
+
+/* Information about the RF MAC address, if one was supplied on the
+ * command line. */
+static bool have_rfmac;
+static u8 rfmac[ETH_ALEN];
+
+static int rfmac_param(char *p)
+{
+	u8	*q;
+	bool	is_high_nibble;
+	int	c;
+
+	/* Skip a leading "0x", if present */
+	if (*p == '0' && *(p+1) == 'x')
+		p += 2;
+
+	q = rfmac;
+	is_high_nibble = true;
+
+	for (c = (unsigned char) *p++;
+		isxdigit(c) && q - rfmac < ETH_ALEN;
+		c = (unsigned char) *p++) {
+		int	nibble;
+
+		nibble = (isdigit(c) ? (c - '0') :
+			(isupper(c) ? c - 'A' + 10 : c - 'a' + 10));
+
+		if (is_high_nibble)
+			*q = nibble << 4;
+		else
+			*q++ |= nibble;
+
+		is_high_nibble = !is_high_nibble;
+	}
+
+	/* If we parsed all the way to the end of the parameter value and
+	 * parsed all ETH_ALEN bytes, we have a usable RF MAC address */
+	have_rfmac = (c == '\0' && q - rfmac == ETH_ALEN);
+
+	return 0;
+}
+
+early_param("rfmac", rfmac_param);
+
+/*
+ * Generate an Ethernet MAC address that has a good chance of being unique.
+ * @addr:	Pointer to six-byte array containing the Ethernet address
+ * Generates an Ethernet MAC address that is highly likely to be unique for
+ * this particular system on a network with other systems of the same type.
+ *
+ * The problem we are solving is that, when random_ether_addr() is used to
+ * generate MAC addresses at startup, there isn't much entropy for the random
+ * number generator to use and the addresses it produces are fairly likely to
+ * be the same as those of other identical systems on the same local network.
+ * This is true even for relatively small numbers of systems (for the reason
+ * why, see the Wikipedia entry for "Birthday problem" at:
+ *	http://en.wikipedia.org/wiki/Birthday_problem
+ *
+ * The good news is that we already have a MAC address known to be unique, the
+ * RF MAC address. The bad news is that this address is already in use on the
+ * RF interface. Worse, the obvious trick, taking the RF MAC address and
+ * turning on the locally managed bit, has already been used for other devices.
+ * Still, this does give us something to work with.
+ *
+ * The approach we take is:
+ * 1.	If we can't get the RF MAC Address, just call random_ether_addr.
+ * 2.	Use the 24-bit NIC-specific bits of the RF MAC address as the last 24
+ *	bits of the new address. This is very likely to be unique, except for
+ *	the current box.
+ * 3.	To avoid using addresses already on the current box, we set the top
+ *	six bits of the address with a value different from any currently
+ *	registered Scientific Atlanta organizationally unique identifyer
+ *	(OUI). This avoids duplication with any addresses on the system that
+ *	were generated from valid Scientific Atlanta-registered address by
+ *	simply flipping the locally managed bit.
+ * 4.	We aren't generating a multicast address, so we leave the multicast
+ *	bit off. Since we aren't using a registered address, we have to set
+ *	the locally managed bit.
+ * 5.	We then randomly generate the remaining 16-bits. This does two
+ *	things:
+ *	a.	It allows us to call this function for more than one device
+ *		in this system
+ *	b.	It ensures that things will probably still work even if
+ *		some device on the device network has a locally managed
+ *		address that matches the top six bits from step 2.
+ */
+void platform_random_ether_addr(u8 addr[ETH_ALEN])
+{
+	const int num_random_bytes = 2;
+	const unsigned char non_sciatl_oui_bits = 0xc0u;
+	const unsigned char mac_addr_locally_managed = (1 << 1);
+
+	if (!have_rfmac) {
+		pr_warning("rfmac not available on command line; "
+			"generating random MAC address\n");
+		random_ether_addr(addr);
+	}
+
+	else {
+		int	i;
+
+		/* Set the first byte to something that won't match a Scientific
+		 * Atlanta OUI, is locally managed, and isn't a multicast
+		 * address */
+		addr[0] = non_sciatl_oui_bits | mac_addr_locally_managed;
+
+		/* Get some bytes of random address information */
+		get_random_bytes(&addr[1], num_random_bytes);
+
+		/* Copy over the NIC-specific bits of the RF MAC address */
+		for (i = 1 + num_random_bytes; i < ETH_ALEN; i++)
+			addr[i] = rfmac[i];
+	}
+}
diff --git a/arch/mips/powertv/reset.c b/arch/mips/powertv/reset.c
new file mode 100644
index 0000000..494c652
--- /dev/null
+++ b/arch/mips/powertv/reset.c
@@ -0,0 +1,65 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/pm.h>
+
+#include <linux/io.h>
+#include <asm/reboot.h>			/* Not included by linux/reboot.h */
+
+#ifdef CONFIG_BOOTLOADER_DRIVER
+#include <asm/mach-powertv/kbldr.h>
+#endif
+
+#include <asm/mach-powertv/asic_regs.h>
+#include "reset.h"
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+
+static void mips_machine_restart(char *command)
+{
+#ifdef CONFIG_BOOTLOADER_DRIVER
+	/*
+	 * Call the bootloader's reset function to ensure
+	 * that persistent data is flushed before hard reset
+	 */
+	kbldr_SetCauseAndReset();
+#else
+	writel(0x1, asic_reg_addr(watchdog));
+#endif
+}
+
+static void mips_machine_halt(void)
+{
+#ifdef CONFIG_BOOTLOADER_DRIVER
+	/*
+	 * Call the bootloader's reset function to ensure
+	 * that persistent data is flushed before hard reset
+	 */
+	kbldr_SetCauseAndReset();
+#else
+	writel(0x1, asic_reg_addr(watchdog));
+#endif
+}
+
+void mips_reboot_setup(void)
+{
+	_machine_restart = mips_machine_restart;
+	_machine_halt = mips_machine_halt;
+	pm_power_off = mips_machine_halt;
+}
diff --git a/arch/mips/powertv/reset.h b/arch/mips/powertv/reset.h
new file mode 100644
index 0000000..888fd09
--- /dev/null
+++ b/arch/mips/powertv/reset.h
@@ -0,0 +1,26 @@
+/*
+ * Definitions from powertv reset.c file
+ *
+ * Copyright (C) 2009  Cisco Systems, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Author: David VomLehn
+ */
+
+#ifndef _POWERTV_POWERTV_RESET_H
+#define _POWERTV_POWERTV_RESET_H
+extern void mips_reboot_setup(void);
+#endif
diff --git a/arch/mips/mipssim/sim_cmdline.c b/arch/mips/powertv/time.c
similarity index 60%
rename from arch/mips/mipssim/sim_cmdline.c
rename to arch/mips/powertv/time.c
index 74240e1..1e0a5ef 100644
--- a/arch/mips/mipssim/sim_cmdline.c
+++ b/arch/mips/powertv/time.c
@@ -1,5 +1,7 @@
 /*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Portions copyright (C) 2009 Cisco Systems, Inc.
  *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
@@ -14,19 +16,22 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * Setting up the clock on the MIPS boards.
  */
+
 #include <linux/init.h>
-#include <linux/string.h>
-#include <asm/bootinfo.h>
+#include <asm/mach-powertv/interrupts.h>
+#include <asm/time.h>
 
-extern char arcs_cmdline[];
+#include "powertv-clock.h"
 
-char * __init prom_getcmdline(void)
+unsigned int __cpuinit get_c0_compare_int(void)
 {
-	return arcs_cmdline;
+	return irq_mips_timer;
 }
 
-void  __init prom_init_cmdline(void)
+void __init plat_time_init(void)
 {
-	/* XXX: Get boot line from environment? */
+	powertv_clocksource_init();
+	r4k_clockevent_init();
 }
diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c
index ad5bd10..d7c26d0 100644
--- a/arch/mips/rb532/prom.c
+++ b/arch/mips/rb532/prom.c
@@ -69,7 +69,7 @@
 
 void __init prom_setup_cmdline(void)
 {
-	static char cmd_line[CL_SIZE] __initdata;
+	static char cmd_line[COMMAND_LINE_SIZE] __initdata;
 	char *cp, *board;
 	int prom_argc;
 	char **prom_argv, **prom_envp;
@@ -115,7 +115,7 @@
 		strcpy(cp, arcs_cmdline);
 		cp += strlen(arcs_cmdline);
 	}
-	cmd_line[CL_SIZE-1] = '\0';
+	cmd_line[COMMAND_LINE_SIZE - 1] = '\0';
 
 	strcpy(arcs_cmdline, cmd_line);
 }
diff --git a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c
index 1617241..da44ccb 100644
--- a/arch/mips/sgi-ip22/ip22-eisa.c
+++ b/arch/mips/sgi-ip22/ip22-eisa.c
@@ -50,9 +50,9 @@
 
 static char __init *decode_eisa_sig(unsigned long addr)
 {
-        static char sig_str[EISA_SIG_LEN];
+	static char sig_str[EISA_SIG_LEN] __initdata;
 	u8 sig[4];
-        u16 rev;
+	u16 rev;
 	int i;
 
 	for (i = 0; i < 4; i++) {
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c
index 0ecd5fe..383f11d 100644
--- a/arch/mips/sgi-ip22/ip22-int.c
+++ b/arch/mips/sgi-ip22/ip22-int.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
+#include <linux/ftrace.h>
 
 #include <asm/irq_cpu.h>
 #include <asm/sgi/hpc3.h>
@@ -150,7 +151,7 @@
 
 extern void ip22_be_interrupt(int irq);
 
-static void indy_buserror_irq(void)
+static void __irq_entry indy_buserror_irq(void)
 {
 	int irq = SGI_BUSERR_IRQ;
 
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index b9a9313..5deeb68 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -67,7 +67,7 @@
 	cserial = ArcGetEnvironmentVariable("ConsoleOut");
 
 	if ((ctype && *ctype == 'd') || (cserial && *cserial == 's')) {
-		static char options[8];
+		static char options[8] __initdata;
 		char *baud = ArcGetEnvironmentVariable("dbaud");
 		if (baud)
 			strcpy(options, baud);
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index c8f7d23..603fc91 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/time.h>
+#include <linux/ftrace.h>
 
 #include <asm/cpu.h>
 #include <asm/mipsregs.h>
@@ -115,7 +116,7 @@
 }
 
 /* Generic SGI handler for (spurious) 8254 interrupts */
-void indy_8254timer_irq(void)
+void __irq_entry indy_8254timer_irq(void)
 {
 	int irq = SGI_8254_0_IRQ;
 	ULONG cnt;
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index c5a5d4a..3abd146 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -90,7 +90,7 @@
 	{
 		char* con = ArcGetEnvironmentVariable("console");
 		if (con && *con == 'd') {
-			static char options[8];
+			static char options[8] __initdata;
 			char *baud = ArcGetEnvironmentVariable("dbaud");
 			if (baud)
 				strcpy(options, baud);
diff --git a/arch/mips/sibyte/common/cfe.c b/arch/mips/sibyte/common/cfe.c
index eb5396c..6343011 100644
--- a/arch/mips/sibyte/common/cfe.c
+++ b/arch/mips/sibyte/common/cfe.c
@@ -287,7 +287,7 @@
 	 * boot console
 	 */
 	cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
-	if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
+	if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, COMMAND_LINE_SIZE) < 0) {
 		if (argc >= 0) {
 			/* The loader should have set the command line */
 			/* too early for panic to do any good */
@@ -318,7 +318,7 @@
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 	/* Not sure this is needed, but it's the safe way. */
-	arcs_cmdline[CL_SIZE-1] = 0;
+	arcs_cmdline[COMMAND_LINE_SIZE-1] = 0;
 
 	prom_meminit();
 
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 7dd76fb..e698089 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -188,7 +188,7 @@
 }
 
 static struct irq_chip a20r_irq_type = {
-	.typename	= "A20R",
+	.name		= "A20R",
 	.ack		= mask_a20r_irq,
 	.mask		= mask_a20r_irq,
 	.mask_ack	= mask_a20r_irq,
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 74e6c67..51e62bb 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -214,7 +214,7 @@
 }
 
 static struct irq_chip pcimt_irq_type = {
-	.typename = "PCIMT",
+	.name = "PCIMT",
 	.ack = disable_pcimt_irq,
 	.mask = disable_pcimt_irq,
 	.mask_ack = disable_pcimt_irq,
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 071a957..f4699d3 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -176,7 +176,7 @@
 }
 
 static struct irq_chip pcit_irq_type = {
-	.typename = "PCIT",
+	.name = "PCIT",
 	.ack = disable_pcit_irq,
 	.mask = disable_pcit_irq,
 	.mask_ack = disable_pcit_irq,
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index 5e68781..46f0069 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -449,7 +449,7 @@
 }
 
 static struct irq_chip rm200_irq_type = {
-	.typename = "RM200",
+	.name = "RM200",
 	.ack = disable_rm200_irq,
 	.mask = disable_rm200_irq,
 	.mask_ack = disable_rm200_irq,
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index a49272c..d16b462 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -60,7 +60,7 @@
 	char *cdev;
 	char *baud;
 	int port;
-	static char options[8];
+	static char options[8] __initdata;
 
 	cdev = prom_getenv("console_dev");
 	if (strncmp(cdev, "tty", 3) == 0) {
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c
index d66802e..06e801c 100644
--- a/arch/mips/txx9/generic/setup.c
+++ b/arch/mips/txx9/generic/setup.c
@@ -160,7 +160,7 @@
 	int argc;
 	int *argv32;
 	int i;			/* Always ignore the "-c" at argv[0] */
-	static char builtin[CL_SIZE] __initdata;
+	static char builtin[COMMAND_LINE_SIZE] __initdata;
 
 	if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) {
 		/*
@@ -315,7 +315,7 @@
 
 static void __init preprocess_cmdline(void)
 {
-	static char cmdline[CL_SIZE] __initdata;
+	static char cmdline[COMMAND_LINE_SIZE] __initdata;
 	char *s;
 
 	strcpy(cmdline, arcs_cmdline);
diff --git a/arch/mn10300/include/asm/asm-offsets.h b/arch/mn10300/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/mn10300/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/mn10300/include/asm/elf.h b/arch/mn10300/include/asm/elf.h
index 75a70aa..e5fa97c 100644
--- a/arch/mn10300/include/asm/elf.h
+++ b/arch/mn10300/include/asm/elf.h
@@ -77,7 +77,6 @@
 	_ur->a1   = 0;	_ur->a0   = 0;	_ur->d1   = 0;	_ur->d0   = 0;	\
 } while (0)
 
-#define USE_ELF_CORE_DUMP
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	4096
 
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 18072e0..92343bd 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -445,12 +445,7 @@
 
 int hpux_pipe(int *kstack_fildes)
 {
-	int error;
-
-	lock_kernel();
-	error = do_pipe_flags(kstack_fildes, 0);
-	unlock_kernel();
-	return error;
+	return do_pipe_flags(kstack_fildes, 0);
 }
 
 /* lies - says it works, but it really didn't lock anything */
diff --git a/arch/parisc/include/asm/asm-offsets.h b/arch/parisc/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/parisc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/parisc/include/asm/bug.h b/arch/parisc/include/asm/bug.h
index 8cfc553..75e46c5 100644
--- a/arch/parisc/include/asm/bug.h
+++ b/arch/parisc/include/asm/bug.h
@@ -32,14 +32,14 @@
 			     "\t.popsection"				\
 			     : : "i" (__FILE__), "i" (__LINE__),	\
 			     "i" (0), "i" (sizeof(struct bug_entry)) ); \
-		for(;;) ;						\
+		unreachable();						\
 	} while(0)
 
 #else
 #define BUG()								\
 	do {								\
 		asm volatile(PARISC_BUG_BREAK_ASM : : );		\
-		for(;;) ;						\
+		unreachable();						\
 	} while(0)
 #endif
 
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h
index 9c802eb..19f6cb1 100644
--- a/arch/parisc/include/asm/elf.h
+++ b/arch/parisc/include/asm/elf.h
@@ -328,7 +328,6 @@
    such function.  */
 #define ELF_PLAT_INIT(_r, load_addr)       _r->gr[23] = 0
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/parisc/include/asm/ftrace.h b/arch/parisc/include/asm/ftrace.h
index 2fa05dd..72c0faf 100644
--- a/arch/parisc/include/asm/ftrace.h
+++ b/arch/parisc/include/asm/ftrace.h
@@ -20,6 +20,20 @@
  * Defined in entry.S
  */
 extern void return_to_handler(void);
+
+
+extern unsigned long return_address(unsigned int);
+
+#define HAVE_ARCH_CALLER_ADDR
+
+#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
+#define CALLER_ADDR1 return_address(1)
+#define CALLER_ADDR2 return_address(2)
+#define CALLER_ADDR3 return_address(3)
+#define CALLER_ADDR4 return_address(4)
+#define CALLER_ADDR5 return_address(5)
+#define CALLER_ADDR6 return_address(6)
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_PARISC_FTRACE_H */
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index fcd3c70..ec787b4 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -244,9 +244,6 @@
 	DEFINE(THREAD_SZ, sizeof(struct thread_info));
 	DEFINE(THREAD_SZ_ALGN, align(sizeof(struct thread_info), 64));
 	BLANK();
-	DEFINE(IRQSTAT_SIRQ_PEND, offsetof(irq_cpustat_t, __softirq_pending));
-	DEFINE(IRQSTAT_SZ, sizeof(irq_cpustat_t));
-	BLANK();
 	DEFINE(ICACHE_BASE, offsetof(struct pdc_cache_info, ic_base));
 	DEFINE(ICACHE_STRIDE, offsetof(struct pdc_cache_info, ic_stride));
 	DEFINE(ICACHE_COUNT, offsetof(struct pdc_cache_info, ic_count));
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index f47465e..efbcee5 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -145,7 +145,7 @@
 #endif
 
 static struct irq_chip cpu_interrupt_type = {
-	.typename	= "CPU",
+	.name		= "CPU",
 	.startup	= cpu_startup_irq,
 	.shutdown	= cpu_disable_irq,
 	.enable		= cpu_enable_irq,
@@ -192,7 +192,7 @@
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
 
-		seq_printf(p, " %14s", irq_desc[i].chip->typename);
+		seq_printf(p, " %14s", irq_desc[i].chip->name);
 #ifndef PARISC_IRQ_CR16_COUNTS
 		seq_printf(p, "  %s", action->name);
 
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index e8467e4..fb37ac5 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -26,7 +26,6 @@
 #include <linux/stddef.h>
 #include <linux/compat.h>
 #include <linux/elf.h>
-#include <linux/tracehook.h>
 #include <asm/ucontext.h>
 #include <asm/rt_sigframe.h>
 #include <asm/uaccess.h>
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 1fd0f0c..3f2fce8 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -60,8 +60,6 @@
 #define smp_debug(lvl, ...)	do { } while(0)
 #endif /* DEBUG_SMP */
 
-DEFINE_SPINLOCK(smp_lock);
-
 volatile struct task_struct *smp_init_current_idle_task;
 
 /* track which CPU is booting */
@@ -69,7 +67,7 @@
 
 static int parisc_max_cpus __cpuinitdata = 1;
 
-DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
+static DEFINE_PER_CPU(spinlock_t, ipi_lock);
 
 enum ipi_message_type {
 	IPI_NOP=0,
@@ -438,6 +436,11 @@
 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		spin_lock_init(&per_cpu(ipi_lock, cpu));
+
 	init_cpu_present(cpumask_of(0));
 
 	parisc_max_cpus = max_cpus;
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index 76d23ec..9779ece 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -26,13 +26,7 @@
 #include <linux/shm.h>
 #include <linux/slab.h>
 #include <linux/uio.h>
-#include <linux/nfs_fs.h>
 #include <linux/ncp_fs.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index a36799e..d58eac1 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kallsyms.h>
+#include <linux/sort.h>
 
 #include <asm/uaccess.h>
 #include <asm/assembly.h>
@@ -115,24 +116,18 @@
 	}
 }
 
+static int cmp_unwind_table_entry(const void *a, const void *b)
+{
+	return ((const struct unwind_table_entry *)a)->region_start
+	     - ((const struct unwind_table_entry *)b)->region_start;
+}
+
 static void
 unwind_table_sort(struct unwind_table_entry *start,
 		  struct unwind_table_entry *finish)
 {
-	struct unwind_table_entry el, *p, *q;
-
-	for (p = start + 1; p < finish; ++p) {
-		if (p[0].region_start < p[-1].region_start) {
-			el = *p;
-			q = p;
-			do {
-				q[0] = q[-1];
-				--q;
-			} while (q > start && 
-				 el.region_start < q[-1].region_start);
-			*q = el;
-		}
-	}
+	sort(start, finish - start, sizeof(struct unwind_table_entry),
+	     cmp_unwind_table_entry, NULL);
 }
 
 struct unwind_table *
@@ -417,3 +412,30 @@
 
 	return ret;
 }
+
+unsigned long return_address(unsigned int level)
+{
+	struct unwind_frame_info info;
+	struct pt_regs r;
+	unsigned long sp;
+
+	/* initialize unwind info */
+	asm volatile ("copy %%r30, %0" : "=r"(sp));
+	memset(&r, 0, sizeof(struct pt_regs));
+	r.iaoq[0] = (unsigned long) current_text_addr();
+	r.gr[2] = (unsigned long) __builtin_return_address(0);
+	r.gr[30] = sp;
+	unwind_frame_init(&info, current, &r);
+
+	/* unwind stack */
+	++level;
+	do {
+		if (unwind_once(&info) < 0 || info.ip == 0)
+			return 0;
+		if (!__kernel_text_address(info.ip)) {
+			return 0;
+		}
+	} while (info.ip && level--);
+
+	return info.ip;
+}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0df5746..ba3948c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -704,7 +704,7 @@
 config PCI
 	bool "PCI support" if PPC_PCI_CHOICE
 	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
-		&& !PPC_85xx && !PPC_86xx
+		&& !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	select ARCH_SUPPORTS_MSI
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index bf3382f..5cdd7ed 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -254,6 +254,14 @@
 	  using a CPM-based serial port.  This assumes that the bootwrapper
 	  has run, and set up the CPM in a particular way.
 
+config PPC_EARLY_DEBUG_USBGECKO
+	bool "Early debugging through the USB Gecko adapter"
+	depends on GAMECUBE_COMMON
+	select USBGECKO_UDBG
+	help
+	  Select this to enable early debugging for Nintendo GameCube/Wii
+	  consoles via an external USB Gecko adapter.
+
 endchoice
 
 config PPC_EARLY_DEBUG_44x_PHYSLOW
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 7bfc8ad..bb2465b 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -66,7 +66,7 @@
 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
 		cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \
-		fsl-soc.c mpc8xx.c pq2.c
+		fsl-soc.c mpc8xx.c pq2.c ugecon.c
 src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \
 		cuboot-ebony.c cuboot-hotfoot.c treeboot-ebony.c prpmc2800.c \
 		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
@@ -76,7 +76,8 @@
 		cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
 		cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
 		virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
-		cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c
+		cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
+		gamecube-head.S gamecube.c wii-head.S wii.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -254,6 +255,8 @@
 image-$(CONFIG_STORCENTER)		+= cuImage.storcenter
 image-$(CONFIG_MPC7448HPC2)		+= cuImage.mpc7448hpc2
 image-$(CONFIG_PPC_C2K)			+= cuImage.c2k
+image-$(CONFIG_GAMECUBE)		+= dtbImage.gamecube
+image-$(CONFIG_WII)			+= dtbImage.wii
 
 # Board port in arch/powerpc/platform/amigaone/Kconfig
 image-$(CONFIG_AMIGAONE)		+= cuImage.amigaone
diff --git a/arch/powerpc/boot/dts/gamecube.dts b/arch/powerpc/boot/dts/gamecube.dts
new file mode 100644
index 0000000..ef3be0e
--- /dev/null
+++ b/arch/powerpc/boot/dts/gamecube.dts
@@ -0,0 +1,114 @@
+/*
+ * arch/powerpc/boot/dts/gamecube.dts
+ *
+ * Nintendo GameCube platform device tree source
+ * Copyright (C) 2007-2009 The GameCube Linux Team
+ * Copyright (C) 2007,2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+	model = "nintendo,gamecube";
+	compatible = "nintendo,gamecube";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	chosen {
+		bootargs = "root=/dev/gcnsda2 rootwait udbg-immortal";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x01800000>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,gekko@0 {
+			device_type = "cpu";
+			reg = <0>;
+			clock-frequency = <486000000>; /* 486MHz */
+			bus-frequency = <162000000>; /* 162MHz core-to-bus 3x */
+			timebase-frequency = <40500000>; /* 162MHz / 4 */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+		};
+	};
+
+	/* devices contained int the flipper chipset */
+	flipper {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "nintendo,flipper";
+		ranges = <0x0c000000 0x0c000000 0x00010000>;
+		interrupt-parent = <&PIC>;
+
+		video@0c002000 {
+			compatible = "nintendo,flipper-vi";
+			reg = <0x0c002000 0x100>;
+			interrupts = <8>;
+		};
+
+		processor-interface@0c003000 {
+			compatible = "nintendo,flipper-pi";
+			reg = <0x0c003000 0x100>;
+
+			PIC: pic {
+				#interrupt-cells = <1>;
+				compatible = "nintendo,flipper-pic";
+				interrupt-controller;
+			};
+		};
+
+		dsp@0c005000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "nintendo,flipper-dsp";
+			reg = <0x0c005000 0x200>;
+			interrupts = <6>;
+
+			memory@0 {
+				compatible = "nintendo,flipper-aram";
+				reg = <0 0x1000000>;	/* 16MB */
+			};
+		};
+
+		disk@0c006000 {
+			compatible = "nintendo,flipper-di";
+			reg = <0x0c006000 0x40>;
+			interrupts = <2>;
+		};
+
+		audio@0c006c00 {
+			compatible = "nintendo,flipper-ai";
+			reg = <0x0c006c00 0x20>;
+			interrupts = <6>;
+		};
+
+		gamepad-controller@0c006400 {
+			compatible = "nintendo,flipper-si";
+			reg = <0x0c006400 0x100>;
+			interrupts = <3>;
+		};
+
+		/* External Interface bus */
+		exi@0c006800 {
+			compatible = "nintendo,flipper-exi";
+			reg = <0x0c006800 0x40>;
+			virtual-reg = <0x0c006800>;
+			interrupts = <4>;
+		};
+        };
+};
+
diff --git a/arch/powerpc/boot/dts/wii.dts b/arch/powerpc/boot/dts/wii.dts
new file mode 100644
index 0000000..77528c9
--- /dev/null
+++ b/arch/powerpc/boot/dts/wii.dts
@@ -0,0 +1,218 @@
+/*
+ * arch/powerpc/boot/dts/wii.dts
+ *
+ * Nintendo Wii platform device tree source
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+/dts-v1/;
+
+/*
+ * This is commented-out for now.
+ * Until a later patch is merged, the kernel can use only the first
+ * contiguous RAM range and will BUG() if the memreserve is outside
+ * that range.
+ */
+/*/memreserve/ 0x10000000 0x0004000;*/	/* DSP RAM */
+
+/ {
+	model = "nintendo,wii";
+	compatible = "nintendo,wii";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	chosen {
+		bootargs = "root=/dev/mmcblk0p2 rootwait udbg-immortal";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x01800000	/* MEM1 24MB 1T-SRAM */
+		       0x10000000 0x04000000>;	/* MEM2 64MB GDDR3 */
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,broadway@0 {
+			device_type = "cpu";
+			reg = <0>;
+			clock-frequency = <729000000>; /* 729MHz */
+			bus-frequency = <243000000>; /* 243MHz core-to-bus 3x */
+			timebase-frequency = <60750000>; /* 243MHz / 4 */
+			i-cache-line-size = <32>;
+			d-cache-line-size = <32>;
+			i-cache-size = <32768>;
+			d-cache-size = <32768>;
+		};
+	};
+
+	/* devices contained in the hollywood chipset */
+	hollywood {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "nintendo,hollywood";
+                ranges = <0x0c000000 0x0c000000 0x01000000
+			  0x0d000000 0x0d000000 0x00800000
+			  0x0d800000 0x0d800000 0x00800000>;
+		interrupt-parent = <&PIC0>;
+
+		video@0c002000 {
+			compatible = "nintendo,hollywood-vi",
+					"nintendo,flipper-vi";
+			reg = <0x0c002000 0x100>;
+			interrupts = <8>;
+		};
+
+		processor-interface@0c003000 {
+			compatible = "nintendo,hollywood-pi",
+					"nintendo,flipper-pi";
+			reg = <0x0c003000 0x100>;
+
+			PIC0: pic0 {
+				#interrupt-cells = <1>;
+				compatible = "nintendo,flipper-pic";
+				interrupt-controller;
+			};
+		};
+
+		dsp@0c005000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "nintendo,hollywood-dsp",
+					"nintendo,flipper-dsp";
+			reg = <0x0c005000 0x200>;
+			interrupts = <6>;
+		};
+
+		gamepad-controller@0d006400 {
+			compatible = "nintendo,hollywood-si",
+					"nintendo,flipper-si";
+			reg = <0x0d006400 0x100>;
+			interrupts = <3>;
+		};
+
+		audio@0c006c00 {
+			compatible = "nintendo,hollywood-ai",
+					"nintendo,flipper-ai";
+			reg = <0x0d006c00 0x20>;
+			interrupts = <6>;
+		};
+
+		/* External Interface bus */
+		exi@0d006800 {
+			compatible = "nintendo,hollywood-exi",
+					"nintendo,flipper-exi";
+			reg = <0x0d006800 0x40>;
+			virtual-reg = <0x0d006800>;
+			interrupts = <4>;
+		};
+
+		usb@0d040000 {
+			compatible = "nintendo,hollywood-usb-ehci",
+					"usb-ehci";
+			reg = <0x0d040000 0x100>;
+			interrupts = <4>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		usb@0d050000 {
+			compatible = "nintendo,hollywood-usb-ohci",
+					"usb-ohci";
+			reg = <0x0d050000 0x100>;
+			interrupts = <5>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		usb@0d060000 {
+			compatible = "nintendo,hollywood-usb-ohci",
+					"usb-ohci";
+			reg = <0x0d060000 0x100>;
+			interrupts = <6>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		sd@0d070000 {
+			compatible = "nintendo,hollywood-sdhci",
+					"sdhci";
+			reg = <0x0d070000 0x200>;
+			interrupts = <7>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		sdio@0d080000 {
+			compatible = "nintendo,hollywood-sdhci",
+					"sdhci";
+			reg = <0x0d080000 0x200>;
+			interrupts = <8>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		ipc@0d000000 {
+			compatible = "nintendo,hollywood-ipc";
+			reg = <0x0d000000 0x10>;
+			interrupts = <30>;
+			interrupt-parent = <&PIC1>;
+		};
+
+		PIC1: pic1@0d800030 {
+			#interrupt-cells = <1>;
+			compatible = "nintendo,hollywood-pic";
+			reg = <0x0d800030 0x10>;
+			interrupt-controller;
+			interrupts = <14>;
+		};
+
+		GPIO: gpio@0d8000c0 {
+			#gpio-cells = <2>;
+			compatible = "nintendo,hollywood-gpio";
+			reg = <0x0d8000c0 0x40>;
+			gpio-controller;
+
+			/*
+			 * This is commented out while a standard binding
+			 * for i2c over gpio is defined.
+			 */
+			/*
+			i2c-video {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			        compatible = "i2c-gpio";
+
+			        gpios = <&GPIO 15 0
+			                 &GPIO 14 0>;
+			        clock-frequency = <250000>;
+				no-clock-stretching;
+			        scl-is-open-drain;
+			        sda-is-open-drain;
+			        sda-enforce-dir;
+
+			        AVE: audio-video-encoder@70 {
+			                compatible = "nintendo,wii-audio-video-encoder";
+			                reg = <0x70>;
+			        };
+			};
+			*/
+		};
+
+		control@0d800100 {
+			compatible = "nintendo,hollywood-control";
+			reg = <0x0d800100 0x300>;
+		};
+
+		disk@0d806000 {
+			compatible = "nintendo,hollywood-di";
+			reg = <0x0d806000 0x40>;
+			interrupts = <2>;
+		};
+	};
+};
+
diff --git a/arch/powerpc/boot/gamecube-head.S b/arch/powerpc/boot/gamecube-head.S
new file mode 100644
index 0000000..65a9b2a
--- /dev/null
+++ b/arch/powerpc/boot/gamecube-head.S
@@ -0,0 +1,111 @@
+/*
+ * arch/powerpc/boot/gamecube-head.S
+ *
+ * Nintendo GameCube bootwrapper entry.
+ * Copyright (C) 2004-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "ppc_asm.h"
+
+/*
+ * The entry code does no assumptions regarding:
+ * - if the data and instruction caches are enabled or not
+ * - if the MMU is enabled or not
+ *
+ * We enable the caches if not already enabled, enable the MMU with an
+ * identity mapping scheme and jump to the start code.
+ */
+
+	.text
+
+	.globl _zimage_start
+_zimage_start:
+
+	/* turn the MMU off */
+	mfmsr	9
+	rlwinm	9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */
+	bcl	20, 31, 1f
+1:
+	mflr	8
+	clrlwi	8, 8, 3		/* convert to a real address */
+	addi	8, 8, _mmu_off - 1b
+	mtsrr0	8
+	mtsrr1	9
+	rfi
+_mmu_off:
+	/* MMU disabled */
+
+	/* setup BATs */
+	isync
+	li      8, 0
+	mtspr	0x210, 8	/* IBAT0U */
+	mtspr	0x212, 8	/* IBAT1U */
+	mtspr	0x214, 8	/* IBAT2U */
+	mtspr	0x216, 8	/* IBAT3U */
+	mtspr	0x218, 8	/* DBAT0U */
+	mtspr	0x21a, 8	/* DBAT1U */
+	mtspr	0x21c, 8	/* DBAT2U */
+	mtspr	0x21e, 8	/* DBAT3U */
+
+	li	8, 0x01ff	/* first 16MiB */
+	li	9, 0x0002	/* rw */
+	mtspr	0x211, 9	/* IBAT0L */
+	mtspr	0x210, 8	/* IBAT0U */
+	mtspr	0x219, 9	/* DBAT0L */
+	mtspr	0x218, 8	/* DBAT0U */
+
+	lis	8, 0x0c00	/* I/O mem */
+	ori	8, 8, 0x3ff	/* 32MiB */
+	lis	9, 0x0c00
+	ori	9, 9, 0x002a	/* uncached, guarded, rw */
+	mtspr	0x21b, 9	/* DBAT1L */
+	mtspr	0x21a, 8	/* DBAT1U */
+
+	lis	8, 0x0100	/* next 8MiB */
+	ori	8, 8, 0x00ff	/* 8MiB */
+	lis	9, 0x0100
+	ori	9, 9, 0x0002	/* rw */
+	mtspr	0x215, 9	/* IBAT2L */
+	mtspr	0x214, 8	/* IBAT2U */
+	mtspr	0x21d, 9	/* DBAT2L */
+	mtspr	0x21c, 8	/* DBAT2U */
+
+	/* enable and invalidate the caches if not already enabled */
+	mfspr	8, 0x3f0	/* HID0 */
+	andi.	0, 8, (1<<15)		/* HID0_ICE */
+	bne	1f
+	ori	8, 8, (1<<15)|(1<<11)	/* HID0_ICE|HID0_ICFI*/
+1:
+	andi.	0, 8, (1<<14)		/* HID0_DCE */
+	bne	1f
+	ori	8, 8, (1<<14)|(1<<10)	/* HID0_DCE|HID0_DCFI*/
+1:
+	mtspr	0x3f0, 8	/* HID0 */
+	isync
+
+	/* initialize arguments */
+	li	3, 0
+	li	4, 0
+	li	5, 0
+
+	/* turn the MMU on */
+	bcl	20, 31, 1f
+1:
+	mflr	8
+	addi	8, 8, _mmu_on - 1b
+	mfmsr	9
+	ori	9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */
+	mtsrr0	8
+	mtsrr1	9
+	sync
+	rfi
+_mmu_on:
+	b _zimage_start_lib
+
diff --git a/arch/powerpc/boot/gamecube.c b/arch/powerpc/boot/gamecube.c
new file mode 100644
index 0000000..28ae7057
--- /dev/null
+++ b/arch/powerpc/boot/gamecube.c
@@ -0,0 +1,35 @@
+/*
+ * arch/powerpc/boot/gamecube.c
+ *
+ * Nintendo GameCube bootwrapper support
+ * Copyright (C) 2004-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "stdio.h"
+#include "types.h"
+#include "io.h"
+#include "ops.h"
+
+#include "ugecon.h"
+
+BSS_STACK(8192);
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
+{
+	u32 heapsize = 16*1024*1024 - (u32)_end;
+
+	simple_alloc_init(_end, heapsize, 32, 64);
+	fdt_init(_dtb_start);
+
+	if (ug_probe())
+		console_ops.write = ug_console_write;
+}
+
diff --git a/arch/powerpc/boot/ugecon.c b/arch/powerpc/boot/ugecon.c
new file mode 100644
index 0000000..50609ea
--- /dev/null
+++ b/arch/powerpc/boot/ugecon.c
@@ -0,0 +1,147 @@
+/*
+ * arch/powerpc/boot/ugecon.c
+ *
+ * USB Gecko bootwrapper console.
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "stdio.h"
+#include "types.h"
+#include "io.h"
+#include "ops.h"
+
+
+#define EXI_CLK_32MHZ           5
+
+#define EXI_CSR                 0x00
+#define   EXI_CSR_CLKMASK       (0x7<<4)
+#define     EXI_CSR_CLK_32MHZ   (EXI_CLK_32MHZ<<4)
+#define   EXI_CSR_CSMASK        (0x7<<7)
+#define     EXI_CSR_CS_0        (0x1<<7)  /* Chip Select 001 */
+
+#define EXI_CR                  0x0c
+#define   EXI_CR_TSTART         (1<<0)
+#define   EXI_CR_WRITE		(1<<2)
+#define   EXI_CR_READ_WRITE     (2<<2)
+#define   EXI_CR_TLEN(len)      (((len)-1)<<4)
+
+#define EXI_DATA                0x10
+
+
+/* virtual address base for input/output, retrieved from device tree */
+static void *ug_io_base;
+
+
+static u32 ug_io_transaction(u32 in)
+{
+	u32 *csr_reg = ug_io_base + EXI_CSR;
+	u32 *data_reg = ug_io_base + EXI_DATA;
+	u32 *cr_reg = ug_io_base + EXI_CR;
+	u32 csr, data, cr;
+
+	/* select */
+	csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
+	out_be32(csr_reg, csr);
+
+	/* read/write */
+	data = in;
+	out_be32(data_reg, data);
+	cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
+	out_be32(cr_reg, cr);
+
+	while (in_be32(cr_reg) & EXI_CR_TSTART)
+		barrier();
+
+	/* deselect */
+	out_be32(csr_reg, 0);
+
+	data = in_be32(data_reg);
+	return data;
+}
+
+static int ug_is_txfifo_ready(void)
+{
+	return ug_io_transaction(0xc0000000) & 0x04000000;
+}
+
+static void ug_raw_putc(char ch)
+{
+	ug_io_transaction(0xb0000000 | (ch << 20));
+}
+
+static void ug_putc(char ch)
+{
+	int count = 16;
+
+	if (!ug_io_base)
+		return;
+
+	while (!ug_is_txfifo_ready() && count--)
+		barrier();
+	if (count)
+		ug_raw_putc(ch);
+}
+
+void ug_console_write(const char *buf, int len)
+{
+	char *b = (char *)buf;
+
+	while (len--) {
+		if (*b == '\n')
+			ug_putc('\r');
+		ug_putc(*b++);
+	}
+}
+
+static int ug_is_adapter_present(void)
+{
+	if (!ug_io_base)
+		return 0;
+	return ug_io_transaction(0x90000000) == 0x04700000;
+}
+
+static void *ug_grab_exi_io_base(void)
+{
+	u32 v;
+	void *devp;
+
+	devp = find_node_by_compatible(NULL, "nintendo,flipper-exi");
+	if (devp == NULL)
+		goto err_out;
+	if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
+		goto err_out;
+
+	return (void *)v;
+
+err_out:
+	return NULL;
+}
+
+void *ug_probe(void)
+{
+	void *exi_io_base;
+	int i;
+
+	exi_io_base = ug_grab_exi_io_base();
+	if (!exi_io_base)
+		return NULL;
+
+	/* look for a usbgecko on memcard slots A and B */
+	for (i = 0; i < 2; i++) {
+		ug_io_base = exi_io_base + 0x14 * i;
+		if (ug_is_adapter_present())
+			break;
+	}
+	if (i == 2)
+		ug_io_base = NULL;
+	return ug_io_base;
+}
+
diff --git a/arch/powerpc/boot/ugecon.h b/arch/powerpc/boot/ugecon.h
new file mode 100644
index 0000000..4373753
--- /dev/null
+++ b/arch/powerpc/boot/ugecon.h
@@ -0,0 +1,24 @@
+/*
+ * arch/powerpc/boot/ugecon.h
+ *
+ * USB Gecko early bootwrapper console.
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __UGECON_H
+#define __UGECON_H
+
+extern void *ug_probe(void);
+
+extern void ug_putc(char ch);
+extern void ug_console_write(const char *buf, int len);
+
+#endif /* __UGECON_H */
+
diff --git a/arch/powerpc/boot/wii-head.S b/arch/powerpc/boot/wii-head.S
new file mode 100644
index 0000000..edd79b8
--- /dev/null
+++ b/arch/powerpc/boot/wii-head.S
@@ -0,0 +1,142 @@
+/*
+ * arch/powerpc/boot/wii-head.S
+ *
+ * Nintendo Wii bootwrapper entry.
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "ppc_asm.h"
+
+/*
+ * The entry code does no assumptions regarding:
+ * - if the data and instruction caches are enabled or not
+ * - if the MMU is enabled or not
+ * - if the high BATs are enabled or not
+ *
+ * We enable the high BATs, enable the caches if not already enabled,
+ * enable the MMU with an identity mapping scheme and jump to the start code.
+ */
+
+	.text
+
+	.globl _zimage_start
+_zimage_start:
+
+	/* turn the MMU off */
+	mfmsr	9
+	rlwinm	9, 9, 0, ~((1<<4)|(1<<5)) /* MSR_DR|MSR_IR */
+	bcl	20, 31, 1f
+1:
+	mflr	8
+	clrlwi	8, 8, 3		/* convert to a real address */
+	addi	8, 8, _mmu_off - 1b
+	mtsrr0	8
+	mtsrr1	9
+	rfi
+_mmu_off:
+	/* MMU disabled */
+
+	/* setup BATs */
+	isync
+	li      8, 0
+	mtspr	0x210, 8	/* IBAT0U */
+	mtspr	0x212, 8	/* IBAT1U */
+	mtspr	0x214, 8	/* IBAT2U */
+	mtspr	0x216, 8	/* IBAT3U */
+	mtspr	0x218, 8	/* DBAT0U */
+	mtspr	0x21a, 8	/* DBAT1U */
+	mtspr	0x21c, 8	/* DBAT2U */
+	mtspr	0x21e, 8	/* DBAT3U */
+
+	mtspr	0x230, 8	/* IBAT4U */
+	mtspr	0x232, 8	/* IBAT5U */
+	mtspr	0x234, 8	/* IBAT6U */
+	mtspr	0x236, 8	/* IBAT7U */
+	mtspr	0x238, 8	/* DBAT4U */
+	mtspr	0x23a, 8	/* DBAT5U */
+	mtspr	0x23c, 8	/* DBAT6U */
+	mtspr	0x23e, 8	/* DBAT7U */
+
+	li	8, 0x01ff	/* first 16MiB */
+	li	9, 0x0002	/* rw */
+	mtspr	0x211, 9	/* IBAT0L */
+	mtspr	0x210, 8	/* IBAT0U */
+	mtspr	0x219, 9	/* DBAT0L */
+	mtspr	0x218, 8	/* DBAT0U */
+
+	lis	8, 0x0c00	/* I/O mem */
+	ori	8, 8, 0x3ff	/* 32MiB */
+	lis	9, 0x0c00
+	ori	9, 9, 0x002a	/* uncached, guarded, rw */
+	mtspr	0x21b, 9	/* DBAT1L */
+	mtspr	0x21a, 8	/* DBAT1U */
+
+	lis	8, 0x0100	/* next 8MiB */
+	ori	8, 8, 0x00ff	/* 8MiB */
+	lis	9, 0x0100
+	ori	9, 9, 0x0002	/* rw */
+	mtspr	0x215, 9	/* IBAT2L */
+	mtspr	0x214, 8	/* IBAT2U */
+	mtspr	0x21d, 9	/* DBAT2L */
+	mtspr	0x21c, 8	/* DBAT2U */
+
+	lis	8, 0x1000	/* MEM2 */
+	ori	8, 8, 0x07ff	/* 64MiB */
+	lis	9, 0x1000
+	ori	9, 9, 0x0002	/* rw */
+	mtspr	0x216, 8	/* IBAT3U */
+	mtspr	0x217, 9	/* IBAT3L */
+	mtspr	0x21e, 8	/* DBAT3U */
+	mtspr	0x21f, 9	/* DBAT3L */
+
+	/* enable the high BATs */
+	mfspr	8, 0x3f3	/* HID4 */
+	oris	8, 8, 0x0200
+	mtspr	0x3f3, 8	/* HID4 */
+
+	/* enable and invalidate the caches if not already enabled */
+	mfspr	8, 0x3f0	/* HID0 */
+	andi.	0, 8, (1<<15)		/* HID0_ICE */
+	bne	1f
+	ori	8, 8, (1<<15)|(1<<11)	/* HID0_ICE|HID0_ICFI*/
+1:
+	andi.	0, 8, (1<<14)		/* HID0_DCE */
+	bne	1f
+	ori	8, 8, (1<<14)|(1<<10)	/* HID0_DCE|HID0_DCFI*/
+1:
+	mtspr	0x3f0, 8	/* HID0 */
+	isync
+
+	/* initialize arguments */
+	li	3, 0
+	li	4, 0
+	li	5, 0
+
+	/* turn the MMU on */
+	bcl	20, 31, 1f
+1:
+	mflr	8
+	addi	8, 8, _mmu_on - 1b
+	mfmsr	9
+	ori	9, 9, (1<<4)|(1<<5) /* MSR_DR|MSR_IR */
+	mtsrr0	8
+	mtsrr1	9
+	sync
+	rfi
+_mmu_on:
+	/* turn on the front blue led (aka: yay! we got here!) */
+	lis	8, 0x0d00
+	ori	8, 8, 0x00c0
+	lwz	9, 0(8)
+	ori	9, 9, 0x20
+	stw	9, 0(8)
+
+	b _zimage_start_lib
+
diff --git a/arch/powerpc/boot/wii.c b/arch/powerpc/boot/wii.c
new file mode 100644
index 0000000..2ebaec0
--- /dev/null
+++ b/arch/powerpc/boot/wii.c
@@ -0,0 +1,158 @@
+/*
+ * arch/powerpc/boot/wii.c
+ *
+ * Nintendo Wii bootwrapper support
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 "stdio.h"
+#include "types.h"
+#include "io.h"
+#include "ops.h"
+
+#include "ugecon.h"
+
+BSS_STACK(8192);
+
+#define HW_REG(x)		((void *)(x))
+
+#define EXI_CTRL		HW_REG(0x0d800070)
+#define EXI_CTRL_ENABLE		(1<<0)
+
+#define MEM2_TOP		(0x10000000 + 64*1024*1024)
+#define FIRMWARE_DEFAULT_SIZE	(12*1024*1024)
+
+
+struct mipc_infohdr {
+	char magic[3];
+	u8 version;
+	u32 mem2_boundary;
+	u32 ipc_in;
+	size_t ipc_in_size;
+	u32 ipc_out;
+	size_t ipc_out_size;
+};
+
+static int mipc_check_address(u32 pa)
+{
+	/* only MEM2 addresses */
+	if (pa < 0x10000000 || pa > 0x14000000)
+		return -EINVAL;
+	return 0;
+}
+
+static struct mipc_infohdr *mipc_get_infohdr(void)
+{
+	struct mipc_infohdr **hdrp, *hdr;
+
+	/* 'mini' header pointer is the last word of MEM2 memory */
+	hdrp = (struct mipc_infohdr **)0x13fffffc;
+	if (mipc_check_address((u32)hdrp)) {
+		printf("mini: invalid hdrp %08X\n", (u32)hdrp);
+		hdr = NULL;
+		goto out;
+	}
+
+	hdr = *hdrp;
+	if (mipc_check_address((u32)hdr)) {
+		printf("mini: invalid hdr %08X\n", (u32)hdr);
+		hdr = NULL;
+		goto out;
+	}
+	if (memcmp(hdr->magic, "IPC", 3)) {
+		printf("mini: invalid magic\n");
+		hdr = NULL;
+		goto out;
+	}
+
+out:
+	return hdr;
+}
+
+static int mipc_get_mem2_boundary(u32 *mem2_boundary)
+{
+	struct mipc_infohdr *hdr;
+	int error;
+
+	hdr = mipc_get_infohdr();
+	if (!hdr) {
+		error = -1;
+		goto out;
+	}
+
+	if (mipc_check_address(hdr->mem2_boundary)) {
+		printf("mini: invalid mem2_boundary %08X\n",
+		       hdr->mem2_boundary);
+		error = -EINVAL;
+		goto out;
+	}
+	*mem2_boundary = hdr->mem2_boundary;
+	error = 0;
+out:
+	return error;
+
+}
+
+static void platform_fixups(void)
+{
+	void *mem;
+	u32 reg[4];
+	u32 mem2_boundary;
+	int len;
+	int error;
+
+	mem = finddevice("/memory");
+	if (!mem)
+		fatal("Can't find memory node\n");
+
+	/* two ranges of (address, size) words */
+	len = getprop(mem, "reg", reg, sizeof(reg));
+	if (len != sizeof(reg)) {
+		/* nothing to do */
+		goto out;
+	}
+
+	/* retrieve MEM2 boundary from 'mini' */
+	error = mipc_get_mem2_boundary(&mem2_boundary);
+	if (error) {
+		/* if that fails use a sane value */
+		mem2_boundary = MEM2_TOP - FIRMWARE_DEFAULT_SIZE;
+	}
+
+	if (mem2_boundary > reg[2] && mem2_boundary < reg[2] + reg[3]) {
+		reg[3] = mem2_boundary - reg[2];
+		printf("top of MEM2 @ %08X\n", reg[2] + reg[3]);
+		setprop(mem, "reg", reg, sizeof(reg));
+	}
+
+out:
+	return;
+}
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5)
+{
+	u32 heapsize = 24*1024*1024 - (u32)_end;
+
+	simple_alloc_init(_end, heapsize, 32, 64);
+	fdt_init(_dtb_start);
+
+	/*
+	 * 'mini' boots the Broadway processor with EXI disabled.
+	 * We need it enabled before probing for the USB Gecko.
+	 */
+	out_be32(EXI_CTRL, in_be32(EXI_CTRL) | EXI_CTRL_ENABLE);
+
+	if (ug_probe())
+		console_ops.write = ug_console_write;
+
+	platform_ops.fixups = platform_fixups;
+}
+
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index ac9e9a5..390512a 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -230,6 +230,10 @@
     link_address='0x1400000'
     platformo=$object/cuboot-85xx.o
     ;;
+gamecube|wii)
+    link_address='0x600000'
+    platformo="$object/$platform-head.o $object/$platform.o"
+    ;;
 esac
 
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
diff --git a/arch/powerpc/configs/gamecube_defconfig b/arch/powerpc/configs/gamecube_defconfig
new file mode 100644
index 0000000..942e119
--- /dev/null
+++ b/arch/powerpc/configs/gamecube_defconfig
@@ -0,0 +1,1061 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc8
+# Sun Nov 22 21:07:30 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_PPC_BOOK3S_32=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
+CONFIG_PPC_PERF_CTRS=y
+# CONFIG_SMP is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-gcn"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=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 is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_EVENT_PROFILE=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_LINKSTATION is not set
+# CONFIG_STORCENTER is not set
+# CONFIG_MPC7448HPC2 is not set
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+# CONFIG_PPC_C2K is not set
+CONFIG_GAMECUBE_COMMON=y
+CONFIG_USBGECKO_UDBG=y
+CONFIG_FLIPPER_PIC=y
+CONFIG_GAMECUBE=y
+# CONFIG_WII is not set
+# CONFIG_AMIGAONE is not set
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# 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_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_PAGE_OFFSET_BOOL is not set
+CONFIG_PAGE_OFFSET=0xc0000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0xc0000000
+# CONFIG_CONSISTENT_SIZE_BOOL is not set
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# 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_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+# CONFIG_STANDALONE is not set
+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
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_XILINX_EMACLITE is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_INPUT_MOUSE 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_ZHENHUA is not set
+# CONFIG_JOYSTICK_JOYDUMP 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 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT 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_CFB_REV_PIXELS_IN_BYTE 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_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PPC=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+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
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_GENERIC=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# 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_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=y
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
+# CONFIG_DLM is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+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 is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# 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 is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+CONFIG_BOOT_TRACER=y
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+CONFIG_DMA_API_DEBUG=y
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+# 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_40x is not set
+# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+CONFIG_PPC_EARLY_DEBUG_USBGECKO=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+# CONFIG_CRYPTO is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig
new file mode 100644
index 0000000..c386828
--- /dev/null
+++ b/arch/powerpc/configs/wii_defconfig
@@ -0,0 +1,1406 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.32-rc8
+# Sun Nov 22 20:37:21 2009
+#
+# CONFIG_PPC64 is not set
+
+#
+# Processor support
+#
+CONFIG_PPC_BOOK3S_32=y
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_8xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
+CONFIG_PPC_PERF_CTRS=y
+# CONFIG_SMP is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_PPC32=y
+CONFIG_WORD_SIZE=32
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_MMU=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
+CONFIG_IRQ_PER_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-wii"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=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 is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+CONFIG_EVENT_PROFILE=y
+CONFIG_PERF_COUNTERS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_SLOW_WORK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# Platform support
+#
+# CONFIG_PPC_CHRP is not set
+# CONFIG_MPC5121_ADS is not set
+# CONFIG_MPC5121_GENERIC is not set
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_86xx is not set
+CONFIG_EMBEDDED6xx=y
+# CONFIG_LINKSTATION is not set
+# CONFIG_STORCENTER is not set
+# CONFIG_MPC7448HPC2 is not set
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+# CONFIG_PPC_C2K is not set
+CONFIG_GAMECUBE_COMMON=y
+CONFIG_USBGECKO_UDBG=y
+CONFIG_FLIPPER_PIC=y
+# CONFIG_GAMECUBE is not set
+CONFIG_HLWD_PIC=y
+CONFIG_STARLET_MINI=y
+CONFIG_WII=y
+# CONFIG_AMIGAONE is not set
+# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
+# CONFIG_IPIC is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# 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_SCHED_HRTICK is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_WALK_MEMORY=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_MAX_ACTIVE_REGIONS=32
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_MIGRATION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_EXTRA_TARGETS=""
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+# CONFIG_HAS_RAPIDIO is not set
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_PAGE_OFFSET_BOOL is not set
+CONFIG_PAGE_OFFSET=0xc0000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_PHYSICAL_START=0x00000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0xc0000000
+# CONFIG_CONSISTENT_SIZE_BOOL is not set
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# 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_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+# CONFIG_BT_SCO is not set
+CONFIG_BT_RFCOMM=y
+# CONFIG_BT_RFCOMM_TTY is not set
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTSDIO is not set
+# CONFIG_BT_HCIUART is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=1
+# CONFIG_CFG80211_DEBUGFS is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=y
+# CONFIG_MAC80211_RC_PID is not set
+CONFIG_MAC80211_RC_MINSTREL=y
+# CONFIG_MAC80211_RC_DEFAULT_PID is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=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
+CONFIG_SCSI_MULTI_LUN=y
+# 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
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_XILINX_EMACLITE is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_HOSTAP is not set
+CONFIG_B43=y
+CONFIG_B43_SDIO=y
+CONFIG_B43_PIO=y
+# CONFIG_B43_PHY_LP is not set
+CONFIG_B43_DEBUG=y
+# CONFIG_B43_FORCE_PIO is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_WL12XX is not set
+# CONFIG_IWM is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C 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_ZHENHUA is not set
+# CONFIG_JOYSTICK_JOYDUMP is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER 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 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_XILINX_XPS_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=64
+# CONFIG_HVC_UDBG is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_NVRAM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_SDIOHOST_POSSIBLE=y
+CONFIG_SSB_SDIOHOST=y
+# CONFIG_SSB_SILENT is not set
+CONFIG_SSB_DEBUG=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT 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_CFB_REV_PIXELS_IN_BYTE 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_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# 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_OF is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_PPC=y
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_APPLE=m
+CONFIG_HID_WACOM=m
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_OF is not set
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_WBSD is not set
+# CONFIG_MMC_AT91 is not set
+# CONFIG_MMC_ATMELMCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_GENERIC=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# 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_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# 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_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=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
+# CONFIG_DLM is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# 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_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+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 is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# 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 is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_LATENCYTOP=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACER_MAX_TRACE=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_TRACING=y
+CONFIG_GENERIC_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+CONFIG_SCHED_TRACER=y
+CONFIG_BOOT_TRACER=y
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+CONFIG_DMA_API_DEBUG=y
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
+# CONFIG_CODE_PATCHING_SELFTEST is not set
+# CONFIG_FTR_FIXUP_SELFTEST is not set
+# CONFIG_MSI_BITMAP_SELFTEST is not set
+# CONFIG_XMON is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
+# CONFIG_BDI_SWITCH is not set
+# 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_40x is not set
+# CONFIG_PPC_EARLY_DEBUG_CPM is not set
+CONFIG_PPC_EARLY_DEBUG_USBGECKO=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_PPC_CLOCK is not set
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/powerpc/include/asm/asm-offsets.h b/arch/powerpc/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/powerpc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/powerpc/include/asm/async_tx.h b/arch/powerpc/include/asm/async_tx.h
new file mode 100644
index 0000000..8b2dc55
--- /dev/null
+++ b/arch/powerpc/include/asm/async_tx.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008-2009 DENX Software Engineering.
+ *
+ * Author: Yuri Tikhonov <yur@emcraft.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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _ASM_POWERPC_ASYNC_TX_H_
+#define _ASM_POWERPC_ASYNC_TX_H_
+
+#if defined(CONFIG_440SPe) || defined(CONFIG_440SP)
+extern struct dma_chan *
+ppc440spe_async_tx_find_best_channel(enum dma_transaction_type cap,
+	struct page **dst_lst, int dst_cnt, struct page **src_lst,
+	int src_cnt, size_t src_sz);
+
+#define async_tx_find_channel(dep, cap, dst_lst, dst_cnt, src_lst, \
+			      src_cnt, src_sz) \
+	ppc440spe_async_tx_find_best_channel(cap, dst_lst, dst_cnt, src_lst, \
+					     src_cnt, src_sz)
+#else
+
+#define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \
+	__async_tx_find_channel(dep, type)
+
+struct dma_chan *
+__async_tx_find_channel(struct async_submit_ctl *submit,
+			enum dma_transaction_type tx_type);
+
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/dcr-regs.h b/arch/powerpc/include/asm/dcr-regs.h
index 828e3aa..380274d 100644
--- a/arch/powerpc/include/asm/dcr-regs.h
+++ b/arch/powerpc/include/asm/dcr-regs.h
@@ -157,4 +157,27 @@
 #define  L2C_SNP_SSR_32G	0x0000f000
 #define  L2C_SNP_ESR		0x00000800
 
+/*
+ * DCR register offsets for 440SP/440SPe I2O/DMA controller.
+ * The base address is configured in the device tree.
+ */
+#define DCRN_I2O0_IBAL		0x006
+#define DCRN_I2O0_IBAH		0x007
+#define I2O_REG_ENABLE		0x00000001	/* Enable I2O/DMA access */
+
+/* 440SP/440SPe Software Reset DCR */
+#define DCRN_SDR0_SRST		0x0200
+#define DCRN_SDR0_SRST_I2ODMA	(0x80000000 >> 15)	/* Reset I2O/DMA */
+
+/* 440SP/440SPe Memory Queue DCR offsets */
+#define DCRN_MQ0_XORBA		0x04
+#define DCRN_MQ0_CF2H		0x06
+#define DCRN_MQ0_CFBHL		0x0f
+#define DCRN_MQ0_BAUH		0x10
+
+/* HB/LL Paths Configuration Register */
+#define MQ0_CFBHL_TPLM		28
+#define MQ0_CFBHL_HBCL		23
+#define MQ0_CFBHL_POLY		15
+
 #endif /* __DCR_REGS_H__ */
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index e281dae..80a973b 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -197,7 +197,7 @@
 	if (!dev->dma_mask)
 		return 0;
 
-	return addr + size <= *dev->dma_mask;
+	return addr + size - 1 <= *dev->dma_mask;
 }
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 014a624..17828ad 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -170,7 +170,6 @@
 #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
 #define compat_elf_check_arch(x)	((x)->e_machine == EM_PPC)
 
-#define USE_ELF_CORE_DUMP
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h
index f1f4e23..5c2c023 100644
--- a/arch/powerpc/include/asm/fixmap.h
+++ b/arch/powerpc/include/asm/fixmap.h
@@ -44,6 +44,9 @@
  */
 enum fixed_addresses {
 	FIX_HOLE,
+	/* reserve the top 128K for early debugging purposes */
+	FIX_EARLY_DEBUG_TOP = FIX_HOLE,
+	FIX_EARLY_DEBUG_BASE = FIX_EARLY_DEBUG_TOP+((128*1024)/PAGE_SIZE)-1,
 #ifdef CONFIG_HIGHMEM
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index 0845488..0192a4e 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -87,5 +87,10 @@
 void sort_ex_table(struct exception_table_entry *start,
 		   struct exception_table_entry *finish);
 
+#ifdef CONFIG_MODVERSIONS
+#define ARCH_RELOCATES_KCRCTAB
+
+extern const unsigned long reloc_start[];
+#endif
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_MODULE_H */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 8c34149..cbd759e 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -140,6 +140,8 @@
 extern void user_enable_block_step(struct task_struct *);
 extern void user_disable_single_step(struct task_struct *);
 
+#define ARCH_HAS_USER_SINGLE_STEP_INFO
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h
index cd21e5e..11ae699 100644
--- a/arch/powerpc/include/asm/udbg.h
+++ b/arch/powerpc/include/asm/udbg.h
@@ -51,6 +51,7 @@
 extern void __init udbg_init_44x_as1(void);
 extern void __init udbg_init_40x_realmode(void);
 extern void __init udbg_init_cpm(void);
+extern void __init udbg_init_usbgecko(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UDBG_H */
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 03c862b..2fc82ba 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -697,9 +697,9 @@
 		.machine_check		= machine_check_generic,
 		.platform		= "ppc750",
 	},
-	{	/* 750CL */
-		.pvr_mask		= 0xfffff0f0,
-		.pvr_value		= 0x00087010,
+	{	/* 750CL (and "Broadway") */
+		.pvr_mask		= 0xfffff0e0,
+		.pvr_value		= 0x00087000,
 		.cpu_name		= "750CL",
 		.cpu_features		= CPU_FTRS_750CL,
 		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 829c3fe..e025e89 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -164,6 +164,9 @@
 #ifdef CONFIG_PPC_EARLY_DEBUG_CPM
 	bl	setup_cpm_bat
 #endif
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+	bl	setup_usbgecko_bat
+#endif
 
 /*
  * Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -1203,6 +1206,28 @@
 	blr
 #endif
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+setup_usbgecko_bat:
+	/* prepare a BAT for early io */
+#if defined(CONFIG_GAMECUBE)
+	lis	r8, 0x0c00
+#elif defined(CONFIG_WII)
+	lis	r8, 0x0d00
+#else
+#error Invalid platform for USB Gecko based early debugging.
+#endif
+	/*
+	 * The virtual address used must match the virtual address
+	 * associated to the fixmap entry FIX_EARLY_DEBUG_BASE.
+	 */
+	lis	r11, 0xfffe	/* top 128K */
+	ori	r8, r8, 0x002a	/* uncached, guarded ,rw */
+	ori	r11, r11, 0x2	/* 128K, Vs=1, Vp=0 */
+	mtspr	SPRN_DBAT1L, r8
+	mtspr	SPRN_DBAT1U, r11
+	blr
+#endif
+
 #ifdef CONFIG_8260
 /* Jump into the system reset for the rom.
  * We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index fd51578..5547ae6 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -30,7 +30,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/dma-mapping.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/iommu-helper.h>
 #include <linux/crash_dump.h>
 #include <asm/io.h>
@@ -251,7 +251,7 @@
 	}
 
 	ppc_md.tce_free(tbl, entry, npages);
-	iommu_area_free(tbl->it_map, free_entry, npages);
+	bitmap_clear(tbl->it_map, free_entry, npages);
 }
 
 static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 804f0f3..d069ff8 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -174,6 +174,15 @@
 	return 0;
 }
 
+void user_single_step_siginfo(struct task_struct *tsk,
+				struct pt_regs *regs, siginfo_t *info)
+{
+	memset(info, 0, sizeof(*info));
+	info->si_signo = SIGTRAP;
+	info->si_code = TRAP_TRACE;
+	info->si_addr = (void __user *)regs->nip;
+}
+
 void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
 {
 	siginfo_t info;
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index fc9af47..e39cad8 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -60,6 +60,8 @@
 	udbg_init_40x_realmode();
 #elif defined(CONFIG_PPC_EARLY_DEBUG_CPM)
 	udbg_init_cpm();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_USBGECKO)
+	udbg_init_usbgecko();
 #endif
 
 #ifdef CONFIG_PPC_EARLY_DEBUG
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 27735a7..dcd01c8 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -38,6 +38,9 @@
 #endif
 SECTIONS
 {
+	. = 0;
+	reloc_start = .;
+
 	. = KERNELBASE;
 
 /*
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c
index f5e7b9c..08dfa8e 100644
--- a/arch/powerpc/mm/40x_mmu.c
+++ b/arch/powerpc/mm/40x_mmu.c
@@ -91,7 +91,7 @@
 #define LARGE_PAGE_SIZE_16M	(1<<24)
 #define LARGE_PAGE_SIZE_4M	(1<<22)
 
-unsigned long __init mmu_mapin_ram(void)
+unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	unsigned long v, s, mapped;
 	phys_addr_t p;
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 98052ac..3986264 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -88,7 +88,7 @@
 	flush_instruction_cache();
 }
 
-unsigned long __init mmu_mapin_ram(void)
+unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	unsigned long addr;
 
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index fcfcb6e..c539472 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -207,7 +207,7 @@
 	return amount_mapped;
 }
 
-unsigned long __init mmu_mapin_ram(void)
+unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1;
 }
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 9ddcfb4..4ec900a 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -82,6 +82,11 @@
 int __map_without_bats;
 int __map_without_ltlbs;
 
+/*
+ * This tells the system to allow ioremapping memory marked as reserved.
+ */
+int __allow_ioremap_reserved;
+
 /* max amount of low RAM to map in */
 unsigned long __max_low_memory = MAX_LOW_MEM;
 
@@ -131,9 +136,13 @@
 	MMU_setup();
 
 	if (lmb.memory.cnt > 1) {
+#ifndef CONFIG_WII
 		lmb.memory.cnt = 1;
 		lmb_analyze();
 		printk(KERN_WARNING "Only using first contiguous memory region");
+#else
+		wii_memory_fixups();
+#endif
 	}
 
 	total_lowmem = total_memory = lmb_end_of_DRAM() - memstart_addr;
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index e27a990..d49a775 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -104,6 +104,7 @@
 		   unsigned int size, int flags);
 
 extern int __map_without_bats;
+extern int __allow_ioremap_reserved;
 extern unsigned long ioremap_base;
 extern unsigned int rtas_data, rtas_size;
 
@@ -125,24 +126,32 @@
 extern phys_addr_t memstart_addr;
 extern phys_addr_t lowmem_end_addr;
 
+#ifdef CONFIG_WII
+extern unsigned long wii_hole_start;
+extern unsigned long wii_hole_size;
+
+extern unsigned long wii_mmu_mapin_mem2(unsigned long top);
+extern void wii_memory_fixups(void);
+#endif
+
 /* ...and now those things that may be slightly different between processor
  * architectures.  -- Dan
  */
 #if defined(CONFIG_8xx)
 #define MMU_init_hw()		do { } while(0)
-#define mmu_mapin_ram()		(0UL)
+#define mmu_mapin_ram(top)	(0UL)
 
 #elif defined(CONFIG_4xx)
 extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(void);
+extern unsigned long mmu_mapin_ram(unsigned long top);
 
 #elif defined(CONFIG_FSL_BOOKE)
 extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(void);
+extern unsigned long mmu_mapin_ram(unsigned long top);
 extern void adjust_total_lowmem(void);
 
 #elif defined(CONFIG_PPC32)
 /* anything 32-bit except 4xx or 8xx */
 extern void MMU_init_hw(void);
-extern unsigned long mmu_mapin_ram(void);
+extern unsigned long mmu_mapin_ram(unsigned long top);
 #endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index cb96cb2..177e403 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -26,6 +26,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/lmb.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -191,7 +192,8 @@
 	 * Don't allow anybody to remap normal RAM that we're using.
 	 * mem_init() sets high_memory so only do the check after that.
 	 */
-	if (mem_init_done && (p < virt_to_phys(high_memory))) {
+	if (mem_init_done && (p < virt_to_phys(high_memory)) &&
+	    !(__allow_ioremap_reserved && lmb_is_region_reserved(p, size))) {
 		printk("__ioremap(): phys addr 0x%llx is RAM lr %p\n",
 		       (unsigned long long)p, __builtin_return_address(0));
 		return NULL;
@@ -283,18 +285,18 @@
 }
 
 /*
- * Map in a big chunk of physical memory starting at PAGE_OFFSET.
+ * Map in a chunk of physical memory starting at start.
  */
-void __init mapin_ram(void)
+void __init __mapin_ram_chunk(unsigned long offset, unsigned long top)
 {
 	unsigned long v, s, f;
 	phys_addr_t p;
 	int ktext;
 
-	s = mmu_mapin_ram();
+	s = offset;
 	v = PAGE_OFFSET + s;
 	p = memstart_addr + s;
-	for (; s < total_lowmem; s += PAGE_SIZE) {
+	for (; s < top; s += PAGE_SIZE) {
 		ktext = ((char *) v >= _stext && (char *) v < etext);
 		f = ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL;
 		map_page(v, p, f);
@@ -307,6 +309,30 @@
 	}
 }
 
+void __init mapin_ram(void)
+{
+	unsigned long s, top;
+
+#ifndef CONFIG_WII
+	top = total_lowmem;
+	s = mmu_mapin_ram(top);
+	__mapin_ram_chunk(s, top);
+#else
+	if (!wii_hole_size) {
+		s = mmu_mapin_ram(total_lowmem);
+		__mapin_ram_chunk(s, total_lowmem);
+	} else {
+		top = wii_hole_start;
+		s = mmu_mapin_ram(top);
+		__mapin_ram_chunk(s, top);
+
+		top = lmb_end_of_DRAM();
+		s = wii_mmu_mapin_mem2(top);
+		__mapin_ram_chunk(s, top);
+	}
+#endif
+}
+
 /* 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
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 2d2a87e..f11c2cd 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -72,7 +72,7 @@
 	return 0;
 }
 
-unsigned long __init mmu_mapin_ram(void)
+unsigned long __init mmu_mapin_ram(unsigned long top)
 {
 	unsigned long tot, bl, done;
 	unsigned long max_size = (256<<20);
@@ -86,7 +86,7 @@
 
 	/* Make sure we don't map a block larger than the
 	   smallest alignment of the physical address. */
-	tot = total_lowmem;
+	tot = top;
 	for (bl = 128<<10; bl < max_size; bl <<= 1) {
 		if (bl * 2 > tot)
 			break;
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index bcc69e1..45c0cb9 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -10,7 +10,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/pci.h>
 #include <linux/of.h>
 #include <asm/prom.h>
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 2eab27a..fa0f690 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -311,7 +311,7 @@
 
 config NOT_COHERENT_CACHE
 	bool
-	depends on 4xx || 8xx || E200 || PPC_MPC512x
+	depends on 4xx || 8xx || E200 || PPC_MPC512x || GAMECUBE_COMMON
 	default y
 
 config CHECK_CACHE_COHERENCY
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c
index 9290a7a..fb4eb0d 100644
--- a/arch/powerpc/platforms/amigaone/setup.c
+++ b/arch/powerpc/platforms/amigaone/setup.c
@@ -14,7 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/seq_file.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 #include <asm/machdep.h>
 #include <asm/cputable.h>
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index b93f877..b9d5d67 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -13,10 +13,8 @@
 SPU_AS		:= $(SPU_CROSS)gcc
 SPU_LD		:= $(SPU_CROSS)ld
 SPU_OBJCOPY	:= $(SPU_CROSS)objcopy
-SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include \
-		   -I$(objtree)/include2 -D__KERNEL__
-SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include \
-		   -I$(objtree)/include2 -D__KERNEL__
+SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include -D__KERNEL__
+SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include -D__KERNEL__
 SPU_LDFLAGS	:= -N -Ttext=0x0
 
 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 52f3df3..8f41685 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -23,7 +23,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/adb.h>
 #include <linux/module.h>
 #include <linux/delay.h>
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 291ac9d..524d971 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -90,3 +90,36 @@
 config MPC10X_STORE_GATHERING
 	bool "Enable MPC10x store gathering"
 	depends on MPC10X_BRIDGE
+
+config GAMECUBE_COMMON
+	bool
+
+config USBGECKO_UDBG
+	bool "USB Gecko udbg console for the Nintendo GameCube/Wii"
+	depends on GAMECUBE_COMMON
+	help
+	  If you say yes to this option, support will be included for the
+	  USB Gecko adapter as an udbg console.
+	  The USB Gecko is a EXI to USB Serial converter that can be plugged
+	  into a memcard slot in the Nintendo GameCube/Wii.
+
+	  This driver bypasses the EXI layer completely.
+
+	  If in doubt, say N here.
+
+config GAMECUBE
+	bool "Nintendo-GameCube"
+	depends on EMBEDDED6xx
+	select GAMECUBE_COMMON
+	help
+	  Select GAMECUBE if configuring for the Nintendo GameCube.
+	  More information at: <http://gc-linux.sourceforge.net/>
+
+config WII
+	bool "Nintendo-Wii"
+	depends on EMBEDDED6xx
+	select GAMECUBE_COMMON
+	help
+	  Select WII if configuring for the Nintendo Wii.
+	  More information at: <http://gc-linux.sourceforge.net/>
+
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile
index 0773c08..66c23e4 100644
--- a/arch/powerpc/platforms/embedded6xx/Makefile
+++ b/arch/powerpc/platforms/embedded6xx/Makefile
@@ -7,3 +7,7 @@
 obj-$(CONFIG_PPC_HOLLY)		+= holly.o
 obj-$(CONFIG_PPC_PRPMC2800)	+= prpmc2800.o
 obj-$(CONFIG_PPC_C2K)		+= c2k.o
+obj-$(CONFIG_USBGECKO_UDBG)	+= usbgecko_udbg.o
+obj-$(CONFIG_GAMECUBE_COMMON)	+= flipper-pic.o
+obj-$(CONFIG_GAMECUBE)		+= gamecube.o
+obj-$(CONFIG_WII)		+= wii.o hlwd-pic.o
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
new file mode 100644
index 0000000..d596328
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -0,0 +1,263 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/flipper-pic.c
+ *
+ * Nintendo GameCube/Wii "Flipper" interrupt controller support.
+ * Copyright (C) 2004-2009 The GameCube Linux Team
+ * Copyright (C) 2007,2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 DRV_MODULE_NAME "flipper-pic"
+#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <asm/io.h>
+
+#include "flipper-pic.h"
+
+#define FLIPPER_NR_IRQS		32
+
+/*
+ * Each interrupt has a corresponding bit in both
+ * the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers.
+ *
+ * Enabling/disabling an interrupt line involves setting/clearing
+ * the corresponding bit in IMR.
+ * Except for the RSW interrupt, all interrupts get deasserted automatically
+ * when the source deasserts the interrupt.
+ */
+#define FLIPPER_ICR		0x00
+#define FLIPPER_ICR_RSS		(1<<16) /* reset switch state */
+
+#define FLIPPER_IMR		0x04
+
+#define FLIPPER_RESET		0x24
+
+
+/*
+ * IRQ chip hooks.
+ *
+ */
+
+static void flipper_pic_mask_and_ack(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+	u32 mask = 1 << irq;
+
+	clrbits32(io_base + FLIPPER_IMR, mask);
+	/* this is at least needed for RSW */
+	out_be32(io_base + FLIPPER_ICR, mask);
+}
+
+static void flipper_pic_ack(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	/* this is at least needed for RSW */
+	out_be32(io_base + FLIPPER_ICR, 1 << irq);
+}
+
+static void flipper_pic_mask(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	clrbits32(io_base + FLIPPER_IMR, 1 << irq);
+}
+
+static void flipper_pic_unmask(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	setbits32(io_base + FLIPPER_IMR, 1 << irq);
+}
+
+
+static struct irq_chip flipper_pic = {
+	.name		= "flipper-pic",
+	.ack		= flipper_pic_ack,
+	.mask_ack	= flipper_pic_mask_and_ack,
+	.mask		= flipper_pic_mask,
+	.unmask		= flipper_pic_unmask,
+};
+
+/*
+ * IRQ host hooks.
+ *
+ */
+
+static struct irq_host *flipper_irq_host;
+
+static int flipper_pic_map(struct irq_host *h, unsigned int virq,
+			   irq_hw_number_t hwirq)
+{
+	set_irq_chip_data(virq, h->host_data);
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq);
+	return 0;
+}
+
+static void flipper_pic_unmap(struct irq_host *h, unsigned int irq)
+{
+	set_irq_chip_data(irq, NULL);
+	set_irq_chip(irq, NULL);
+}
+
+static int flipper_pic_match(struct irq_host *h, struct device_node *np)
+{
+	return 1;
+}
+
+
+static struct irq_host_ops flipper_irq_host_ops = {
+	.map = flipper_pic_map,
+	.unmap = flipper_pic_unmap,
+	.match = flipper_pic_match,
+};
+
+/*
+ * Platform hooks.
+ *
+ */
+
+static void __flipper_quiesce(void __iomem *io_base)
+{
+	/* mask and ack all IRQs */
+	out_be32(io_base + FLIPPER_IMR, 0x00000000);
+	out_be32(io_base + FLIPPER_ICR, 0xffffffff);
+}
+
+struct irq_host * __init flipper_pic_init(struct device_node *np)
+{
+	struct device_node *pi;
+	struct irq_host *irq_host = NULL;
+	struct resource res;
+	void __iomem *io_base;
+	int retval;
+
+	pi = of_get_parent(np);
+	if (!pi) {
+		pr_err("no parent found\n");
+		goto out;
+	}
+	if (!of_device_is_compatible(pi, "nintendo,flipper-pi")) {
+		pr_err("unexpected parent compatible\n");
+		goto out;
+	}
+
+	retval = of_address_to_resource(pi, 0, &res);
+	if (retval) {
+		pr_err("no io memory range found\n");
+		goto out;
+	}
+	io_base = ioremap(res.start, resource_size(&res));
+
+	pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
+
+	__flipper_quiesce(io_base);
+
+	irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, FLIPPER_NR_IRQS,
+				  &flipper_irq_host_ops, -1);
+	if (!irq_host) {
+		pr_err("failed to allocate irq_host\n");
+		return NULL;
+	}
+
+	irq_host->host_data = io_base;
+
+out:
+	return irq_host;
+}
+
+unsigned int flipper_pic_get_irq(void)
+{
+	void __iomem *io_base = flipper_irq_host->host_data;
+	int irq;
+	u32 irq_status;
+
+	irq_status = in_be32(io_base + FLIPPER_ICR) &
+		     in_be32(io_base + FLIPPER_IMR);
+	if (irq_status == 0)
+		return NO_IRQ;	/* no more IRQs pending */
+
+	irq = __ffs(irq_status);
+	return irq_linear_revmap(flipper_irq_host, irq);
+}
+
+/*
+ * Probe function.
+ *
+ */
+
+void __init flipper_pic_probe(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-pic");
+	BUG_ON(!np);
+
+	flipper_irq_host = flipper_pic_init(np);
+	BUG_ON(!flipper_irq_host);
+
+	irq_set_default_host(flipper_irq_host);
+
+	of_node_put(np);
+}
+
+/*
+ * Misc functions related to the flipper chipset.
+ *
+ */
+
+/**
+ * flipper_quiesce() - quiesce flipper irq controller
+ *
+ * Mask and ack all interrupt sources.
+ *
+ */
+void flipper_quiesce(void)
+{
+	void __iomem *io_base = flipper_irq_host->host_data;
+
+	__flipper_quiesce(io_base);
+}
+
+/*
+ * Resets the platform.
+ */
+void flipper_platform_reset(void)
+{
+	void __iomem *io_base;
+
+	if (flipper_irq_host && flipper_irq_host->host_data) {
+		io_base = flipper_irq_host->host_data;
+		out_8(io_base + FLIPPER_RESET, 0x00);
+	}
+}
+
+/*
+ * Returns non-zero if the reset button is pressed.
+ */
+int flipper_is_reset_button_pressed(void)
+{
+	void __iomem *io_base;
+	u32 icr;
+
+	if (flipper_irq_host && flipper_irq_host->host_data) {
+		io_base = flipper_irq_host->host_data;
+		icr = in_be32(io_base + FLIPPER_ICR);
+		return !(icr & FLIPPER_ICR_RSS);
+	}
+	return 0;
+}
+
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.h b/arch/powerpc/platforms/embedded6xx/flipper-pic.h
new file mode 100644
index 0000000..e339186
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.h
@@ -0,0 +1,25 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/flipper-pic.h
+ *
+ * Nintendo GameCube/Wii "Flipper" interrupt controller support.
+ * Copyright (C) 2004-2009 The GameCube Linux Team
+ * Copyright (C) 2007,2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __FLIPPER_PIC_H
+#define __FLIPPER_PIC_H
+
+unsigned int flipper_pic_get_irq(void);
+void __init flipper_pic_probe(void);
+
+void flipper_quiesce(void);
+void flipper_platform_reset(void);
+int flipper_is_reset_button_pressed(void);
+
+#endif
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c
new file mode 100644
index 0000000..1106fd9
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/gamecube.c
@@ -0,0 +1,118 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/gamecube.c
+ *
+ * Nintendo GameCube board-specific support
+ * Copyright (C) 2004-2009 The GameCube Linux Team
+ * Copyright (C) 2007,2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/init.h>
+#include <linux/irq.h>
+#include <linux/kexec.h>
+#include <linux/seq_file.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+#include "flipper-pic.h"
+#include "usbgecko_udbg.h"
+
+
+static void gamecube_spin(void)
+{
+	/* spin until power button pressed */
+	for (;;)
+		cpu_relax();
+}
+
+static void gamecube_restart(char *cmd)
+{
+	local_irq_disable();
+	flipper_platform_reset();
+	gamecube_spin();
+}
+
+static void gamecube_power_off(void)
+{
+	local_irq_disable();
+	gamecube_spin();
+}
+
+static void gamecube_halt(void)
+{
+	gamecube_restart(NULL);
+}
+
+static void __init gamecube_init_early(void)
+{
+	ug_udbg_init();
+}
+
+static int __init gamecube_probe(void)
+{
+	unsigned long dt_root;
+
+	dt_root = of_get_flat_dt_root();
+	if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube"))
+		return 0;
+
+	return 1;
+}
+
+static void gamecube_shutdown(void)
+{
+	flipper_quiesce();
+}
+
+#ifdef CONFIG_KEXEC
+static int gamecube_kexec_prepare(struct kimage *image)
+{
+	return 0;
+}
+#endif /* CONFIG_KEXEC */
+
+
+define_machine(gamecube) {
+	.name			= "gamecube",
+	.probe			= gamecube_probe,
+	.init_early		= gamecube_init_early,
+	.restart		= gamecube_restart,
+	.power_off		= gamecube_power_off,
+	.halt			= gamecube_halt,
+	.init_IRQ		= flipper_pic_probe,
+	.get_irq		= flipper_pic_get_irq,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.machine_shutdown	= gamecube_shutdown,
+#ifdef CONFIG_KEXEC
+	.machine_kexec_prepare	= gamecube_kexec_prepare,
+#endif
+};
+
+
+static struct of_device_id gamecube_of_bus[] = {
+	{ .compatible = "nintendo,flipper", },
+	{ },
+};
+
+static int __init gamecube_device_probe(void)
+{
+	if (!machine_is(gamecube))
+		return 0;
+
+	of_platform_bus_probe(NULL, gamecube_of_bus, NULL);
+	return 0;
+}
+device_initcall(gamecube_device_probe);
+
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
new file mode 100644
index 0000000..dd20bff
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -0,0 +1,241 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+ *
+ * Nintendo Wii "Hollywood" interrupt controller support.
+ * Copyright (C) 2009 The GameCube Linux Team
+ * Copyright (C) 2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 DRV_MODULE_NAME "hlwd-pic"
+#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <asm/io.h>
+
+#include "hlwd-pic.h"
+
+#define HLWD_NR_IRQS	32
+
+/*
+ * Each interrupt has a corresponding bit in both
+ * the Interrupt Cause (ICR) and Interrupt Mask (IMR) registers.
+ *
+ * Enabling/disabling an interrupt line involves asserting/clearing
+ * the corresponding bit in IMR. ACK'ing a request simply involves
+ * asserting the corresponding bit in ICR.
+ */
+#define HW_BROADWAY_ICR		0x00
+#define HW_BROADWAY_IMR		0x04
+
+
+/*
+ * IRQ chip hooks.
+ *
+ */
+
+static void hlwd_pic_mask_and_ack(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+	u32 mask = 1 << irq;
+
+	clrbits32(io_base + HW_BROADWAY_IMR, mask);
+	out_be32(io_base + HW_BROADWAY_ICR, mask);
+}
+
+static void hlwd_pic_ack(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
+}
+
+static void hlwd_pic_mask(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
+}
+
+static void hlwd_pic_unmask(unsigned int virq)
+{
+	int irq = virq_to_hw(virq);
+	void __iomem *io_base = get_irq_chip_data(virq);
+
+	setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
+}
+
+
+static struct irq_chip hlwd_pic = {
+	.name		= "hlwd-pic",
+	.ack		= hlwd_pic_ack,
+	.mask_ack	= hlwd_pic_mask_and_ack,
+	.mask		= hlwd_pic_mask,
+	.unmask		= hlwd_pic_unmask,
+};
+
+/*
+ * IRQ host hooks.
+ *
+ */
+
+static struct irq_host *hlwd_irq_host;
+
+static int hlwd_pic_map(struct irq_host *h, unsigned int virq,
+			   irq_hw_number_t hwirq)
+{
+	set_irq_chip_data(virq, h->host_data);
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
+	return 0;
+}
+
+static void hlwd_pic_unmap(struct irq_host *h, unsigned int irq)
+{
+	set_irq_chip_data(irq, NULL);
+	set_irq_chip(irq, NULL);
+}
+
+static struct irq_host_ops hlwd_irq_host_ops = {
+	.map = hlwd_pic_map,
+	.unmap = hlwd_pic_unmap,
+};
+
+static unsigned int __hlwd_pic_get_irq(struct irq_host *h)
+{
+	void __iomem *io_base = h->host_data;
+	int irq;
+	u32 irq_status;
+
+	irq_status = in_be32(io_base + HW_BROADWAY_ICR) &
+		     in_be32(io_base + HW_BROADWAY_IMR);
+	if (irq_status == 0)
+		return NO_IRQ;	/* no more IRQs pending */
+
+	irq = __ffs(irq_status);
+	return irq_linear_revmap(h, irq);
+}
+
+static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
+				      struct irq_desc *desc)
+{
+	struct irq_host *irq_host = get_irq_data(cascade_virq);
+	unsigned int virq;
+
+	spin_lock(&desc->lock);
+	desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
+	spin_unlock(&desc->lock);
+
+	virq = __hlwd_pic_get_irq(irq_host);
+	if (virq != NO_IRQ)
+		generic_handle_irq(virq);
+	else
+		pr_err("spurious interrupt!\n");
+
+	spin_lock(&desc->lock);
+	desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
+	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
+		desc->chip->unmask(cascade_virq);
+	spin_unlock(&desc->lock);
+}
+
+/*
+ * Platform hooks.
+ *
+ */
+
+static void __hlwd_quiesce(void __iomem *io_base)
+{
+	/* mask and ack all IRQs */
+	out_be32(io_base + HW_BROADWAY_IMR, 0);
+	out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff);
+}
+
+struct irq_host *hlwd_pic_init(struct device_node *np)
+{
+	struct irq_host *irq_host;
+	struct resource res;
+	void __iomem *io_base;
+	int retval;
+
+	retval = of_address_to_resource(np, 0, &res);
+	if (retval) {
+		pr_err("no io memory range found\n");
+		return NULL;
+	}
+	io_base = ioremap(res.start, resource_size(&res));
+	if (!io_base) {
+		pr_err("ioremap failed\n");
+		return NULL;
+	}
+
+	pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
+
+	__hlwd_quiesce(io_base);
+
+	irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, HLWD_NR_IRQS,
+				  &hlwd_irq_host_ops, -1);
+	if (!irq_host) {
+		pr_err("failed to allocate irq_host\n");
+		return NULL;
+	}
+	irq_host->host_data = io_base;
+
+	return irq_host;
+}
+
+unsigned int hlwd_pic_get_irq(void)
+{
+	return __hlwd_pic_get_irq(hlwd_irq_host);
+}
+
+/*
+ * Probe function.
+ *
+ */
+
+void hlwd_pic_probe(void)
+{
+	struct irq_host *host;
+	struct device_node *np;
+	const u32 *interrupts;
+	int cascade_virq;
+
+	for_each_compatible_node(np, NULL, "nintendo,hollywood-pic") {
+		interrupts = of_get_property(np, "interrupts", NULL);
+		if (interrupts) {
+			host = hlwd_pic_init(np);
+			BUG_ON(!host);
+			cascade_virq = irq_of_parse_and_map(np, 0);
+			set_irq_data(cascade_virq, host);
+			set_irq_chained_handler(cascade_virq,
+						hlwd_pic_irq_cascade);
+			hlwd_irq_host = host;
+			break;
+		}
+	}
+}
+
+/**
+ * hlwd_quiesce() - quiesce hollywood irq controller
+ *
+ * Mask and ack all interrupt sources.
+ *
+ */
+void hlwd_quiesce(void)
+{
+	void __iomem *io_base = hlwd_irq_host->host_data;
+
+	__hlwd_quiesce(io_base);
+}
+
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.h b/arch/powerpc/platforms/embedded6xx/hlwd-pic.h
new file mode 100644
index 0000000..d2e5a09
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.h
@@ -0,0 +1,22 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/hlwd-pic.h
+ *
+ * Nintendo Wii "Hollywood" interrupt controller support.
+ * Copyright (C) 2009 The GameCube Linux Team
+ * Copyright (C) 2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __HLWD_PIC_H
+#define __HLWD_PIC_H
+
+extern unsigned int hlwd_pic_get_irq(void);
+extern void hlwd_pic_probe(void);
+extern void hlwd_quiesce(void);
+
+#endif
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
new file mode 100644
index 0000000..edc956c
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
@@ -0,0 +1,328 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
+ *
+ * udbg serial input/output routines for the USB Gecko adapter.
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 <mm/mmu_decl.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/fixmap.h>
+
+#include "usbgecko_udbg.h"
+
+
+#define EXI_CLK_32MHZ           5
+
+#define EXI_CSR                 0x00
+#define   EXI_CSR_CLKMASK       (0x7<<4)
+#define     EXI_CSR_CLK_32MHZ   (EXI_CLK_32MHZ<<4)
+#define   EXI_CSR_CSMASK        (0x7<<7)
+#define     EXI_CSR_CS_0        (0x1<<7)  /* Chip Select 001 */
+
+#define EXI_CR                  0x0c
+#define   EXI_CR_TSTART         (1<<0)
+#define   EXI_CR_WRITE		(1<<2)
+#define   EXI_CR_READ_WRITE     (2<<2)
+#define   EXI_CR_TLEN(len)      (((len)-1)<<4)
+
+#define EXI_DATA                0x10
+
+#define UG_READ_ATTEMPTS	100
+#define UG_WRITE_ATTEMPTS	100
+
+
+static void __iomem *ug_io_base;
+
+/*
+ * Performs one input/output transaction between the exi host and the usbgecko.
+ */
+static u32 ug_io_transaction(u32 in)
+{
+	u32 __iomem *csr_reg = ug_io_base + EXI_CSR;
+	u32 __iomem *data_reg = ug_io_base + EXI_DATA;
+	u32 __iomem *cr_reg = ug_io_base + EXI_CR;
+	u32 csr, data, cr;
+
+	/* select */
+	csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
+	out_be32(csr_reg, csr);
+
+	/* read/write */
+	data = in;
+	out_be32(data_reg, data);
+	cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
+	out_be32(cr_reg, cr);
+
+	while (in_be32(cr_reg) & EXI_CR_TSTART)
+		barrier();
+
+	/* deselect */
+	out_be32(csr_reg, 0);
+
+	/* result */
+	data = in_be32(data_reg);
+
+	return data;
+}
+
+/*
+ * Returns true if an usbgecko adapter is found.
+ */
+static int ug_is_adapter_present(void)
+{
+	if (!ug_io_base)
+		return 0;
+
+	return ug_io_transaction(0x90000000) == 0x04700000;
+}
+
+/*
+ * Returns true if the TX fifo is ready for transmission.
+ */
+static int ug_is_txfifo_ready(void)
+{
+	return ug_io_transaction(0xc0000000) & 0x04000000;
+}
+
+/*
+ * Tries to transmit a character.
+ * If the TX fifo is not ready the result is undefined.
+ */
+static void ug_raw_putc(char ch)
+{
+	ug_io_transaction(0xb0000000 | (ch << 20));
+}
+
+/*
+ * Transmits a character.
+ * It silently fails if the TX fifo is not ready after a number of retries.
+ */
+static void ug_putc(char ch)
+{
+	int count = UG_WRITE_ATTEMPTS;
+
+	if (!ug_io_base)
+		return;
+
+	if (ch == '\n')
+		ug_putc('\r');
+
+	while (!ug_is_txfifo_ready() && count--)
+		barrier();
+	if (count)
+		ug_raw_putc(ch);
+}
+
+/*
+ * Returns true if the RX fifo is ready for transmission.
+ */
+static int ug_is_rxfifo_ready(void)
+{
+	return ug_io_transaction(0xd0000000) & 0x04000000;
+}
+
+/*
+ * Tries to receive a character.
+ * If a character is unavailable the function returns -1.
+ */
+static int ug_raw_getc(void)
+{
+	u32 data = ug_io_transaction(0xa0000000);
+	if (data & 0x08000000)
+		return (data >> 16) & 0xff;
+	else
+		return -1;
+}
+
+/*
+ * Receives a character.
+ * It fails if the RX fifo is not ready after a number of retries.
+ */
+static int ug_getc(void)
+{
+	int count = UG_READ_ATTEMPTS;
+
+	if (!ug_io_base)
+		return -1;
+
+	while (!ug_is_rxfifo_ready() && count--)
+		barrier();
+	return ug_raw_getc();
+}
+
+/*
+ * udbg functions.
+ *
+ */
+
+/*
+ * Transmits a character.
+ */
+void ug_udbg_putc(char ch)
+{
+	ug_putc(ch);
+}
+
+/*
+ * Receives a character. Waits until a character is available.
+ */
+static int ug_udbg_getc(void)
+{
+	int ch;
+
+	while ((ch = ug_getc()) == -1)
+		barrier();
+	return ch;
+}
+
+/*
+ * Receives a character. If a character is not available, returns -1.
+ */
+static int ug_udbg_getc_poll(void)
+{
+	if (!ug_is_rxfifo_ready())
+		return -1;
+	return ug_getc();
+}
+
+/*
+ * Retrieves and prepares the virtual address needed to access the hardware.
+ */
+static void __iomem *ug_udbg_setup_exi_io_base(struct device_node *np)
+{
+	void __iomem *exi_io_base = NULL;
+	phys_addr_t paddr;
+	const unsigned int *reg;
+
+	reg = of_get_property(np, "reg", NULL);
+	if (reg) {
+		paddr = of_translate_address(np, reg);
+		if (paddr)
+			exi_io_base = ioremap(paddr, reg[1]);
+	}
+	return exi_io_base;
+}
+
+/*
+ * Checks if a USB Gecko adapter is inserted in any memory card slot.
+ */
+static void __iomem *ug_udbg_probe(void __iomem *exi_io_base)
+{
+	int i;
+
+	/* look for a usbgecko on memcard slots A and B */
+	for (i = 0; i < 2; i++) {
+		ug_io_base = exi_io_base + 0x14 * i;
+		if (ug_is_adapter_present())
+			break;
+	}
+	if (i == 2)
+		ug_io_base = NULL;
+	return ug_io_base;
+
+}
+
+/*
+ * USB Gecko udbg support initialization.
+ */
+void __init ug_udbg_init(void)
+{
+	struct device_node *np;
+	void __iomem *exi_io_base;
+
+	if (ug_io_base)
+		udbg_printf("%s: early -> final\n", __func__);
+
+	np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi");
+	if (!np) {
+		udbg_printf("%s: EXI node not found\n", __func__);
+		goto done;
+	}
+
+	exi_io_base = ug_udbg_setup_exi_io_base(np);
+	if (!exi_io_base) {
+		udbg_printf("%s: failed to setup EXI io base\n", __func__);
+		goto done;
+	}
+
+	if (!ug_udbg_probe(exi_io_base)) {
+		udbg_printf("usbgecko_udbg: not found\n");
+		iounmap(exi_io_base);
+	} else {
+		udbg_putc = ug_udbg_putc;
+		udbg_getc = ug_udbg_getc;
+		udbg_getc_poll = ug_udbg_getc_poll;
+		udbg_printf("usbgecko_udbg: ready\n");
+	}
+
+done:
+	if (np)
+		of_node_put(np);
+	return;
+}
+
+#ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
+
+static phys_addr_t __init ug_early_grab_io_addr(void)
+{
+#if defined(CONFIG_GAMECUBE)
+	return 0x0c000000;
+#elif defined(CONFIG_WII)
+	return 0x0d000000;
+#else
+#error Invalid platform for USB Gecko based early debugging.
+#endif
+}
+
+/*
+ * USB Gecko early debug support initialization for udbg.
+ */
+void __init udbg_init_usbgecko(void)
+{
+	void __iomem *early_debug_area;
+	void __iomem *exi_io_base;
+
+	/*
+	 * At this point we have a BAT already setup that enables I/O
+	 * to the EXI hardware.
+	 *
+	 * The BAT uses a virtual address range reserved at the fixmap.
+	 * This must match the virtual address configured in
+	 * head_32.S:setup_usbgecko_bat().
+	 */
+	early_debug_area = (void __iomem *)__fix_to_virt(FIX_EARLY_DEBUG_BASE);
+	exi_io_base = early_debug_area + 0x00006800;
+
+	/* try to detect a USB Gecko */
+	if (!ug_udbg_probe(exi_io_base))
+		return;
+
+	/* we found a USB Gecko, load udbg hooks */
+	udbg_putc = ug_udbg_putc;
+	udbg_getc = ug_udbg_getc;
+	udbg_getc_poll = ug_udbg_getc_poll;
+
+	/*
+	 * Prepare again the same BAT for MMU_init.
+	 * This allows udbg I/O to continue working after the MMU is
+	 * turned on for real.
+	 * It is safe to continue using the same virtual address as it is
+	 * a reserved fixmap area.
+	 */
+	setbat(1, (unsigned long)early_debug_area,
+	       ug_early_grab_io_addr(), 128*1024, PAGE_KERNEL_NCG);
+}
+
+#endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */
+
diff --git a/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
new file mode 100644
index 0000000..bb6cde4
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
@@ -0,0 +1,32 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/usbgecko_udbg.h
+ *
+ * udbg serial input/output routines for the USB Gecko adapter.
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __USBGECKO_UDBG_H
+#define __USBGECKO_UDBG_H
+
+#ifdef CONFIG_USBGECKO_UDBG
+
+extern void __init ug_udbg_init(void);
+
+#else
+
+static inline void __init ug_udbg_init(void)
+{
+}
+
+#endif /* CONFIG_USBGECKO_UDBG */
+
+void __init udbg_init_usbgecko(void);
+
+#endif /* __USBGECKO_UDBG_H */
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
new file mode 100644
index 0000000..57e5b60
--- /dev/null
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -0,0 +1,268 @@
+/*
+ * arch/powerpc/platforms/embedded6xx/wii.c
+ *
+ * Nintendo Wii board-specific support
+ * Copyright (C) 2008-2009 The GameCube Linux Team
+ * Copyright (C) 2008,2009 Albert Herranz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 DRV_MODULE_NAME "wii"
+#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/kexec.h>
+#include <linux/of_platform.h>
+#include <linux/lmb.h>
+#include <mm/mmu_decl.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+#include "flipper-pic.h"
+#include "hlwd-pic.h"
+#include "usbgecko_udbg.h"
+
+/* control block */
+#define HW_CTRL_COMPATIBLE	"nintendo,hollywood-control"
+
+#define HW_CTRL_RESETS		0x94
+#define HW_CTRL_RESETS_SYS	(1<<0)
+
+/* gpio */
+#define HW_GPIO_COMPATIBLE	"nintendo,hollywood-gpio"
+
+#define HW_GPIO_BASE(idx)	(idx * 0x20)
+#define HW_GPIO_OUT(idx)	(HW_GPIO_BASE(idx) + 0)
+#define HW_GPIO_DIR(idx)	(HW_GPIO_BASE(idx) + 4)
+
+#define HW_GPIO_SHUTDOWN	(1<<1)
+#define HW_GPIO_SLOT_LED	(1<<5)
+#define HW_GPIO_SENSOR_BAR	(1<<8)
+
+
+static void __iomem *hw_ctrl;
+static void __iomem *hw_gpio;
+
+unsigned long wii_hole_start;
+unsigned long wii_hole_size;
+
+
+static int __init page_aligned(unsigned long x)
+{
+	return !(x & (PAGE_SIZE-1));
+}
+
+void __init wii_memory_fixups(void)
+{
+	struct lmb_property *p = lmb.memory.region;
+
+	/*
+	 * This is part of a workaround to allow the use of two
+	 * discontiguous RAM ranges on the Wii, even if this is
+	 * currently unsupported on 32-bit PowerPC Linux.
+	 *
+	 * We coealesce the two memory ranges of the Wii into a
+	 * single range, then create a reservation for the "hole"
+	 * between both ranges.
+	 */
+
+	BUG_ON(lmb.memory.cnt != 2);
+	BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
+
+	p[0].size = _ALIGN_DOWN(p[0].size, PAGE_SIZE);
+	p[1].size = _ALIGN_DOWN(p[1].size, PAGE_SIZE);
+
+	wii_hole_start = p[0].base + p[0].size;
+	wii_hole_size = p[1].base - wii_hole_start;
+
+	pr_info("MEM1: <%08llx %08llx>\n", p[0].base, p[0].size);
+	pr_info("HOLE: <%08lx %08lx>\n", wii_hole_start, wii_hole_size);
+	pr_info("MEM2: <%08llx %08llx>\n", p[1].base, p[1].size);
+
+	p[0].size += wii_hole_size + p[1].size;
+
+	lmb.memory.cnt = 1;
+	lmb_analyze();
+
+	/* reserve the hole */
+	lmb_reserve(wii_hole_start, wii_hole_size);
+
+	/* allow ioremapping the address space in the hole */
+	__allow_ioremap_reserved = 1;
+}
+
+unsigned long __init wii_mmu_mapin_mem2(unsigned long top)
+{
+	unsigned long delta, size, bl;
+	unsigned long max_size = (256<<20);
+
+	/* MEM2 64MB@0x10000000 */
+	delta = wii_hole_start + wii_hole_size;
+	size = top - delta;
+	for (bl = 128<<10; bl < max_size; bl <<= 1) {
+		if (bl * 2 > size)
+			break;
+	}
+	setbat(4, PAGE_OFFSET+delta, delta, bl, PAGE_KERNEL_X);
+	return delta + bl;
+}
+
+static void wii_spin(void)
+{
+	local_irq_disable();
+	for (;;)
+		cpu_relax();
+}
+
+static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible)
+{
+	void __iomem *hw_regs = NULL;
+	struct device_node *np;
+	struct resource res;
+	int error = -ENODEV;
+
+	np = of_find_compatible_node(NULL, NULL, compatible);
+	if (!np) {
+		pr_err("no compatible node found for %s\n", compatible);
+		goto out;
+	}
+	error = of_address_to_resource(np, 0, &res);
+	if (error) {
+		pr_err("no valid reg found for %s\n", np->name);
+		goto out_put;
+	}
+
+	hw_regs = ioremap(res.start, resource_size(&res));
+	if (hw_regs) {
+		pr_info("%s at 0x%08x mapped to 0x%p\n", name,
+			res.start, hw_regs);
+	}
+
+out_put:
+	of_node_put(np);
+out:
+	return hw_regs;
+}
+
+static void __init wii_setup_arch(void)
+{
+	hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE);
+	hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE);
+	if (hw_gpio) {
+		/* turn off the front blue led and IR light */
+		clrbits32(hw_gpio + HW_GPIO_OUT(0),
+			  HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
+	}
+}
+
+static void wii_restart(char *cmd)
+{
+	local_irq_disable();
+
+	if (hw_ctrl) {
+		/* clear the system reset pin to cause a reset */
+		clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS);
+	}
+	wii_spin();
+}
+
+static void wii_power_off(void)
+{
+	local_irq_disable();
+
+	if (hw_gpio) {
+		/* make sure that the poweroff GPIO is configured as output */
+		setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN);
+
+		/* drive the poweroff GPIO high */
+		setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN);
+	}
+	wii_spin();
+}
+
+static void wii_halt(void)
+{
+	if (ppc_md.restart)
+		ppc_md.restart(NULL);
+	wii_spin();
+}
+
+static void __init wii_init_early(void)
+{
+	ug_udbg_init();
+}
+
+static void __init wii_pic_probe(void)
+{
+	flipper_pic_probe();
+	hlwd_pic_probe();
+}
+
+static int __init wii_probe(void)
+{
+	unsigned long dt_root;
+
+	dt_root = of_get_flat_dt_root();
+	if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
+		return 0;
+
+	return 1;
+}
+
+static void wii_shutdown(void)
+{
+	hlwd_quiesce();
+	flipper_quiesce();
+}
+
+#ifdef CONFIG_KEXEC
+static int wii_machine_kexec_prepare(struct kimage *image)
+{
+	return 0;
+}
+#endif /* CONFIG_KEXEC */
+
+define_machine(wii) {
+	.name			= "wii",
+	.probe			= wii_probe,
+	.init_early		= wii_init_early,
+	.setup_arch		= wii_setup_arch,
+	.restart		= wii_restart,
+	.power_off		= wii_power_off,
+	.halt			= wii_halt,
+	.init_IRQ		= wii_pic_probe,
+	.get_irq		= flipper_pic_get_irq,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+	.machine_shutdown	= wii_shutdown,
+#ifdef CONFIG_KEXEC
+	.machine_kexec_prepare	= wii_machine_kexec_prepare,
+#endif
+};
+
+static struct of_device_id wii_of_bus[] = {
+	{ .compatible = "nintendo,hollywood", },
+	{ },
+};
+
+static int __init wii_device_probe(void)
+{
+	if (!machine_is(wii))
+		return 0;
+
+	of_platform_bus_probe(NULL, wii_of_bus, NULL);
+	return 0;
+}
+device_initcall(wii_device_probe);
+
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index cf66091..9dd789a 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
 #include <asm/page.h>
diff --git a/arch/s390/include/asm/asm-offsets.h b/arch/s390/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/s390/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index e885442..354d426 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -155,7 +155,6 @@
 	} while (0)
 
 #define CORE_DUMP_USE_REGSET
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/score/include/asm/asm-offsets.h b/arch/score/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/score/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/score/include/asm/cacheflush.h b/arch/score/include/asm/cacheflush.h
index caaba24..1d545d0 100644
--- a/arch/score/include/asm/cacheflush.h
+++ b/arch/score/include/asm/cacheflush.h
@@ -14,10 +14,12 @@
 extern void flush_icache_all(void);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void flush_dcache_range(unsigned long start, unsigned long end);
+extern void flush_dcache_page(struct page *page);
+
+#define PG_dcache_dirty         PG_arch_1
 
 #define flush_cache_dup_mm(mm)			do {} while (0)
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
-#define flush_dcache_page(page)			do {} while (0)
 #define flush_dcache_mmap_lock(mapping)		do {} while (0)
 #define flush_dcache_mmap_unlock(mapping)	do {} while (0)
 #define flush_cache_vmap(start, end)		do {} while (0)
diff --git a/arch/score/include/asm/delay.h b/arch/score/include/asm/delay.h
index 6726ec1..529e494 100644
--- a/arch/score/include/asm/delay.h
+++ b/arch/score/include/asm/delay.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SCORE_DELAY_H
 #define _ASM_SCORE_DELAY_H
 
+#include <asm-generic/param.h>
+
 static inline void __delay(unsigned long loops)
 {
 	/* 3 cycles per loop. */
diff --git a/arch/score/include/asm/elf.h b/arch/score/include/asm/elf.h
index 43526d9..f478ce9 100644
--- a/arch/score/include/asm/elf.h
+++ b/arch/score/include/asm/elf.h
@@ -61,7 +61,6 @@
 struct pt_regs;
 
 #define CORE_DUMP_USE_REGSET
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /* This yields a mask that user programs can use to figure out what
diff --git a/arch/score/include/asm/page.h b/arch/score/include/asm/page.h
index d92a5a2..1e9ade8 100644
--- a/arch/score/include/asm/page.h
+++ b/arch/score/include/asm/page.h
@@ -74,7 +74,7 @@
 #define page_to_bus(page)	(page_to_phys(page))
 #define phys_to_page(paddr)	(pfn_to_page(phys_to_pfn(paddr)))
 
-#define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_mapnr)
+#define pfn_valid(pfn)		(((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn))
 
 #define ARCH_PFN_OFFSET		(PAGE_OFFSET >> PAGE_SHIFT)
 
diff --git a/arch/score/kernel/setup.c b/arch/score/kernel/setup.c
index 6a2503c..6f898c0 100644
--- a/arch/score/kernel/setup.c
+++ b/arch/score/kernel/setup.c
@@ -49,6 +49,7 @@
 
 	min_low_pfn = PFN_UP(MEMORY_START);
 	max_low_pfn = PFN_UP(MEMORY_START + MEMORY_SIZE);
+	max_mapnr = max_low_pfn - min_low_pfn;
 
 	/* Initialize the boot-time allocator with low memory only. */
 	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
diff --git a/arch/score/mm/cache.c b/arch/score/mm/cache.c
index dbac9d9..b25e957 100644
--- a/arch/score/mm/cache.c
+++ b/arch/score/mm/cache.c
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/fs.h>
 
 #include <asm/mmu_context.h>
 
@@ -51,6 +52,27 @@
 	}
 }
 
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping = page_mapping(page);
+	unsigned long addr;
+
+	if (PageHighMem(page))
+		return;
+	if (mapping && !mapping_mapped(mapping)) {
+		set_bit(PG_dcache_dirty, &(page)->flags);
+		return;
+	}
+
+	/*
+	 * We could delay the flush for the !page_mapping case too.  But that
+	 * case is for exec env/arg pages and those are %99 certainly going to
+	 * get faulted into the tlb (and thus flushed) anyways.
+	 */
+	addr = (unsigned long) page_address(page);
+	flush_data_cache_page(addr);
+}
+
 /* called by update_mmu_cache. */
 void __update_cache(struct vm_area_struct *vma, unsigned long address,
 		pte_t pte)
@@ -63,11 +85,11 @@
 	if (unlikely(!pfn_valid(pfn)))
 		return;
 	page = pfn_to_page(pfn);
-	if (page_mapping(page) && test_bit(PG_arch_1, &page->flags)) {
+	if (page_mapping(page) && test_bit(PG_dcache_dirty, &(page)->flags)) {
 		addr = (unsigned long) page_address(page);
 		if (exec)
 			flush_data_cache_page(addr);
-		clear_bit(PG_arch_1, &page->flags);
+		clear_bit(PG_dcache_dirty, &(page)->flags);
 	}
 }
 
diff --git a/arch/score/mm/init.c b/arch/score/mm/init.c
index 4e3dcd0..8c15b2c 100644
--- a/arch/score/mm/init.c
+++ b/arch/score/mm/init.c
@@ -83,7 +83,6 @@
 	unsigned long codesize, reservedpages, datasize, initsize;
 	unsigned long tmp, ram = 0;
 
-	max_mapnr = max_low_pfn;
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 	totalram_pages += free_all_bootmem();
 	totalram_pages -= setup_zero_page();	/* Setup zeroed pages. */
@@ -101,10 +100,6 @@
 	datasize = (unsigned long) &_edata - (unsigned long) &_etext;
 	initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
-	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
-	kclist_add(&kcore_vmalloc, (void *) VMALLOC_START,
-			VMALLOC_END - VMALLOC_START);
-
 	printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, "
 			"%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n",
 			(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 55907af..12fec72 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -19,50 +19,6 @@
 	  mask ROM and no flash (WindowsCE machines fall in this category).
 	  If unsure, say N.
 
-config EARLY_SCIF_CONSOLE
-	bool "Use early SCIF console"
-	help
-	  This enables an early console using a fixed SCIF port. This can
-	  be used by platforms that are either not running the SH
-	  standard BIOS, or do not wish to use the BIOS callbacks for the
-	  serial I/O.
-
-config EARLY_SCIF_CONSOLE_PORT
-	hex
-	depends on EARLY_SCIF_CONSOLE
-	default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
-	default "0xa4430000" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
-	default "0xf8420000" if CPU_SUBTYPE_SH7619
-	default "0xff804000" if CPU_SUBTYPE_MXG
-	default "0xffc30000" if CPU_SUBTYPE_SHX3
-	default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
-				CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
-				CPU_SUBTYPE_SH7343
-	default "0xfe4c0000" if CPU_SUBTYPE_SH7757
-	default "0xffeb0000" if CPU_SUBTYPE_SH7785
-	default "0xffeb0000" if CPU_SUBTYPE_SH7786
-	default "0xfffe8000" if CPU_SUBTYPE_SH7203
-	default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
-	default "0xffe80000" if CPU_SH4
-	default "0xa4000150" if CPU_SH3
-	default "0x00000000"
-
-config EARLY_PRINTK
-	bool "Early printk support"
-	depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
-	help
-	  Say Y here to redirect kernel printk messages to the serial port
-	  used by the SH-IPL bootloader, starting very early in the boot
-	  process and ending when the kernel's serial console is initialised.
-	  This option is only useful porting the kernel to a new machine,
-	  when the kernel may crash or hang before the serial console is
-	  initialised. If unsure, say N.
-
-	  On devices that are running SH-IPL and want to keep the port
-	  initialization consistent while not using the BIOS callbacks,
-	  select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
-	  the kernel command line option to toggle back and forth.
-
 config STACK_DEBUG
 	bool "Check for stack overflows"
 	depends on DEBUG_KERNEL && SUPERH32
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index ac17c5a..db91925 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -205,10 +205,7 @@
 
 BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec uImage.bin \
 	       zImage vmlinux.srec romImage
-PHONY += maketools $(BOOT_TARGETS) FORCE
-
-maketools:  include/linux/version.h FORCE
-	$(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h
+PHONY += $(BOOT_TARGETS)
 
 all: $(KBUILD_IMAGE)
 
@@ -217,7 +214,8 @@
 
 compressed: zImage
 
-archprepare: maketools
+archprepare:
+	$(Q)$(MAKE) $(build)=arch/sh/tools include/generated/machtypes.h
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
@@ -234,5 +232,3 @@
 	@echo '  uImage.bz2	           - Kernel-only image for U-Boot (bzip2)'
 	@echo '  uImage.lzma	           - Kernel-only image for U-Boot (lzma)'
 endef
-
-CLEAN_FILES += include/asm-sh/machtypes.h
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index cf9dc12..1f5fa5c 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -316,20 +316,24 @@
 	.format_name = "UYVY",
 	.format_depth = 16,
 	.format = {
-		.pixelformat = V4L2_PIX_FMT_UYVY,
+		.code = V4L2_MBUS_FMT_YUYV8_2X8_BE,
 		.colorspace = V4L2_COLORSPACE_SMPTE170M,
+		.field = V4L2_FIELD_NONE,
 		.width = 640,
 		.height = 480,
 	},
 	.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
-	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8 |
+	SOCAM_DATA_ACTIVE_HIGH,
 	.set_capture = camera_set_capture,
-	.link = {
-		.bus_id		= 0,
-		.add_device	= ap325rxa_camera_add,
-		.del_device	= ap325rxa_camera_del,
-		.module_name	= "soc_camera_platform",
-	},
+};
+
+struct soc_camera_link camera_link = {
+	.bus_id		= 0,
+	.add_device	= ap325rxa_camera_add,
+	.del_device	= ap325rxa_camera_del,
+	.module_name	= "soc_camera_platform",
+	.priv		= &camera_info,
 };
 
 static void dummy_release(struct device *dev)
@@ -347,7 +351,7 @@
 static int ap325rxa_camera_add(struct soc_camera_link *icl,
 			       struct device *dev)
 {
-	if (icl != &camera_info.link || camera_probe() <= 0)
+	if (icl != &camera_link || camera_probe() <= 0)
 		return -ENODEV;
 
 	camera_info.dev = dev;
@@ -357,7 +361,7 @@
 
 static void ap325rxa_camera_del(struct soc_camera_link *icl)
 {
-	if (icl != &camera_info.link)
+	if (icl != &camera_link)
 		return;
 
 	platform_device_unregister(&camera_device);
@@ -470,13 +474,15 @@
 	.buswidth	= SOCAM_DATAWIDTH_8,
 	.flags		= OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP,
 	.edgectrl	= OV772X_AUTO_EDGECTRL(0xf, 0),
-	.link = {
-		.bus_id		= 0,
-		.power		= ov7725_power,
-		.board_info	= &ap325rxa_i2c_camera[0],
-		.i2c_adapter_id	= 0,
-		.module_name	= "ov772x",
-	},
+};
+
+static struct soc_camera_link ov7725_link = {
+	.bus_id		= 0,
+	.power		= ov7725_power,
+	.board_info	= &ap325rxa_i2c_camera[0],
+	.i2c_adapter_id	= 0,
+	.module_name	= "ov772x",
+	.priv		= &ov7725_info,
 };
 
 static struct platform_device ap325rxa_camera[] = {
@@ -484,13 +490,13 @@
 		.name	= "soc-camera-pdrv",
 		.id	= 0,
 		.dev	= {
-			.platform_data = &ov7725_info.link,
+			.platform_data = &ov7725_link,
 		},
 	}, {
 		.name	= "soc-camera-pdrv",
 		.id	= 1,
 		.dev	= {
-			.platform_data = &camera_info.link,
+			.platform_data = &camera_link,
 		},
 	},
 };
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 826e623..194aaca 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -19,11 +19,18 @@
 #include <linux/usb/r8a66597.h>
 #include <linux/i2c.h>
 #include <linux/i2c/tsc2007.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/sh_msiof.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/host.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/mfd/sh_mobile_sdhi.h>
 #include <video/sh_mobile_lcdc.h>
+#include <sound/sh_fsi.h>
 #include <media/sh_mobile_ceu.h>
+#include <media/tw9910.h>
+#include <media/mt9t112.h>
 #include <asm/heartbeat.h>
 #include <asm/sh_eth.h>
 #include <asm/clock.h>
@@ -338,6 +345,12 @@
 };
 
 /* I2C device */
+static struct i2c_board_info i2c0_devices[] = {
+	{
+		I2C_BOARD_INFO("da7210", 0x1a),
+	},
+};
+
 static struct i2c_board_info i2c1_devices[] = {
 	{
 		I2C_BOARD_INFO("r2025sd", 0x32),
@@ -421,6 +434,7 @@
 	.irq		= IRQ0,
 };
 
+#ifdef CONFIG_MFD_SH_MOBILE_SDHI
 /* SHDI0 */
 static void sdhi0_set_pwr(struct platform_device *pdev, int state)
 {
@@ -493,6 +507,248 @@
 	},
 };
 
+#else
+
+static int mmc_spi_get_ro(struct device *dev)
+{
+	return gpio_get_value(GPIO_PTY6);
+}
+
+static int mmc_spi_get_cd(struct device *dev)
+{
+	return !gpio_get_value(GPIO_PTY7);
+}
+
+static void mmc_spi_setpower(struct device *dev, unsigned int maskval)
+{
+	gpio_set_value(GPIO_PTB6, maskval ? 1 : 0);
+}
+
+static struct mmc_spi_platform_data mmc_spi_info = {
+	.get_ro = mmc_spi_get_ro,
+	.get_cd = mmc_spi_get_cd,
+	.caps = MMC_CAP_NEEDS_POLL,
+	.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, /* 3.3V only */
+	.setpower = mmc_spi_setpower,
+};
+
+static struct spi_board_info spi_bus[] = {
+	{
+		.modalias	= "mmc_spi",
+		.platform_data	= &mmc_spi_info,
+		.max_speed_hz	= 5000000,
+		.mode		= SPI_MODE_0,
+		.controller_data = (void *) GPIO_PTM4,
+	},
+};
+
+static struct sh_msiof_spi_info msiof0_data = {
+	.num_chipselect = 1,
+};
+
+static struct resource msiof0_resources[] = {
+	[0] = {
+		.name	= "MSIOF0",
+		.start	= 0xa4c40000,
+		.end	= 0xa4c40063,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 84,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msiof0_device = {
+	.name		= "spi_sh_msiof",
+	.id		= 0, /* MSIOF0 */
+	.dev = {
+		.platform_data = &msiof0_data,
+	},
+	.num_resources	= ARRAY_SIZE(msiof0_resources),
+	.resource	= msiof0_resources,
+	.archdata = {
+		.hwblk_id = HWBLK_MSIOF0,
+	},
+};
+
+#endif
+
+/* I2C Video/Camera */
+static struct i2c_board_info i2c_camera[] = {
+	{
+		I2C_BOARD_INFO("tw9910", 0x45),
+	},
+	{
+		/* 1st camera */
+		I2C_BOARD_INFO("mt9t112", 0x3c),
+	},
+	{
+		/* 2nd camera */
+		I2C_BOARD_INFO("mt9t112", 0x3c),
+	},
+};
+
+/* tw9910 */
+static int tw9910_power(struct device *dev, int mode)
+{
+	int val = mode ? 0 : 1;
+
+	gpio_set_value(GPIO_PTU2, val);
+	if (mode)
+		mdelay(100);
+
+	return 0;
+}
+
+static struct tw9910_video_info tw9910_info = {
+	.buswidth	= SOCAM_DATAWIDTH_8,
+	.mpout		= TW9910_MPO_FIELD,
+};
+
+static struct soc_camera_link tw9910_link = {
+	.i2c_adapter_id	= 0,
+	.bus_id		= 1,
+	.power		= tw9910_power,
+	.board_info	= &i2c_camera[0],
+	.module_name	= "tw9910",
+	.priv		= &tw9910_info,
+};
+
+/* mt9t112 */
+static int mt9t112_power1(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_PTA3, mode);
+	if (mode)
+		mdelay(100);
+
+	return 0;
+}
+
+static struct mt9t112_camera_info mt9t112_info1 = {
+	.flags = MT9T112_FLAG_PCLK_RISING_EDGE | MT9T112_FLAG_DATAWIDTH_8,
+	.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
+};
+
+static struct soc_camera_link mt9t112_link1 = {
+	.i2c_adapter_id	= 0,
+	.power		= mt9t112_power1,
+	.bus_id		= 0,
+	.board_info	= &i2c_camera[1],
+	.module_name	= "mt9t112",
+	.priv		= &mt9t112_info1,
+};
+
+static int mt9t112_power2(struct device *dev, int mode)
+{
+	gpio_set_value(GPIO_PTA4, mode);
+	if (mode)
+		mdelay(100);
+
+	return 0;
+}
+
+static struct mt9t112_camera_info mt9t112_info2 = {
+	.flags = MT9T112_FLAG_PCLK_RISING_EDGE | MT9T112_FLAG_DATAWIDTH_8,
+	.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
+};
+
+static struct soc_camera_link mt9t112_link2 = {
+	.i2c_adapter_id	= 1,
+	.power		= mt9t112_power2,
+	.bus_id		= 1,
+	.board_info	= &i2c_camera[2],
+	.module_name	= "mt9t112",
+	.priv		= &mt9t112_info2,
+};
+
+static struct platform_device camera_devices[] = {
+	{
+		.name	= "soc-camera-pdrv",
+		.id	= 0,
+		.dev	= {
+			.platform_data = &tw9910_link,
+		},
+	},
+	{
+		.name	= "soc-camera-pdrv",
+		.id	= 1,
+		.dev	= {
+			.platform_data = &mt9t112_link1,
+		},
+	},
+	{
+		.name	= "soc-camera-pdrv",
+		.id	= 2,
+		.dev	= {
+			.platform_data = &mt9t112_link2,
+		},
+	},
+};
+
+/* FSI */
+/*
+ * FSI-B use external clock which came from da7210.
+ * So, we should change parent of fsi
+ */
+#define FCLKBCR		0xa415000c
+static void fsimck_init(struct clk *clk)
+{
+	u32 status = ctrl_inl(clk->enable_reg);
+
+	/* use external clock */
+	status &= ~0x000000ff;
+	status |= 0x00000080;
+
+	ctrl_outl(status, clk->enable_reg);
+}
+
+static struct clk_ops fsimck_clk_ops = {
+	.init = fsimck_init,
+};
+
+static struct clk fsimckb_clk = {
+	.name		= "fsimckb_clk",
+	.id		= -1,
+	.ops		= &fsimck_clk_ops,
+	.enable_reg	= (void __iomem *)FCLKBCR,
+	.rate		= 0, /* unknown */
+};
+
+struct sh_fsi_platform_info fsi_info = {
+	.portb_flags = SH_FSI_BRS_INV |
+		       SH_FSI_OUT_SLAVE_MODE |
+		       SH_FSI_IN_SLAVE_MODE |
+		       SH_FSI_OFMT(I2S) |
+		       SH_FSI_IFMT(I2S),
+};
+
+static struct resource fsi_resources[] = {
+	[0] = {
+		.name	= "FSI",
+		.start	= 0xFE3C0000,
+		.end	= 0xFE3C021d,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 108,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device fsi_device = {
+	.name		= "sh_fsi",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(fsi_resources),
+	.resource	= fsi_resources,
+	.dev	= {
+		.platform_data	= &fsi_info,
+	},
+	.archdata = {
+		.hwblk_id = HWBLK_SPU, /* FSI needs SPU hwblk */
+	},
+};
+
 static struct platform_device *ecovec_devices[] __initdata = {
 	&heartbeat_device,
 	&nor_flash_device,
@@ -503,8 +759,16 @@
 	&ceu0_device,
 	&ceu1_device,
 	&keysc_device,
+#ifdef CONFIG_MFD_SH_MOBILE_SDHI
 	&sdhi0_device,
 	&sdhi1_device,
+#else
+	&msiof0_device,
+#endif
+	&camera_devices[0],
+	&camera_devices[1],
+	&camera_devices[2],
+	&fsi_device,
 };
 
 #define EEPROM_ADDR 0x50
@@ -560,6 +824,8 @@
 
 static int __init arch_setup(void)
 {
+	struct clk *clk;
+
 	/* register board specific self-refresh code */
 	sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
 					&ecovec24_sdram_enter_start,
@@ -773,7 +1039,8 @@
 	gpio_direction_input(GPIO_PTR5);
 	gpio_direction_input(GPIO_PTR6);
 
-	/* enable SDHI0 (needs DS2.4 set to ON) */
+#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+	/* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
 	gpio_request(GPIO_FN_SDHI0CD,  NULL);
 	gpio_request(GPIO_FN_SDHI0WP,  NULL);
 	gpio_request(GPIO_FN_SDHI0CMD, NULL);
@@ -785,7 +1052,7 @@
 	gpio_request(GPIO_PTB6, NULL);
 	gpio_direction_output(GPIO_PTB6, 0);
 
-	/* enable SDHI1 (needs DS2.6,7 set to ON,OFF) */
+	/* enable SDHI1 on CN12 (needs DS2.6,7 set to ON,OFF) */
 	gpio_request(GPIO_FN_SDHI1CD,  NULL);
 	gpio_request(GPIO_FN_SDHI1WP,  NULL);
 	gpio_request(GPIO_FN_SDHI1CMD, NULL);
@@ -799,8 +1066,59 @@
 
 	/* I/O buffer drive ability is high for SDHI1 */
 	ctrl_outw((ctrl_inw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA);
+#else
+	/* enable MSIOF0 on CN11 (needs DS2.4 set to OFF) */
+	gpio_request(GPIO_FN_MSIOF0_TXD, NULL);
+	gpio_request(GPIO_FN_MSIOF0_RXD, NULL);
+	gpio_request(GPIO_FN_MSIOF0_TSCK, NULL);
+	gpio_request(GPIO_PTM4, NULL); /* software CS control of TSYNC pin */
+	gpio_direction_output(GPIO_PTM4, 1); /* active low CS */
+	gpio_request(GPIO_PTB6, NULL); /* 3.3V power control */
+	gpio_direction_output(GPIO_PTB6, 0); /* disable power by default */
+	gpio_request(GPIO_PTY6, NULL); /* write protect */
+	gpio_direction_input(GPIO_PTY6);
+	gpio_request(GPIO_PTY7, NULL); /* card detect */
+	gpio_direction_input(GPIO_PTY7);
+
+	spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus));
+#endif
+
+	/* enable Video */
+	gpio_request(GPIO_PTU2, NULL);
+	gpio_direction_output(GPIO_PTU2, 1);
+
+	/* enable Camera */
+	gpio_request(GPIO_PTA3, NULL);
+	gpio_request(GPIO_PTA4, NULL);
+	gpio_direction_output(GPIO_PTA3, 0);
+	gpio_direction_output(GPIO_PTA4, 0);
+
+	/* enable FSI */
+	gpio_request(GPIO_FN_FSIMCKB,    NULL);
+	gpio_request(GPIO_FN_FSIIBSD,    NULL);
+	gpio_request(GPIO_FN_FSIOBSD,    NULL);
+	gpio_request(GPIO_FN_FSIIBBCK,   NULL);
+	gpio_request(GPIO_FN_FSIIBLRCK,  NULL);
+	gpio_request(GPIO_FN_FSIOBBCK,   NULL);
+	gpio_request(GPIO_FN_FSIOBLRCK,  NULL);
+	gpio_request(GPIO_FN_CLKAUDIOBO, NULL);
+
+	/* change parent of FSI B */
+	clk = clk_get(NULL, "fsib_clk");
+	clk_register(&fsimckb_clk);
+	clk_set_parent(clk, &fsimckb_clk);
+	clk_set_rate(clk, 11000);
+	clk_set_rate(&fsimckb_clk, 11000);
+	clk_put(clk);
+
+	gpio_request(GPIO_PTU0, NULL);
+	gpio_direction_output(GPIO_PTU0, 0);
+	mdelay(20);
 
 	/* enable I2C device */
+	i2c_register_board_info(0, i2c0_devices,
+				ARRAY_SIZE(i2c0_devices));
+
 	i2c_register_board_info(1, i2c1_devices,
 				ARRAY_SIZE(i2c1_devices));
 
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index 8ccb1cc..e9b97084 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -273,6 +273,12 @@
 	return 0;
 }
 
+void kfr2r09_lcd_start(void *board_data, void *sohandle,
+		       struct sh_mobile_lcdc_sys_bus_ops *so)
+{
+	write_memory_start(sohandle, so);
+}
+
 #define CTRL_CKSW       0x10
 #define CTRL_C10        0x20
 #define CTRL_CPSW       0x80
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 87438d6..5d7b5d9 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -19,6 +19,7 @@
 #include <linux/input/sh_keysc.h>
 #include <linux/i2c.h>
 #include <linux/usb/r8a66597.h>
+#include <media/rj54n1cb0c.h>
 #include <media/soc_camera.h>
 #include <media/sh_mobile_ceu.h>
 #include <video/sh_mobile_lcdc.h>
@@ -149,6 +150,7 @@
 		},
 		.board_cfg = {
 			.setup_sys = kfr2r09_lcd_setup,
+			.start_transfer = kfr2r09_lcd_start,
 			.display_on = kfr2r09_lcd_on,
 			.display_off = kfr2r09_lcd_off,
 		},
@@ -255,6 +257,9 @@
 
 static struct clk *camera_clk;
 
+/* set VIO_CKO clock to 25MHz */
+#define CEU_MCLK_FREQ 25000000
+
 #define DRVCRB 0xA405018C
 static int camera_power(struct device *dev, int mode)
 {
@@ -267,8 +272,7 @@
 		if (IS_ERR(camera_clk))
 			return PTR_ERR(camera_clk);
 
-		/* set VIO_CKO clock to 25MHz */
-		rate = clk_round_rate(camera_clk, 25000000);
+		rate = clk_round_rate(camera_clk, CEU_MCLK_FREQ);
 		ret = clk_set_rate(camera_clk, rate);
 		if (ret < 0)
 			goto eclkrate;
@@ -318,11 +322,17 @@
 	return ret;
 }
 
+static struct rj54n1_pdata rj54n1_priv = {
+	.mclk_freq	= CEU_MCLK_FREQ,
+	.ioctl_high	= false,
+};
+
 static struct soc_camera_link rj54n1_link = {
 	.power		= camera_power,
 	.board_info	= &kfr2r09_i2c_camera,
 	.i2c_adapter_id	= 1,
 	.module_name	= "rj54n1cb0c",
+	.priv		= &rj54n1_priv,
 };
 
 static struct platform_device kfr2r09_camera = {
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 9099b6d..507c77b 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -432,23 +432,27 @@
 
 static struct ov772x_camera_info ov7725_info = {
 	.buswidth	= SOCAM_DATAWIDTH_8,
-	.link = {
-		.power		= ov7725_power,
-		.board_info	= &migor_i2c_camera[0],
-		.i2c_adapter_id	= 0,
-		.module_name	= "ov772x",
-	},
+};
+
+static struct soc_camera_link ov7725_link = {
+	.power		= ov7725_power,
+	.board_info	= &migor_i2c_camera[0],
+	.i2c_adapter_id	= 0,
+	.module_name	= "ov772x",
+	.priv		= &ov7725_info,
 };
 
 static struct tw9910_video_info tw9910_info = {
 	.buswidth	= SOCAM_DATAWIDTH_8,
 	.mpout		= TW9910_MPO_FIELD,
-	.link = {
-		.power		= tw9910_power,
-		.board_info	= &migor_i2c_camera[1],
-		.i2c_adapter_id	= 0,
-		.module_name	= "tw9910",
-	}
+};
+
+static struct soc_camera_link tw9910_link = {
+	.power		= tw9910_power,
+	.board_info	= &migor_i2c_camera[1],
+	.i2c_adapter_id	= 0,
+	.module_name	= "tw9910",
+	.priv		= &tw9910_info,
 };
 
 static struct platform_device migor_camera[] = {
@@ -456,13 +460,13 @@
 		.name	= "soc-camera-pdrv",
 		.id	= 0,
 		.dev	= {
-			.platform_data = &ov7725_info.link,
+			.platform_data = &ov7725_link,
 		},
 	}, {
 		.name	= "soc-camera-pdrv",
 		.id	= 1,
 		.dev	= {
-			.platform_data = &tw9910_info.link,
+			.platform_data = &tw9910_link,
 		},
 	},
 };
diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c
index 4eb31ac..b221b68 100644
--- a/arch/sh/boards/mach-se/7722/irq.c
+++ b/arch/sh/boards/mach-se/7722/irq.c
@@ -57,15 +57,16 @@
  */
 void __init init_se7722_IRQ(void)
 {
-	int i;
+	int i, irq;
 
 	ctrl_outw(0, IRQ01_MASK);       /* disable all irqs */
 	ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
 
 	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
-		se7722_fpga_irq[i] = create_irq();
-		if (se7722_fpga_irq[i] < 0)
+		irq = create_irq();
+		if (irq < 0)
 			return;
+		se7722_fpga_irq[i] = irq;
 
 		set_irq_chip_and_handler_name(se7722_fpga_irq[i],
 					      &se7722_irq_chip,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 4b0f0c0..5d0f70b 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -514,6 +514,13 @@
 	&sdhi1_cn8_device,
 };
 
+/* I2C device */
+static struct i2c_board_info i2c0_devices[] = {
+	{
+		I2C_BOARD_INFO("ak4642", 0x12),
+	},
+};
+
 #define EEPROM_OP   0xBA206000
 #define EEPROM_ADR  0xBA206004
 #define EEPROM_DATA 0xBA20600C
@@ -575,6 +582,16 @@
 extern char ms7724se_sdram_leave_start;
 extern char ms7724se_sdram_leave_end;
 
+
+static int __init arch_setup(void)
+{
+	/* enable I2C device */
+	i2c_register_board_info(0, i2c0_devices,
+				ARRAY_SIZE(i2c0_devices));
+	return 0;
+}
+arch_initcall(arch_setup);
+
 static int __init devices_setup(void)
 {
 	u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
diff --git a/arch/sh/configs/ecovec24-romimage_defconfig b/arch/sh/configs/ecovec24-romimage_defconfig
index 0774924..4687470 100644
--- a/arch/sh/configs/ecovec24-romimage_defconfig
+++ b/arch/sh/configs/ecovec24-romimage_defconfig
@@ -203,7 +203,7 @@
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
-CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_MEMORY_SIZE=0x10000000
 CONFIG_29BIT=y
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig
index ac64697..cad9184 100644
--- a/arch/sh/configs/ecovec24_defconfig
+++ b/arch/sh/configs/ecovec24_defconfig
@@ -204,7 +204,7 @@
 CONFIG_PAGE_OFFSET=0x80000000
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_MEMORY_START=0x08000000
-CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_MEMORY_SIZE=0x10000000
 CONFIG_29BIT=y
 # CONFIG_X2TLB is not set
 CONFIG_VSYSCALL=y
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig
index f521e82..6f1126b 100644
--- a/arch/sh/configs/rts7751r2d1_defconfig
+++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -324,7 +324,7 @@
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_OVERWRITE=y
 # CONFIG_CMDLINE_EXTEND is not set
-CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=serial"
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 root=/dev/sda1"
 
 #
 # Bus options
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig
index a156cd1..9215bbb1 100644
--- a/arch/sh/configs/rts7751r2dplus_defconfig
+++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -324,7 +324,7 @@
 # CONFIG_UBC_WAKEUP is not set
 CONFIG_CMDLINE_OVERWRITE=y
 # CONFIG_CMDLINE_EXTEND is not set
-CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=serial"
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 root=/dev/sda1"
 
 #
 # Bus options
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index 052b354..7898f14 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -15,7 +15,7 @@
 #include <mach/lboxre2.h>
 #include <mach/r2d.h>
 #include "pci-sh4.h"
-#include <asm/machtypes.h>
+#include <generated/machtypes.h>
 
 #define PCIMCR_MRSET_OFF	0xBFFFFFFF
 #define PCIMCR_RFSH_OFF		0xFFFFFFFB
diff --git a/arch/sh/include/asm/.gitignore b/arch/sh/include/asm/.gitignore
deleted file mode 100644
index 378db77..0000000
--- a/arch/sh/include/asm/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-machtypes.h
diff --git a/arch/sh/include/asm/asm-offsets.h b/arch/sh/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/sh/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h
index ccb1d93..ac04255 100644
--- a/arch/sh/include/asm/elf.h
+++ b/arch/sh/include/asm/elf.h
@@ -114,7 +114,6 @@
  */
 #define CORE_DUMP_USE_REGSET
 
-#define USE_ELF_CORE_DUMP
 #define ELF_FDPIC_CORE_EFLAGS	EF_SH_FDPIC
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 512cd3e..026dd65 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -233,11 +233,17 @@
  * doesn't exist, so everything must go through page tables.
  */
 #ifdef CONFIG_MMU
-void __iomem *__ioremap(unsigned long offset, unsigned long size,
-			unsigned long flags);
+void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
+			       unsigned long flags, void *caller);
 void __iounmap(void __iomem *addr);
 
 static inline void __iomem *
+__ioremap(unsigned long offset, unsigned long size, unsigned long flags)
+{
+	return __ioremap_caller(offset, size, flags, __builtin_return_address(0));
+}
+
+static inline void __iomem *
 __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
 {
 #if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB)
@@ -271,6 +277,7 @@
 	return __ioremap(offset, size, flags);
 }
 #else
+#define __ioremap(offset, size, flags)		((void __iomem *)(offset))
 #define __ioremap_mode(offset, size, flags)	((void __iomem *)(offset))
 #define __iounmap(addr)				do { } while (0)
 #endif /* CONFIG_MMU */
diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h
index 84dd377..9c30955 100644
--- a/arch/sh/include/asm/machvec.h
+++ b/arch/sh/include/asm/machvec.h
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/time.h>
-#include <asm/machtypes.h>
+#include <generated/machtypes.h>
 
 struct sh_machine_vector {
 	void (*mv_setup)(char **cmdline_p);
diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h
index b354355..5003ee8 100644
--- a/arch/sh/include/asm/pgtable_32.h
+++ b/arch/sh/include/asm/pgtable_32.h
@@ -344,7 +344,8 @@
 #define pte_special(pte)	((pte).pte_low & _PAGE_SPECIAL)
 
 #ifdef CONFIG_X2TLB
-#define pte_write(pte)		((pte).pte_high & _PAGE_EXT_USER_WRITE)
+#define pte_write(pte) \
+	((pte).pte_high & (_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE))
 #else
 #define pte_write(pte)		((pte).pte_low & _PAGE_RW)
 #endif
@@ -358,7 +359,7 @@
  * 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, wrprotect, &= ~_PAGE_EXT_USER_WRITE);
+PTE_BIT_FUNC(high, wrprotect, &= ~(_PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE));
 PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE);
 PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE);
 #else
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index f3fd1b9..f18c4f9 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -345,8 +345,9 @@
 #define __NR_pwritev		334
 #define __NR_rt_tgsigqueueinfo	335
 #define __NR_perf_event_open	336
+#define __NR_recvmmsg		337
 
-#define NR_syscalls 337
+#define NR_syscalls 338
 
 #ifdef __KERNEL__
 
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h
index 343ce8f..3e7645d 100644
--- a/arch/sh/include/asm/unistd_64.h
+++ b/arch/sh/include/asm/unistd_64.h
@@ -385,10 +385,11 @@
 #define __NR_pwritev		362
 #define __NR_rt_tgsigqueueinfo	363
 #define __NR_perf_event_open	364
+#define __NR_recvmmsg		365
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 365
+#define NR_syscalls 366
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index 174374e..484ef42 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -8,6 +8,8 @@
 void kfr2r09_lcd_off(void *board_data);
 int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle,
 		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle,
+		       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 #else
 static inline void kfr2r09_lcd_on(void *board_data) {}
 static inline void kfr2r09_lcd_off(void *board_data) {}
@@ -16,6 +18,10 @@
 {
 	return -ENODEV;
 }
+static inline void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle,
+				     struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
+{
+}
 #endif
 
 #endif /* __ASM_SH_KFR2R09_H */
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 0471a3e..0d587da 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -22,11 +22,10 @@
 obj-y				+= cpu/
 obj-$(CONFIG_VSYSCALL)		+= vsyscall/
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
+obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o early_printk.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_SH_CPU_FREQ)	+= cpufreq.o
 obj-$(CONFIG_MODULES)		+= sh_ksyms_$(BITS).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
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index c1508a9..9282d96 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -17,16 +17,17 @@
  * for more details.
  */
 #include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/io.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/topology.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));
+	return container_of(chip, struct ipr_desc, chip);
 }
 
 static void disable_ipr_irq(unsigned int irq)
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 8555c05..114c7ce 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -59,32 +59,48 @@
 static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xf8400000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 88, 88, 88, 88 },
-	}, {
-		.mapbase	= 0xf8410000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 92, 92, 92, 92 },
-	}, {
-		.mapbase	= 0xf8420000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 96, 96, 96, 96 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xf8400000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 88, 88, 88, 88 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xf8410000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 92, 92, 92, 92 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xf8420000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 96, 96, 96, 96 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
 	},
 };
 
@@ -176,7 +192,9 @@
 };
 
 static struct platform_device *sh7619_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&eth_device,
 	&cmt0_device,
 	&cmt1_device,
@@ -195,6 +213,9 @@
 }
 
 static struct platform_device *sh7619_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&cmt0_device,
 	&cmt1_device,
 };
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index b673764..8f669dc 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -207,27 +207,23 @@
 	.num_resources	= ARRAY_SIZE(mtu2_2_resources),
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xff804000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 220, 220, 220, 220 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xff804000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 220, 220, 220, 220 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
 	},
 };
 
 static struct platform_device *mxg_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&mtu2_2_device,
@@ -246,6 +242,7 @@
 }
 
 static struct platform_device *mxg_early_devices[] __initdata = {
+	&scif0_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&mtu2_2_device,
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
index fbde5b7..4ccfeb5 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -177,57 +177,123 @@
 static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfffe8000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 180, 180, 180, 180 }
-	}, {
-		.mapbase	= 0xfffe8800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 184, 184, 184, 184 }
-	}, {
-		.mapbase	= 0xfffe9000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 188, 188, 188, 188 }
-	}, {
-		.mapbase	= 0xfffe9800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 192, 192, 192, 192 }
-	}, {
-		.mapbase	= 0xfffea000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 196, 196, 196, 196 }
-	}, {
-		.mapbase	= 0xfffea800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 200, 200, 200, 200 }
-	}, {
-		.mapbase	= 0xfffeb000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 204, 204, 204, 204 }
-	}, {
-		.mapbase	= 0xfffeb800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 208, 208, 208, 208 }
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xfffe8000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 180, 180, 180, 180 }
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xfffe8800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 184, 184, 184, 184 }
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xfffe9000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 188, 188, 188, 188 }
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xfffe9800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 192, 192, 192, 192 }
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xfffea000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 196, 196, 196, 196 }
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase	= 0xfffea800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 200, 200, 200, 200 }
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
+	},
+};
+
+static struct plat_sci_port scif6_platform_data = {
+	.mapbase	= 0xfffeb000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 204, 204, 204, 204 }
+};
+
+static struct platform_device scif6_device = {
+	.name		= "sh-sci",
+	.id		= 6,
+	.dev		= {
+		.platform_data	= &scif6_platform_data,
+	},
+};
+
+static struct plat_sci_port scif7_platform_data = {
+	.mapbase	= 0xfffeb800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 208, 208, 208, 208 }
+};
+
+static struct platform_device scif7_device = {
+	.name		= "sh-sci",
+	.id		= 7,
+	.dev		= {
+		.platform_data	= &scif7_platform_data,
 	},
 };
 
@@ -345,7 +411,14 @@
 };
 
 static struct platform_device *sh7201_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
 	&rtc_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
@@ -365,6 +438,14 @@
 }
 
 static struct platform_device *sh7201_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
 	&mtu2_0_device,
 	&mtu2_1_device,
 	&mtu2_2_device,
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index d3fd536..3136966 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -173,37 +173,63 @@
 static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfffe8000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		=  { 192, 192, 192, 192 },
-	}, {
-		.mapbase	= 0xfffe8800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		=  { 196, 196, 196, 196 },
-	}, {
-		.mapbase	= 0xfffe9000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		=  { 200, 200, 200, 200 },
-	}, {
-		.mapbase	= 0xfffe9800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		=  { 204, 204, 204, 204 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xfffe8000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		=  { 192, 192, 192, 192 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xfffe8800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		=  { 196, 196, 196, 196 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xfffe9000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		=  { 200, 200, 200, 200 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xfffe9800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		=  { 204, 204, 204, 204 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
 	},
 };
 
@@ -354,7 +380,10 @@
 };
 
 static struct platform_device *sh7203_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt0_device,
 	&cmt1_device,
 	&mtu2_0_device,
@@ -375,6 +404,10 @@
 }
 
 static struct platform_device *sh7203_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt0_device,
 	&cmt1_device,
 	&mtu2_0_device,
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index a9ccc5e..0648735 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -133,37 +133,63 @@
 static DECLARE_INTC_DESC(intc_desc, "sh7206", vectors, groups,
 			 mask_registers, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfffe8000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 240, 240, 240, 240 },
-	}, {
-		.mapbase	= 0xfffe8800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 244, 244, 244, 244 },
-	}, {
-		.mapbase	= 0xfffe9000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 248, 248, 248, 248 },
-	}, {
-		.mapbase	= 0xfffe9800,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 252, 252, 252, 252 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xfffe8000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 240, 240, 240, 240 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xfffe8800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 244, 244, 244, 244 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xfffe9000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 248, 248, 248, 248 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xfffe9800,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 252, 252, 252, 252 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
 	},
 };
 
@@ -325,7 +351,10 @@
 };
 
 static struct platform_device *sh7206_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt0_device,
 	&cmt1_device,
 	&mtu2_0_device,
@@ -346,6 +375,10 @@
 }
 
 static struct platform_device *sh7206_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt0_device,
 	&cmt1_device,
 	&mtu2_0_device,
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index c231059..7b892d6 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -67,27 +67,33 @@
 static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL,
 			 NULL, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xa4410000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 56, 56, 56 },
-	}, {
-		.mapbase	= 0xa4400000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 52, 52, 52 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xa4410000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 56, 56, 56 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xa4400000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 52, 52, 52 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
 	},
 };
 
@@ -210,10 +216,11 @@
 };
 
 static struct platform_device *sh7705_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
-	&sci_device,
 	&rtc_device,
 };
 
@@ -225,6 +232,8 @@
 arch_initcall(sh7705_devices_setup);
 
 static struct platform_device *sh7705_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index 347ab35..bc0c4f6 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
@@ -106,44 +106,55 @@
 	.resource	= rtc_resources,
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfffffe80,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
-		.irqs		= { 23, 23, 23, 0 },
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xfffffe80,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCI,
+	.irqs		= { 23, 23, 23, 0 },
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
 	},
+};
 #if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
-	{
-		.mapbase	= 0xa4000150,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 56, 56, 56, 56 },
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xa4000150,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 56, 56, 56, 56 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
 	},
+};
 #endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
     defined(CONFIG_CPU_SUBTYPE_SH7709)
-	{
-		.mapbase	= 0xa4000140,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_IRDA,
-		.irqs		= { 52, 52, 52, 52 },
-	},
-#endif
-	{
-		.flags = 0,
-	}
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xa4000140,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_IRDA,
+	.irqs		= { 52, 52, 52, 52 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif2_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 2,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif2_platform_data,
 	},
 };
+#endif
 
 static struct sh_timer_config tmu0_platform_data = {
 	.name = "TMU0",
@@ -238,10 +249,19 @@
 };
 
 static struct platform_device *sh770x_devices[] __initdata = {
+	&scif0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709)
+	&scif1_device,
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709)
+	&scif2_device,
+#endif
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
-	&sci_device,
 	&rtc_device,
 };
 
@@ -253,6 +273,16 @@
 arch_initcall(sh770x_devices_setup);
 
 static struct platform_device *sh770x_early_devices[] __initdata = {
+	&scif0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709)
+	&scif1_device,
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709)
+	&scif2_device,
+#endif
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 717e90a..0845a3a 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -96,28 +96,33 @@
 	},
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xa4400000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 52, 52, 52, 52 },
-	}, {
-		.mapbase	= 0xa4410000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs           = { 56, 56, 56, 56 },
-	}, {
-
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xa4400000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 52, 52, 52, 52 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xa4410000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs           = { 56, 56, 56, 56 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
 	},
 };
 
@@ -214,10 +219,11 @@
 };
 
 static struct platform_device *sh7710_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
-	&sci_device,
 	&rtc_device,
 };
 
@@ -229,6 +235,8 @@
 arch_initcall(sh7710_devices_setup);
 
 static struct platform_device *sh7710_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 74d8baa..a718a62 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -48,28 +48,33 @@
 	},
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xa4430000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 80, 80, 80, 80 },
-	}, {
-		.mapbase	= 0xa4438000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs           = { 81, 81, 81, 81 },
-	}, {
-
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xa4430000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 80, 80, 80, 80 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xa4438000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
 	},
 };
 
@@ -369,6 +374,8 @@
 };
 
 static struct platform_device *sh7720_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&cmt0_device,
 	&cmt1_device,
 	&cmt2_device,
@@ -378,7 +385,6 @@
 	&tmu1_device,
 	&tmu2_device,
 	&rtc_device,
-	&sci_device,
 	&usb_ohci_device,
 	&usbf_device,
 };
@@ -391,6 +397,8 @@
 arch_initcall(sh7720_devices_setup);
 
 static struct platform_device *sh7720_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&cmt0_device,
 	&cmt1_device,
 	&cmt2_device,
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
index de4827d..4b73371 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -15,22 +15,18 @@
 #include <linux/sh_timer.h>
 #include <linux/io.h>
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe80000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffe80000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 41, 43, 42 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
 	},
 };
 
@@ -127,7 +123,7 @@
 };
 
 static struct platform_device *sh4202_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -141,6 +137,7 @@
 arch_initcall(sh4202_devices_setup);
 
 static struct platform_device *sh4202_early_devices[] __initdata = {
+	&scif0_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 1b8b122..b2a9df1 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -35,29 +35,33 @@
 	.resource	= rtc_resources,
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-#ifndef CONFIG_SH_RTS7751R2D
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
-		.irqs		= { 23, 23, 23, 0 },
-	}, {
-#endif
-		.mapbase	= 0xffe80000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 40, 40, 40 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffe00000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCI,
+	.irqs		= { 23, 23, 23, 0 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffe80000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 40, 40, 40 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
 	},
 };
 
@@ -221,8 +225,9 @@
 #endif
 
 static struct platform_device *sh7750_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&rtc_device,
-	&sci_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -242,6 +247,8 @@
 arch_initcall(sh7750_devices_setup);
 
 static struct platform_device *sh7750_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 7fbb7be..5b74cc0 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -126,37 +126,63 @@
 static DECLARE_INTC_DESC(intc_desc_irq, "sh7760-irq", vectors_irq, groups,
 			 mask_registers, prio_registers, NULL);
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfe600000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 52, 53, 55, 54 },
-	}, {
-		.mapbase	= 0xfe610000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 72, 73, 75, 74 },
-	}, {
-		.mapbase	= 0xfe620000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 76, 77, 79, 78 },
-	}, {
-		.mapbase	= 0xfe480000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCI,
-		.irqs		= { 80, 81, 82, 0 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xfe600000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 52, 53, 55, 54 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xfe610000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 72, 73, 75, 74 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xfe620000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 76, 77, 79, 78 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xfe480000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCI,
+	.irqs		= { 80, 81, 82, 0 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
 	},
 };
 
@@ -254,7 +280,10 @@
 
 
 static struct platform_device *sh7760_devices[] __initdata = {
-	&sci_device,
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -268,6 +297,10 @@
 arch_initcall(sh7760_devices_setup);
 
 static struct platform_device *sh7760_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index ac4d567..45eb1bf 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -15,6 +15,71 @@
 #include <linux/sh_timer.h>
 #include <asm/clock.h>
 
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase        = 0xffe00000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 80, 80, 80, 80 },
+	.clk		= "scif0",
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase        = 0xffe10000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+	.clk		= "scif1",
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase        = 0xffe20000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+	.clk		= "scif2",
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase        = 0xffe30000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 83, 83, 83, 83 },
+	.clk		= "scif3",
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
 static struct resource iic0_resources[] = {
 	[0] = {
 		.name	= "IIC0",
@@ -265,52 +330,17 @@
 	.num_resources	= ARRAY_SIZE(tmu2_resources),
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 80, 80, 80, 80 },
-		.clk		= "scif0",
-	}, {
-		.mapbase	= 0xffe10000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 81, 81, 81, 81 },
-		.clk		= "scif1",
-	}, {
-		.mapbase	= 0xffe20000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 82, 82, 82, 82 },
-		.clk		= "scif2",
-	}, {
-		.mapbase	= 0xffe30000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 83, 83, 83, 83 },
-		.clk		= "scif3",
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct platform_device *sh7343_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
 	&iic0_device,
 	&iic1_device,
-	&sci_device,
 	&vpu_device,
 	&veu_device,
 	&jpu_device,
@@ -328,6 +358,10 @@
 arch_initcall(sh7343_devices_setup);
 
 static struct platform_device *sh7343_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 4a9010b..c494c19 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -18,6 +18,22 @@
 #include <linux/usb/r8a66597.h>
 #include <asm/clock.h>
 
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffe00000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 80, 80, 80, 80 },
+	.clk		= "scif0",
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
 static struct resource iic_resources[] = {
 	[0] = {
 		.name	= "IIC",
@@ -276,33 +292,13 @@
 	.num_resources	= ARRAY_SIZE(tmu2_resources),
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 80, 80, 80, 80 },
-		.clk		= "scif0",
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct platform_device *sh7366_devices[] __initdata = {
+	&scif0_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
 	&iic_device,
-	&sci_device,
 	&usb_host_device,
 	&vpu_device,
 	&veu0_device,
@@ -321,6 +317,7 @@
 arch_initcall(sh7366_devices_setup);
 
 static struct platform_device *sh7366_early_devices[] __initdata = {
+	&scif0_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 5491b09..b5335b5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -20,6 +20,55 @@
 #include <asm/dma-sh.h>
 #include <cpu/sh7722.h>
 
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase        = 0xffe00000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 80, 80, 80, 80 },
+	.clk		= "scif0",
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase        = 0xffe10000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+	.clk		= "scif1",
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase        = 0xffe20000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+	.clk		= "scif2",
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
 static struct resource rtc_resources[] = {
 	[0] = {
 		.start	= 0xa465fec0,
@@ -339,41 +388,6 @@
 	},
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 80, 80, 80, 80 },
-		.clk		= "scif0",
-	},
-	{
-		.mapbase	= 0xffe10000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 81, 81, 81, 81 },
-		.clk		= "scif1",
-	},
-	{
-		.mapbase	= 0xffe20000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 82, 82, 82, 82 },
-		.clk		= "scif2",
-	},
-	{
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct sh_dmae_pdata dma_platform_data = {
 	.mode = 0,
 };
@@ -387,6 +401,9 @@
 };
 
 static struct platform_device *sh7722_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
@@ -394,7 +411,6 @@
 	&rtc_device,
 	&usbf_device,
 	&iic_device,
-	&sci_device,
 	&vpu_device,
 	&veu_device,
 	&jpu_device,
@@ -413,6 +429,9 @@
 arch_initcall(sh7722_devices_setup);
 
 static struct platform_device *sh7722_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 4caa5a7..772b926 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -20,6 +20,103 @@
 #include <asm/mmzone.h>
 #include <cpu/sh7723.h>
 
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase        = 0xffe00000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 80, 80, 80, 80 },
+	.clk		= "scif0",
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase        = 0xffe10000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+	.clk		= "scif1",
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase        = 0xffe20000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+	.clk		= "scif2",
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase        = 0xa4e30000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 56, 56, 56, 56 },
+	.clk		= "scif3",
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase        = 0xa4e40000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 88, 88, 88, 88 },
+	.clk		= "scif4",
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase        = 0xa4e50000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 109, 109, 109, 109 },
+	.clk		= "scif5",
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
+	},
+};
+
 static struct uio_info vpu_platform_data = {
 	.name = "VPU5",
 	.version = "0",
@@ -348,56 +445,6 @@
 	},
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase        = 0xffe00000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 80, 80, 80, 80 },
-		.clk		= "scif0",
-	},{
-		.mapbase        = 0xffe10000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 81, 81, 81, 81 },
-		.clk		= "scif1",
-	},{
-		.mapbase        = 0xffe20000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 82, 82, 82, 82 },
-		.clk		= "scif2",
-	},{
-		.mapbase	= 0xa4e30000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 56, 56, 56, 56 },
-		.clk		= "scif3",
-	},{
-		.mapbase	= 0xa4e40000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 88, 88, 88, 88 },
-		.clk		= "scif4",
-	},{
-		.mapbase	= 0xa4e50000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 109, 109, 109, 109 },
-		.clk		= "scif5",
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct resource rtc_resources[] = {
 	[0] = {
 		.start	= 0xa465fec0,
@@ -488,6 +535,12 @@
 };
 
 static struct platform_device *sh7723_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
@@ -495,7 +548,6 @@
 	&tmu3_device,
 	&tmu4_device,
 	&tmu5_device,
-	&sci_device,
 	&rtc_device,
 	&iic_device,
 	&sh7723_usb_host_device,
@@ -516,6 +568,12 @@
 arch_initcall(sh7723_devices_setup);
 
 static struct platform_device *sh7723_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 845e89c..a52f351 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -27,53 +27,99 @@
 #include <cpu/sh7724.h>
 
 /* Serial */
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase        = 0xffe00000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 80, 80, 80, 80 },
-		.clk		= "scif0",
-	}, {
-		.mapbase        = 0xffe10000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 81, 81, 81, 81 },
-		.clk		= "scif1",
-	}, {
-		.mapbase        = 0xffe20000,
-		.flags          = UPF_BOOT_AUTOCONF,
-		.type           = PORT_SCIF,
-		.irqs           = { 82, 82, 82, 82 },
-		.clk		= "scif2",
-	}, {
-		.mapbase	= 0xa4e30000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 56, 56, 56, 56 },
-		.clk		= "scif3",
-	}, {
-		.mapbase	= 0xa4e40000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 88, 88, 88, 88 },
-		.clk		= "scif4",
-	}, {
-		.mapbase	= 0xa4e50000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIFA,
-		.irqs		= { 109, 109, 109, 109 },
-		.clk		= "scif5",
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase        = 0xffe00000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 80, 80, 80, 80 },
+	.clk		= "scif0",
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase        = 0xffe10000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 81, 81, 81, 81 },
+	.clk		= "scif1",
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase        = 0xffe20000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIF,
+	.irqs           = { 82, 82, 82, 82 },
+	.clk		= "scif2",
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase        = 0xa4e30000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 56, 56, 56, 56 },
+	.clk		= "scif3",
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase        = 0xa4e40000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 88, 88, 88, 88 },
+	.clk		= "scif4",
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase        = 0xa4e50000,
+	.flags          = UPF_BOOT_AUTOCONF,
+	.type           = PORT_SCIFA,
+	.irqs           = { 109, 109, 109, 109 },
+	.clk		= "scif5",
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
 	},
 };
 
@@ -590,6 +636,12 @@
 };
 
 static struct platform_device *sh7724_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
@@ -597,7 +649,6 @@
 	&tmu3_device,
 	&tmu4_device,
 	&tmu5_device,
-	&sci_device,
 	&rtc_device,
 	&iic0_device,
 	&iic1_device,
@@ -624,6 +675,12 @@
 arch_initcall(sh7724_devices_setup);
 
 static struct platform_device *sh7724_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&cmt_device,
 	&tmu0_device,
 	&tmu1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index c470e15..37e32ef 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -17,6 +17,51 @@
 #include <linux/mm.h>
 #include <linux/sh_timer.h>
 
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xfe4b0000,		/* SCIF2 */
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 40, 40, 40 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xfe4c0000,		/* SCIF3 */
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 76, 76, 76, 76 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xfe4d0000,		/* SCIF4 */
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 104, 104, 104, 104 },
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
 static struct sh_timer_config tmu0_platform_data = {
 	.name = "TMU0",
 	.channel_offset = 0x04,
@@ -79,39 +124,12 @@
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xfe4b0000,		/* SCIF2 */
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 40, 40, 40 },
-	}, {
-		.mapbase	= 0xfe4c0000,		/* SCIF3 */
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 76, 76, 76, 76 },
-	}, {
-		.mapbase	= 0xfe4d0000,		/* SCIF4 */
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 104, 104, 104, 104 },
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct platform_device *sh7757_devices[] __initdata = {
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
 	&tmu0_device,
 	&tmu1_device,
-	&sci_device,
 };
 
 static int __init sh7757_devices_setup(void)
@@ -121,6 +139,20 @@
 }
 arch_initcall(sh7757_devices_setup);
 
+static struct platform_device *sh7757_early_devices[] __initdata = {
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&tmu0_device,
+	&tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+	early_platform_add_devices(sh7757_early_devices,
+				   ARRAY_SIZE(sh7757_early_devices));
+}
+
 enum {
 	UNUSED = 0,
 
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 4659fff..6aba26f 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -16,6 +16,51 @@
 #include <linux/io.h>
 #include <linux/serial_sci.h>
 
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffe00000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 40, 40, 40 },
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffe08000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 76, 76, 76, 76 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xffe10000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 104, 104, 104, 104 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
 static struct resource rtc_resources[] = {
 	[0] = {
 		.start	= 0xffe80000,
@@ -36,35 +81,6 @@
 	.resource	= rtc_resources,
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 40, 40, 40 },
-	}, {
-		.mapbase	= 0xffe08000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 76, 76, 76, 76 },
-	}, {
-		.mapbase	= 0xffe10000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 104, 104, 104, 104 },
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct resource usb_ohci_resources[] = {
 	[0] = {
 		.start	= 0xffec8000,
@@ -297,6 +313,9 @@
 };
 
 static struct platform_device *sh7763_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -304,7 +323,6 @@
 	&tmu4_device,
 	&tmu5_device,
 	&rtc_device,
-	&sci_device,
 	&usb_ohci_device,
 	&usbf_device,
 };
@@ -317,6 +335,9 @@
 arch_initcall(sh7763_devices_setup);
 
 static struct platform_device *sh7763_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index eead08d..c1643bc 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
@@ -14,67 +14,153 @@
 #include <linux/sh_timer.h>
 #include <linux/io.h>
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xff923000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 61, 61, 61, 61 },
-	}, {
-		.mapbase	= 0xff924000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 62, 62, 62, 62 },
-	}, {
-		.mapbase	= 0xff925000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 63, 63, 63, 63 },
-	}, {
-		.mapbase	= 0xff926000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 64, 64, 64, 64 },
-	}, {
-		.mapbase	= 0xff927000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 65, 65, 65, 65 },
-	}, {
-		.mapbase	= 0xff928000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 66, 66, 66, 66 },
-	}, {
-		.mapbase	= 0xff929000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 67, 67, 67, 67 },
-	}, {
-		.mapbase	= 0xff92a000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 68, 68, 68, 68 },
-	}, {
-		.mapbase	= 0xff92b000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 69, 69, 69, 69 },
-	}, {
-		.mapbase	= 0xff92c000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 70, 70, 70, 70 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xff923000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 61, 61, 61, 61 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xff924000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 62, 62, 62, 62 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xff925000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 63, 63, 63, 63 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xff926000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 64, 64, 64, 64 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xff927000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 65, 65, 65, 65 },
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase	= 0xff928000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 66, 66, 66, 66 },
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
+	},
+};
+
+static struct plat_sci_port scif6_platform_data = {
+	.mapbase	= 0xff929000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 67, 67, 67, 67 },
+};
+
+static struct platform_device scif6_device = {
+	.name		= "sh-sci",
+	.id		= 6,
+	.dev		= {
+		.platform_data	= &scif6_platform_data,
+	},
+};
+
+static struct plat_sci_port scif7_platform_data = {
+	.mapbase	= 0xff92a000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 68, 68, 68, 68 },
+};
+
+static struct platform_device scif7_device = {
+	.name		= "sh-sci",
+	.id		= 7,
+	.dev		= {
+		.platform_data	= &scif7_platform_data,
+	},
+};
+
+static struct plat_sci_port scif8_platform_data = {
+	.mapbase	= 0xff92b000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 69, 69, 69, 69 },
+};
+
+static struct platform_device scif8_device = {
+	.name		= "sh-sci",
+	.id		= 8,
+	.dev		= {
+		.platform_data	= &scif8_platform_data,
+	},
+};
+
+static struct plat_sci_port scif9_platform_data = {
+	.mapbase	= 0xff92c000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 70, 70, 70, 70 },
+};
+
+static struct platform_device scif9_device = {
+	.name		= "sh-sci",
+	.id		= 9,
+	.dev		= {
+		.platform_data	= &scif9_platform_data,
 	},
 };
 
@@ -351,6 +437,16 @@
 };
 
 static struct platform_device *sh7770_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
+	&scif8_device,
+	&scif9_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -360,7 +456,6 @@
 	&tmu6_device,
 	&tmu7_device,
 	&tmu8_device,
-	&sci_device,
 };
 
 static int __init sh7770_devices_setup(void)
@@ -371,6 +466,16 @@
 arch_initcall(sh7770_devices_setup);
 
 static struct platform_device *sh7770_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
+	&scif6_device,
+	&scif7_device,
+	&scif8_device,
+	&scif9_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 12ff56f..c310558 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -15,6 +15,36 @@
 #include <linux/sh_timer.h>
 #include <asm/dma-sh.h>
 
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffe00000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 40, 40, 40 },
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffe10000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 76, 76, 76, 76 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
 static struct sh_timer_config tmu0_platform_data = {
 	.name = "TMU0",
 	.channel_offset = 0x04,
@@ -217,30 +247,6 @@
 	.resource	= rtc_resources,
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffe00000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 40, 40, 40 },
-	}, {
-		.mapbase	= 0xffe10000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 76, 76, 76, 76 },
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct sh_dmae_pdata dma_platform_data = {
 	.mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1),
 };
@@ -254,6 +260,8 @@
 };
 
 static struct platform_device *sh7780_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -261,7 +269,6 @@
 	&tmu4_device,
 	&tmu5_device,
 	&rtc_device,
-	&sci_device,
 	&dma_device,
 };
 
@@ -271,8 +278,9 @@
 				    ARRAY_SIZE(sh7780_devices));
 }
 arch_initcall(sh7780_devices_setup);
-
 static struct platform_device *sh7780_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 7f6c718..ef26ebd 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -16,6 +16,102 @@
 #include <linux/sh_timer.h>
 #include <asm/mmzone.h>
 
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffea0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 40, 40, 40 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif0_device = {
+	.name		= "sh-sci",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffeb0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 44, 44, 44, 44 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xffec0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 60, 60, 60, 60 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xffed0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 61, 61, 61, 61 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xffee0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 62, 62, 62, 62 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase	= 0xffef0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 63, 63, 63, 63 },
+	.clk		= "scif_fck",
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
+	},
+};
+
 static struct sh_timer_config tmu0_platform_data = {
 	.name = "TMU0",
 	.channel_offset = 0x04,
@@ -198,64 +294,19 @@
 	.num_resources	= ARRAY_SIZE(tmu5_resources),
 };
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffea0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 40, 40, 40 },
-		.clk		= "scif_fck",
-	}, {
-		.mapbase	= 0xffeb0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 44, 44, 44, 44 },
-		.clk		= "scif_fck",
-	}, {
-		.mapbase	= 0xffec0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 60, 60, 60, 60 },
-		.clk		= "scif_fck",
-	}, {
-		.mapbase	= 0xffed0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 61, 61, 61, 61 },
-		.clk		= "scif_fck",
-	}, {
-		.mapbase	= 0xffee0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 62, 62, 62, 62 },
-		.clk		= "scif_fck",
-	}, {
-		.mapbase	= 0xffef0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 63, 63, 63, 63 },
-		.clk		= "scif_fck",
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct platform_device sci_device = {
-	.name		= "sh-sci",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= sci_platform_data,
-	},
-};
-
 static struct platform_device *sh7785_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
 	&tmu3_device,
 	&tmu4_device,
 	&tmu5_device,
-	&sci_device,
 };
 
 static int __init sh7785_devices_setup(void)
@@ -266,6 +317,12 @@
 arch_initcall(sh7785_devices_setup);
 
 static struct platform_device *sh7785_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
index 0104a8e..7167348 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -23,51 +23,96 @@
 #include <linux/sh_timer.h>
 #include <asm/mmzone.h>
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= 0xffea0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 40, 41, 43, 42 },
-	},
-	/*
-	 * The rest of these all have multiplexed IRQs
-	 */
-	{
-		.mapbase	= 0xffeb0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 44, 44, 44, 44 },
-	}, {
-		.mapbase	= 0xffec0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 50, 50, 50, 50 },
-	}, {
-		.mapbase	= 0xffed0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 51, 51, 51, 51 },
-	}, {
-		.mapbase	= 0xffee0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 52, 52, 52, 52 },
-	}, {
-		.mapbase	= 0xffef0000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 53, 53, 53, 53 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffea0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 41, 43, 42 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+/*
+ * The rest of these all have multiplexed IRQs
+ */
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffeb0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 44, 44, 44, 44 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xffec0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 50, 50, 50, 50 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
+	},
+};
+
+static struct plat_sci_port scif3_platform_data = {
+	.mapbase	= 0xffed0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 51, 51, 51, 51 },
+};
+
+static struct platform_device scif3_device = {
+	.name		= "sh-sci",
+	.id		= 3,
+	.dev		= {
+		.platform_data	= &scif3_platform_data,
+	},
+};
+
+static struct plat_sci_port scif4_platform_data = {
+	.mapbase	= 0xffee0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 52, 52, 52, 52 },
+};
+
+static struct platform_device scif4_device = {
+	.name		= "sh-sci",
+	.id		= 4,
+	.dev		= {
+		.platform_data	= &scif4_platform_data,
+	},
+};
+
+static struct plat_sci_port scif5_platform_data = {
+	.mapbase	= 0xffef0000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 53, 53, 53, 53 },
+};
+
+static struct platform_device scif5_device = {
+	.name		= "sh-sci",
+	.id		= 5,
+	.dev		= {
+		.platform_data	= &scif5_platform_data,
 	},
 };
 
@@ -459,6 +504,12 @@
 };
 
 static struct platform_device *sh7786_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
+	&scif3_device,
+	&scif4_device,
+	&scif5_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -474,7 +525,6 @@
 };
 
 static struct platform_device *sh7786_devices[] __initdata = {
-	&sci_device,
 	&usb_ohci_device,
 };
 
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index c7ba916..780ba17 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -24,32 +24,48 @@
  * silicon in the first place, we just refuse to deal with the port at
  * all rather than adding infrastructure to hack around it.
  */
-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	= 0xffc60000,
-		.flags		= UPF_BOOT_AUTOCONF,
-		.type		= PORT_SCIF,
-		.irqs		= { 52, 53, 55, 54 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= 0xffc30000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 40, 41, 43, 42 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
+	},
+};
+
+static struct plat_sci_port scif1_platform_data = {
+	.mapbase	= 0xffc40000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 44, 45, 47, 46 },
+};
+
+static struct platform_device scif1_device = {
+	.name		= "sh-sci",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &scif1_platform_data,
+	},
+};
+
+static struct plat_sci_port scif2_platform_data = {
+	.mapbase	= 0xffc60000,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.type		= PORT_SCIF,
+	.irqs		= { 52, 53, 55, 54 },
+};
+
+static struct platform_device scif2_device = {
+	.name		= "sh-sci",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &scif2_platform_data,
 	},
 };
 
@@ -236,6 +252,9 @@
 };
 
 static struct platform_device *shx3_early_devices[] __initdata = {
+	&scif0_device,
+	&scif1_device,
+	&scif2_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
@@ -244,21 +263,10 @@
 	&tmu5_device,
 };
 
-static struct platform_device *shx3_devices[] __initdata = {
-	&sci_device,
-};
-
 static int __init shx3_devices_setup(void)
 {
-	int ret;
-
-	ret = platform_add_devices(shx3_early_devices,
+	return platform_add_devices(shx3_early_devices,
 				   ARRAY_SIZE(shx3_early_devices));
-	if (unlikely(ret != 0))
-		return ret;
-
-	return platform_add_devices(shx3_devices,
-				    ARRAY_SIZE(shx3_devices));
 }
 arch_initcall(shx3_devices_setup);
 
diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c
index dd4f51f..4648cce 100644
--- a/arch/sh/kernel/cpu/sh5/fpu.c
+++ b/arch/sh/kernel/cpu/sh5/fpu.c
@@ -34,7 +34,7 @@
 	}
 };
 
-void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
+void save_fpu(struct task_struct *tsk)
 {
 	asm volatile("fst.p     %0, (0*8), fp0\n\t"
 		     "fst.p     %0, (1*8), fp2\n\t"
@@ -153,7 +153,7 @@
 	enable_fpu();
 	if (last_task_used_math != NULL)
 		/* Other processes fpu state, save away */
-		save_fpu(last_task_used_math, regs);
+		save_fpu(last_task_used_math);
 
         last_task_used_math = current;
         if (used_math()) {
diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c
index 6a0f82f..e7a3c1e 100644
--- a/arch/sh/kernel/cpu/sh5/setup-sh5.c
+++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c
@@ -16,22 +16,18 @@
 #include <linux/sh_timer.h>
 #include <asm/addrspace.h>
 
-static struct plat_sci_port sci_platform_data[] = {
-	{
-		.mapbase	= PHYS_PERIPHERAL_BLOCK + 0x01030000,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,
-		.type		= PORT_SCIF,
-		.irqs		= { 39, 40, 42, 0 },
-	}, {
-		.flags = 0,
-	}
+static struct plat_sci_port scif0_platform_data = {
+	.mapbase	= PHYS_PERIPHERAL_BLOCK + 0x01030000,
+	.flags		= UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+	.type		= PORT_SCIF,
+	.irqs		= { 39, 40, 42, 0 },
 };
 
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
 	.name		= "sh-sci",
-	.id		= -1,
+	.id		= 0,
 	.dev		= {
-		.platform_data	= sci_platform_data,
+		.platform_data	= &scif0_platform_data,
 	},
 };
 
@@ -164,13 +160,13 @@
 };
 
 static struct platform_device *sh5_early_devices[] __initdata = {
+	&scif0_device,
 	&tmu0_device,
 	&tmu1_device,
 	&tmu2_device,
 };
 
 static struct platform_device *sh5_devices[] __initdata = {
-	&sci_device,
 	&rtc_device,
 };
 
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index 81a4614..f8bb50c 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -15,7 +15,6 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
 
 /*
@@ -57,149 +56,8 @@
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
 };
-#endif
 
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
-#include <linux/serial_core.h>
-#include "../../../drivers/serial/sh-sci.h"
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define EPK_SCSMR_VALUE 0x000
-#define EPK_SCBRR_VALUE 0x00C
-#define EPK_FIFO_SIZE 64
-#define EPK_FIFO_BITS (0x7f00 >> 8)
-#else
-#define EPK_FIFO_SIZE 16
-#define EPK_FIFO_BITS (0x1f00 >> 8)
-#endif
-
-static struct uart_port scif_port = {
-	.type		= PORT_SCIF,
-	.mapbase	= CONFIG_EARLY_SCIF_CONSOLE_PORT,
-	.membase	= (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
-};
-
-static void scif_sercon_putc(int c)
-{
-	while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
-		;
-
-	sci_in(&scif_port, SCxSR);
-	sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
-	sci_out(&scif_port, SCxTDR, c);
-
-	while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
-		;
-
-	if (c == '\n')
-		scif_sercon_putc('\r');
-}
-
-static void scif_sercon_write(struct console *con, const char *s,
-			      unsigned count)
-{
-	while (count-- > 0)
-		scif_sercon_putc(*s++);
-}
-
-static int __init scif_sercon_setup(struct console *con, char *options)
-{
-	con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
-
-	return 0;
-}
-
-static struct console scif_console = {
-	.name		= "sercon",
-	.write		= scif_sercon_write,
-	.setup		= scif_sercon_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-#if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721)
-static void scif_sercon_init(char *s)
-{
-	sci_out(&scif_port, SCSCR, 0x0000);	/* clear TE and RE */
-	sci_out(&scif_port, SCFCR, 0x4006);	/* reset */
-	sci_out(&scif_port, SCSCR, 0x0000);	/* select internal clock */
-	sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE);
-	sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE);
-
-	mdelay(1);	/* wait 1-bit time */
-
-	sci_out(&scif_port, SCFCR, 0x0030);	/* TTRG=b'11 */
-	sci_out(&scif_port, SCSCR, 0x0030);	/* TE, RE */
-}
-#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
-#define DEFAULT_BAUD 115200
-/*
- * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
- * devices that aren't using sh-ipl+g.
- */
-static void scif_sercon_init(char *s)
-{
-	struct uart_port *port = &scif_port;
-	unsigned baud = DEFAULT_BAUD;
-	unsigned int status;
-	char *e;
-
-	if (*s == ',')
-		++s;
-
-	if (*s) {
-		/* ignore ioport/device name */
-		s += strcspn(s, ",");
-		if (*s == ',')
-			s++;
-	}
-
-	if (*s) {
-		baud = simple_strtoul(s, &e, 0);
-		if (baud == 0 || s == e)
-			baud = DEFAULT_BAUD;
-	}
-
-	do {
-		status = sci_in(port, SCxSR);
-	} while (!(status & SCxSR_TEND(port)));
-
-	sci_out(port, SCSCR, 0);	 /* TE=0, RE=0 */
-	sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
-	sci_out(port, SCSMR, 0);
-
-	/* Set baud rate */
-	sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) /
-		(32 * baud) - 1);
-	udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
-
-	sci_out(port, SCSPTR, 0);
-	sci_out(port, SCxSR, 0x60);
-	sci_out(port, SCLSR, 0);
-
-	sci_out(port, SCFCR, 0);
-	sci_out(port, SCSCR, 0x30);	 /* TE=1, RE=1 */
-}
-#endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */
-#endif /* !defined(CONFIG_SH_STANDARD_BIOS) */
-#endif /* CONFIG_EARLY_SCIF_CONSOLE */
-
-/*
- * Setup a default console, if more than one is compiled in, rely on the
- * earlyprintk= parsing to give priority.
- */
-static struct console *early_console =
-#ifdef CONFIG_SH_STANDARD_BIOS
-	&bios_console
-#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
-	&scif_console
-#else
-	NULL
-#endif
-	;
+static struct console *early_console;
 
 static int __init setup_early_printk(char *buf)
 {
@@ -211,21 +69,8 @@
 	if (strstr(buf, "keep"))
 		keep_early = 1;
 
-#ifdef CONFIG_SH_STANDARD_BIOS
 	if (!strncmp(buf, "bios", 4))
 		early_console = &bios_console;
-#endif
-#if defined(CONFIG_EARLY_SCIF_CONSOLE)
-	if (!strncmp(buf, "serial", 6)) {
-		early_console = &scif_console;
-
-#if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3)
-		scif_sercon_init(buf + 6);
-#endif
-#endif
-	}
-#endif
 
 	if (likely(early_console)) {
 		if (keep_early)
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c
index b6f41c1..a48cded 100644
--- a/arch/sh/kernel/ftrace.c
+++ b/arch/sh/kernel/ftrace.c
@@ -401,82 +401,10 @@
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
 #ifdef CONFIG_FTRACE_SYSCALLS
-
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
 extern unsigned long *sys_call_table;
 
-static struct syscall_metadata **syscalls_metadata;
-
-static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
+unsigned long __init arch_syscall_addr(int nr)
 {
-	struct syscall_metadata *start;
-	struct syscall_metadata *stop;
-	char str[KSYM_SYMBOL_LEN];
-
-
-	start = (struct syscall_metadata *)__start_syscalls_metadata;
-	stop = (struct syscall_metadata *)__stop_syscalls_metadata;
-	kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
-
-	for ( ; start < stop; start++) {
-		if (start->name && !strcmp(start->name, str))
-			return start;
-	}
-
-	return NULL;
+	return (unsigned long)sys_call_table[nr];
 }
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
-	if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
-		return NULL;
-
-	return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
-{
-	int i;
-
-	if (!syscalls_metadata)
-		return -1;
-	for (i = 0; i < NR_syscalls; i++)
-		if (syscalls_metadata[i])
-			if (!strcmp(syscalls_metadata[i]->name, name))
-				return i;
-	return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
-	syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
-{
-	syscalls_metadata[num]->exit_id = id;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
-	int i;
-	struct syscall_metadata *meta;
-	unsigned long **psys_syscall_table = &sys_call_table;
-
-	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
-					FTRACE_SYSCALL_MAX, GFP_KERNEL);
-	if (!syscalls_metadata) {
-		WARN_ON(1);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
-		meta = find_syscall_meta(psys_syscall_table[i]);
-		syscalls_metadata[i] = meta;
-	}
-
-	return 0;
-}
-arch_initcall(arch_init_ftrace_syscalls);
 #endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 359b8a2..31f80c6 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -404,7 +404,7 @@
 	if (fpvalid) {
 		if (current == last_task_used_math) {
 			enable_fpu();
-			save_fpu(tsk, regs);
+			save_fpu(tsk);
 			disable_fpu();
 			last_task_used_math = 0;
 			regs->sr |= SR_FD;
@@ -431,7 +431,7 @@
 #ifdef CONFIG_SH_FPU
 	if(last_task_used_math == current) {
 		enable_fpu();
-		save_fpu(current, regs);
+		save_fpu(current);
 		disable_fpu();
 		last_task_used_math = NULL;
 		regs->sr |= SR_FD;
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index 952da83..873ebdc 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -82,7 +82,7 @@
 
 	if (last_task_used_math == task) {
 		enable_fpu();
-		save_fpu(task, regs);
+		save_fpu(task);
 		disable_fpu();
 		last_task_used_math = 0;
 		regs->sr |= SR_FD;
@@ -118,7 +118,7 @@
 		set_stopped_child_used_math(task);
 	} else if (last_task_used_math == task) {
 		enable_fpu();
-		save_fpu(task, regs);
+		save_fpu(task);
 		disable_fpu();
 		last_task_used_math = 0;
 		regs->sr |= SR_FD;
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 5a947a2..8b0e697 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -423,6 +423,9 @@
 
 	plat_early_device_setup();
 
+	/* Let earlyprintk output early console messages */
+	early_platform_driver_probe("earlyprintk", 1, 1);
+
 	sh_mv_setup();
 
 	/*
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index feb3ddd..ce76dbd 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -314,7 +314,7 @@
 
 	if (current == last_task_used_math) {
 		enable_fpu();
-		save_fpu(current, regs);
+		save_fpu(current);
 		disable_fpu();
 		last_task_used_math = NULL;
 		regs->sr |= SR_FD;
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 19fd11d..4bd5a11 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -353,3 +353,4 @@
 	.long sys_pwritev
 	.long sys_rt_tgsigqueueinfo	/* 335 */
 	.long sys_perf_event_open
+	.long sys_recvmmsg
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 3da5a12..86639be 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -452,12 +452,18 @@
 	rm = regs->regs[index];
 
 	/* shout about fixups */
-	if (!expected && printk_ratelimit())
-		printk(KERN_NOTICE "Fixing up unaligned %s access "
-		       "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
-		       user_mode(regs) ? "userspace" : "kernel",
-		       current->comm, task_pid_nr(current),
-		       (void *)regs->pc, instruction);
+	if (!expected) {
+		if (user_mode(regs) && (se_usermode & 1) && printk_ratelimit())
+			pr_notice("Fixing up unaligned userspace access "
+				  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+				  current->comm, task_pid_nr(current),
+				  (void *)regs->pc, instruction);
+		else if (se_kernmode_warn && printk_ratelimit())
+			pr_notice("Fixing up unaligned kernel access "
+				  "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
+				  current->comm, task_pid_nr(current),
+				  (void *)regs->pc, instruction);
+	}
 
 	ret = -EFAULT;
 	switch (instruction&0xF000) {
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 75c0cbe..d86f531 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -600,7 +600,7 @@
 		   indexed by register number. */
 		if (last_task_used_math == current) {
 			enable_fpu();
-			save_fpu(current, regs);
+			save_fpu(current);
 			disable_fpu();
 			last_task_used_math = NULL;
 			regs->sr |= SR_FD;
@@ -673,7 +673,7 @@
 		   indexed by register number. */
 		if (last_task_used_math == current) {
 			enable_fpu();
-			save_fpu(current, regs);
+			save_fpu(current);
 			disable_fpu();
 			last_task_used_math = NULL;
 			regs->sr |= SR_FD;
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index f36a08b..560ddb6 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -256,8 +256,7 @@
 		address = (unsigned long)vaddr;
 	}
 
-	if (pages_do_alias(address, phys))
-		flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
+	flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
 			(address & shm_align_mask), phys);
 
 	if (vma->vm_flags & VM_EXEC)
diff --git a/arch/sh/mm/ioremap_32.c b/arch/sh/mm/ioremap_32.c
index a86eaa9..2141bef 100644
--- a/arch/sh/mm/ioremap_32.c
+++ b/arch/sh/mm/ioremap_32.c
@@ -33,10 +33,10 @@
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
-			unsigned long flags)
+void __iomem *__ioremap_caller(unsigned long phys_addr, unsigned long size,
+			       unsigned long flags, void *caller)
 {
-	struct vm_struct * area;
+	struct vm_struct *area;
 	unsigned long offset, last_addr, addr, orig_addr;
 	pgprot_t pgprot;
 
@@ -67,7 +67,7 @@
 	/*
 	 * Ok, go for it..
 	 */
-	area = get_vm_area(size, VM_IOREMAP);
+	area = get_vm_area_caller(size, VM_IOREMAP, caller);
 	if (!area)
 		return NULL;
 	area->phys_addr = phys_addr;
@@ -103,7 +103,7 @@
 
 	return (void __iomem *)(offset + (char *)orig_addr);
 }
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(__ioremap_caller);
 
 void __iounmap(void __iomem *addr)
 {
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
index b16843d..ef43465 100644
--- a/arch/sh/mm/ioremap_64.c
+++ b/arch/sh/mm/ioremap_64.c
@@ -258,15 +258,15 @@
 	pte_clear(&init_mm, vaddr, ptep);
 }
 
-void __iomem *__ioremap(unsigned long offset, unsigned long size,
-			unsigned long flags)
+void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
+			       unsigned long flags, void *caller)
 {
 	char name[14];
 
 	sprintf(name, "phys_%08x", (u32)offset);
 	return shmedia_alloc_io(offset, size, name, flags);
 }
-EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(__ioremap_caller);
 
 void __iounmap(void __iomem *virtual)
 {
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 6c52444..422e927 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -28,7 +28,7 @@
 {
 	unsigned long free_pfn = PFN_UP(__pa(_end));
 	u64 base = min_low_pfn << PAGE_SHIFT;
-	u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn;
+	u64 size = (max_low_pfn << PAGE_SHIFT) - base;
 
 	lmb_add(base, size);
 
@@ -38,6 +38,15 @@
 		    (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET));
 
 	/*
+	 * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET.
+	 */
+	if (CONFIG_ZERO_PAGE_OFFSET != 0)
+		lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET);
+
+	lmb_analyze();
+	lmb_dump_all();
+
+	/*
 	 * Node 0 sets up its pgdat at the first available pfn,
 	 * and bumps it up before setting up the bootmem allocator.
 	 */
@@ -71,7 +80,7 @@
 
 	/* Node-local pgdat */
 	NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data),
-					     SMP_CACHE_BYTES, end_pfn));
+					     SMP_CACHE_BYTES, end));
 	memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
 	NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
@@ -81,7 +90,7 @@
 	/* Node-local bootmap */
 	bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
 	bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
-				       PAGE_SIZE, end_pfn);
+				       PAGE_SIZE, end);
 	init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
 			  start_pfn, end_pfn);
 
diff --git a/arch/sh/tools/Makefile b/arch/sh/tools/Makefile
index 567516b..558a56b 100644
--- a/arch/sh/tools/Makefile
+++ b/arch/sh/tools/Makefile
@@ -10,7 +10,7 @@
 # Shamelessly cloned from ARM.
 #
 
-include/asm-sh/machtypes.h: $(src)/gen-mach-types $(src)/mach-types
+include/generated/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)mkdir -p $(dir $@)
 	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
diff --git a/arch/sh/tools/gen-mach-types b/arch/sh/tools/gen-mach-types
index 65161e3..f5ff7c5 100644
--- a/arch/sh/tools/gen-mach-types
+++ b/arch/sh/tools/gen-mach-types
@@ -1,6 +1,6 @@
 #!/bin/awk
 #
-# Awk script to generate include/asm-sh/machtypes.h
+# Awk script to generate include/generated/machtypes.h
 # Heavily based on arch/arm/tools/gen-mach-types
 #
 BEGIN	{ nr = 0 }
diff --git a/arch/sparc/include/asm/asm-offsets.h b/arch/sparc/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/sparc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
index 381a1b5..4269ca6 100644
--- a/arch/sparc/include/asm/elf_32.h
+++ b/arch/sparc/include/asm/elf_32.h
@@ -104,8 +104,6 @@
 #define ELF_CLASS	ELFCLASS32
 #define ELF_DATA	ELFDATA2MSB
 
-#define USE_ELF_CORE_DUMP
-
 #define ELF_EXEC_PAGESIZE	4096
 
 
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
index d42e393..ff66bb8 100644
--- a/arch/sparc/include/asm/elf_64.h
+++ b/arch/sparc/include/asm/elf_64.h
@@ -152,7 +152,6 @@
 					 (x)->e_machine == EM_SPARC32PLUS)
 #define compat_start_thread		start_thread32
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h
index 3b9cfb3..38f37b33 100644
--- a/arch/sparc/include/asm/fcntl.h
+++ b/arch/sparc/include/asm/fcntl.h
@@ -19,7 +19,7 @@
 #define O_NOATIME	0x200000
 #define O_CLOEXEC	0x400000
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 7690cc2..5fad949 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -11,6 +11,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/iommu-helper.h>
+#include <linux/bitmap.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -169,7 +170,7 @@
 
 	entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
 
-	iommu_area_free(arena->map, entry, npages);
+	bitmap_clear(arena->map, entry, npages);
 }
 
 int iommu_table_init(struct iommu *iommu, int tsbsize,
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index e0ba898..df39a0f 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/init.h>
+#include <linux/bitmap.h>
 
 #include <asm/hypervisor.h>
 #include <asm/iommu.h>
@@ -1875,7 +1876,7 @@
 static long arena_alloc(struct ldc_iommu *iommu, unsigned long npages)
 {
 	struct iommu_arena *arena = &iommu->arena;
-	unsigned long n, i, start, end, limit;
+	unsigned long n, start, end, limit;
 	int pass;
 
 	limit = arena->limit;
@@ -1883,7 +1884,7 @@
 	pass = 0;
 
 again:
-	n = find_next_zero_bit(arena->map, limit, start);
+	n = bitmap_find_next_zero_area(arena->map, limit, start, npages, 0);
 	end = n + npages;
 	if (unlikely(end >= limit)) {
 		if (likely(pass < 1)) {
@@ -1896,16 +1897,7 @@
 			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);
+	bitmap_set(arena->map, n, npages);
 
 	arena->hint = end;
 
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index b85374f..539e83f 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -1064,7 +1064,6 @@
 
 	return (device_mask & dma_addr_mask) == dma_addr_mask;
 }
-EXPORT_SYMBOL(pci_dma_supported);
 
 void pci_resource_to_user(const struct pci_dev *pdev, int bar,
 			  const struct resource *rp, resource_size_t *start,
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index 0f26066..372ad59 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -38,17 +38,5 @@
 EXPORT_SYMBOL(sun4v_niagara2_getperf);
 EXPORT_SYMBOL(sun4v_niagara2_setperf);
 
-#ifdef CONFIG_PCI
-/* inline functions in asm/pci_64.h */
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_unmap_sg);
-EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
-EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
-#endif
-
 /* Exporting a symbol from /init/main.c */
 EXPORT_SYMBOL(saved_command_line);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 2ffacd6..a89baf0 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -17,6 +17,7 @@
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
+#include <linux/bitmap.h>
 
 #include <asm/sections.h>
 #include <asm/page.h>
@@ -1021,20 +1022,12 @@
 	npages = (((unsigned long)vaddr & ~PAGE_MASK) +
 		  size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
 
-	scan = 0;
 	local_irq_save(flags);
-	for (;;) {
-		scan = find_next_zero_bit(sun4c_iobuffer_map,
-					  iobuffer_map_size, scan);
-		if ((base = scan) + npages > iobuffer_map_size) goto abend;
-		for (;;) {
-			if (scan >= base + npages) goto found;
-			if (test_bit(scan, sun4c_iobuffer_map)) break;
-			scan++;
-		}
-	}
+	base = bitmap_find_next_zero_area(sun4c_iobuffer_map, iobuffer_map_size,
+						0, npages, 0);
+	if (base >= iobuffer_map_size)
+		goto abend;
 
-found:
 	high = ((base + npages) << PAGE_SHIFT) + sun4c_iobuffer_start;
 	high = SUN4C_REAL_PGDIR_ALIGN(high);
 	while (high > sun4c_iobuffer_high) {
diff --git a/arch/um/Makefile b/arch/um/Makefile
index fc633db..fab8121 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -149,6 +149,6 @@
 
 $(SHARED_HEADERS)/kern_constants.h:
 	$(Q)mkdir -p $(dir $@)
-	$(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
+	$(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@
 
 export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
diff --git a/arch/um/include/asm/asm-offsets.h b/arch/um/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/um/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index d0da9d7..7708854 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -48,7 +48,6 @@
 	PT_REGS_EAX(regs) = 0; \
 } while (0)
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE 4096
 
 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
diff --git a/arch/um/sys-ppc/asm/elf.h b/arch/um/sys-ppc/asm/elf.h
index af9463c..8aacaf5 100644
--- a/arch/um/sys-ppc/asm/elf.h
+++ b/arch/um/sys-ppc/asm/elf.h
@@ -17,8 +17,6 @@
 #define ELF_CLASS ELFCLASS32
 #endif
 
-#define USE_ELF_CORE_DUMP
-
 #define R_386_NONE	0
 #define R_386_32	1
 #define R_386_PC32	2
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index 04b9e87..49655c8 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -104,7 +104,6 @@
         clear_thread_flag(TIF_IA32);
 #endif
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE 4096
 
 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
index bbeb0c3..89bbf4e 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/boot/compressed/relocs.c
@@ -9,6 +9,9 @@
 #include <byteswap.h>
 #define USE_BSD
 #include <endian.h>
+#include <regex.h>
+
+static void die(char *fmt, ...);
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 static Elf32_Ehdr ehdr;
@@ -30,25 +33,47 @@
  * the address for which it has been compiled. Don't warn user about
  * absolute relocations present w.r.t these symbols.
  */
-static const char* safe_abs_relocs[] = {
-		"xen_irq_disable_direct_reloc",
-		"xen_save_fl_direct_reloc",
-};
-
-static int is_safe_abs_reloc(const char* sym_name)
+static const char abs_sym_regex[] =
+	"^(xen_irq_disable_direct_reloc$|"
+	"xen_save_fl_direct_reloc$|"
+	"VDSO|"
+	"__crc_)";
+static regex_t abs_sym_regex_c;
+static int is_abs_reloc(const char *sym_name)
 {
-	int i;
+	return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0);
+}
 
-	for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
-		if (!strcmp(sym_name, safe_abs_relocs[i]))
-			/* Match found */
-			return 1;
-	}
-	if (strncmp(sym_name, "VDSO", 4) == 0)
-		return 1;
-	if (strncmp(sym_name, "__crc_", 6) == 0)
-		return 1;
-	return 0;
+/*
+ * These symbols are known to be relative, even if the linker marks them
+ * as absolute (typically defined outside any section in the linker script.)
+ */
+static const char rel_sym_regex[] =
+	"^_end$";
+static regex_t rel_sym_regex_c;
+static int is_rel_reloc(const char *sym_name)
+{
+	return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0);
+}
+
+static void regex_init(void)
+{
+        char errbuf[128];
+        int err;
+	
+        err = regcomp(&abs_sym_regex_c, abs_sym_regex,
+                      REG_EXTENDED|REG_NOSUB);
+        if (err) {
+                regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf);
+                die("%s", errbuf);
+        }
+
+        err = regcomp(&rel_sym_regex_c, rel_sym_regex,
+                      REG_EXTENDED|REG_NOSUB);
+        if (err) {
+                regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf);
+                die("%s", errbuf);
+        }
 }
 
 static void die(char *fmt, ...)
@@ -131,7 +156,7 @@
 #undef REL_TYPE
 	};
 	const char *name = "unknown type rel type name";
-	if (type < ARRAY_SIZE(type_name)) {
+	if (type < ARRAY_SIZE(type_name) && type_name[type]) {
 		name = type_name[type];
 	}
 	return name;
@@ -448,7 +473,7 @@
 			 * Before warning check if this absolute symbol
 			 * relocation is harmless.
 			 */
-			if (is_safe_abs_reloc(name))
+			if (is_abs_reloc(name) || is_rel_reloc(name))
 				continue;
 
 			if (!printed) {
@@ -501,21 +526,26 @@
 			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 			r_type = ELF32_R_TYPE(rel->r_info);
 			/* Don't visit relocations to absolute symbols */
-			if (sym->st_shndx == SHN_ABS) {
+			if (sym->st_shndx == SHN_ABS &&
+			    !is_rel_reloc(sym_name(sym_strtab, sym))) {
 				continue;
 			}
-			if (r_type == R_386_NONE || r_type == R_386_PC32) {
+			switch (r_type) {
+			case R_386_NONE:
+			case R_386_PC32:
 				/*
 				 * NONE can be ignored and and PC relative
 				 * relocations don't need to be adjusted.
 				 */
-			}
-			else if (r_type == R_386_32) {
+				break;
+			case R_386_32:
 				/* Visit relocations that need to be adjusted */
 				visit(rel, sym);
-			}
-			else {
-				die("Unsupported relocation type: %d\n", r_type);
+				break;
+			default:
+				die("Unsupported relocation type: %s (%d)\n",
+				    rel_type(r_type), r_type);
+				break;
 			}
 		}
 	}
@@ -571,16 +601,15 @@
 	}
 	else {
 		unsigned char buf[4];
-		buf[0] = buf[1] = buf[2] = buf[3] = 0;
 		/* Print a stop */
-		printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
+		fwrite("\0\0\0\0", 4, 1, stdout);
 		/* Now print each relocation */
 		for (i = 0; i < reloc_count; i++) {
 			buf[0] = (relocs[i] >>  0) & 0xff;
 			buf[1] = (relocs[i] >>  8) & 0xff;
 			buf[2] = (relocs[i] >> 16) & 0xff;
 			buf[3] = (relocs[i] >> 24) & 0xff;
-			printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
+			fwrite(buf, 4, 1, stdout);
 		}
 	}
 }
@@ -598,6 +627,8 @@
 	FILE *fp;
 	int i;
 
+	regex_init();
+
 	show_absolute_syms = 0;
 	show_absolute_relocs = 0;
 	as_text = 0;
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b31cc54..93e689f4 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -16,7 +16,7 @@
  */
 
 #include <asm/segment.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <asm/boot.h>
 #include <asm/e820.h>
 #include <asm/page_types.h>
diff --git a/arch/x86/boot/version.c b/arch/x86/boot/version.c
index 2723d9b..2b15aa4 100644
--- a/arch/x86/boot/version.c
+++ b/arch/x86/boot/version.c
@@ -13,8 +13,8 @@
  */
 
 #include "boot.h"
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
+#include <generated/utsrelease.h>
+#include <generated/compile.h>
 
 const char kernel_version[] =
 	UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") "
diff --git a/arch/x86/include/asm/asm-offsets.h b/arch/x86/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/x86/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 0f6c02f..ac91eed 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -67,7 +67,7 @@
 	if (!dev->dma_mask)
 		return 0;
 
-	return addr + size <= *dev->dma_mask;
+	return addr + size - 1 <= *dev->dma_mask;
 }
 
 static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 8a024ba..b4501ee 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -239,7 +239,6 @@
 #endif /* !CONFIG_X86_32 */
 
 #define CORE_DUMP_USE_REGSET
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 3d11fd0..9d369f6 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -292,6 +292,8 @@
 #define arch_has_block_step()	(boot_cpu_data.x86 >= 6)
 #endif
 
+#define ARCH_HAS_USER_SINGLE_STEP_INFO
+
 struct user_desc;
 extern int do_get_thread_area(struct task_struct *p, int idx,
 			      struct user_desc __user *info);
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 87ffcb1..8085277 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -5,13 +5,17 @@
 
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
-extern int pci_swiotlb_init(void);
+extern int __init pci_swiotlb_detect(void);
+extern void __init pci_swiotlb_init(void);
 #else
 #define swiotlb 0
-static inline int pci_swiotlb_init(void)
+static inline int pci_swiotlb_detect(void)
 {
 	return 0;
 }
+static inline void pci_swiotlb_init(void)
+{
+}
 #endif
 
 static inline void dma_mark_clean(void *addr, size_t size) {}
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 4a5a089e..d5f6904 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -30,7 +30,6 @@
 asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
 asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
 
-asmlinkage long sys32_pipe(int __user *);
 struct sigaction32;
 struct old_sigaction32;
 asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 1bb6e39..8868b94 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -18,16 +18,24 @@
 /* Common in X86_32 and X86_64 */
 /* kernel/ioport.c */
 asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
+long sys_iopl(unsigned int, struct pt_regs *);
 
 /* kernel/process.c */
 int sys_fork(struct pt_regs *);
 int sys_vfork(struct pt_regs *);
+long sys_execve(char __user *, char __user * __user *,
+		char __user * __user *, struct pt_regs *);
+long sys_clone(unsigned long, unsigned long, void __user *,
+	       void __user *, struct pt_regs *);
 
 /* kernel/ldt.c */
 asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
 
 /* kernel/signal.c */
 long sys_rt_sigreturn(struct pt_regs *);
+long sys_sigaltstack(const stack_t __user *, stack_t __user *,
+		     struct pt_regs *);
+
 
 /* kernel/tls.c */
 asmlinkage int sys_set_thread_area(struct user_desc __user *);
@@ -35,18 +43,11 @@
 
 /* X86_32 only */
 #ifdef CONFIG_X86_32
-/* kernel/ioport.c */
-long sys_iopl(struct pt_regs *);
-
-/* kernel/process_32.c */
-int sys_clone(struct pt_regs *);
-int sys_execve(struct pt_regs *);
 
 /* kernel/signal.c */
 asmlinkage int sys_sigsuspend(int, int, old_sigset_t);
 asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
 			     struct old_sigaction __user *);
-int sys_sigaltstack(struct pt_regs *);
 unsigned long sys_sigreturn(struct pt_regs *);
 
 /* kernel/sys_i386_32.c */
@@ -62,28 +63,15 @@
 asmlinkage int sys_olduname(struct oldold_utsname __user *);
 
 /* kernel/vm86_32.c */
-int sys_vm86old(struct pt_regs *);
-int sys_vm86(struct pt_regs *);
+int sys_vm86old(struct vm86_struct __user *, struct pt_regs *);
+int sys_vm86(unsigned long, unsigned long, struct pt_regs *);
 
 #else /* CONFIG_X86_32 */
 
 /* X86_64 only */
-/* kernel/ioport.c */
-asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
-
 /* kernel/process_64.c */
-asmlinkage long sys_clone(unsigned long, unsigned long,
-			  void __user *, void __user *,
-			  struct pt_regs *);
-asmlinkage long sys_execve(char __user *, char __user * __user *,
-			   char __user * __user *,
-			   struct pt_regs *);
 long sys_arch_prctl(int, unsigned long);
 
-/* kernel/signal.c */
-asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
-				struct pt_regs *);
-
 /* kernel/sys_x86_64.c */
 struct new_utsname;
 
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index 7ed17ff..2751f30 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -76,15 +76,6 @@
 	};
 };
 
-union uv_watchlist_u {
-	u64	val;
-	struct {
-		u64	blade	: 16,
-			size	: 32,
-			filler	: 16;
-	};
-};
-
 enum uv_memprotect {
 	UV_MEMPROT_RESTRICT_ACCESS,
 	UV_MEMPROT_ALLOW_AMO,
@@ -100,7 +91,7 @@
 
 extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *);
 extern s64 uv_bios_freq_base(u64, u64 *);
-extern int uv_bios_mq_watchlist_alloc(int, unsigned long, unsigned int,
+extern int uv_bios_mq_watchlist_alloc(unsigned long, unsigned int,
 					unsigned long *);
 extern int uv_bios_mq_watchlist_free(int, int);
 extern s64 uv_bios_change_memprotect(u64, u64, enum uv_memprotect);
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index d1414af..811bfab 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -172,6 +172,8 @@
 #define UV_LOCAL_MMR_SIZE		(64UL * 1024 * 1024)
 #define UV_GLOBAL_MMR32_SIZE		(64UL * 1024 * 1024)
 
+#define UV_GLOBAL_GRU_MMR_BASE		0x4000000
+
 #define UV_GLOBAL_MMR32_PNODE_SHIFT	15
 #define UV_GLOBAL_MMR64_PNODE_SHIFT	26
 
@@ -232,6 +234,26 @@
 	return uv_soc_phys_ram_to_gpa(__pa(v));
 }
 
+/* Top two bits indicate the requested address is in MMR space.  */
+static inline int
+uv_gpa_in_mmr_space(unsigned long gpa)
+{
+	return (gpa >> 62) == 0x3UL;
+}
+
+/* UV global physical address --> socket phys RAM */
+static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
+{
+	unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+	unsigned long remap_base = uv_hub_info->lowmem_remap_base;
+	unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
+
+	if (paddr >= remap_base && paddr < remap_base + remap_top)
+		paddr -= remap_base;
+	return paddr;
+}
+
+
 /* gnode -> pnode */
 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
 {
@@ -308,6 +330,15 @@
 }
 
 /*
+ * Global MMR space addresses when referenced by the GRU. (GRU does
+ * NOT use socket addressing).
+ */
+static inline unsigned long uv_global_gru_mmr_address(int pnode, unsigned long offset)
+{
+	return UV_GLOBAL_GRU_MMR_BASE | offset | (pnode << uv_hub_info->m_val);
+}
+
+/*
  * Access hub local MMRs. Faster than using global space but only local MMRs
  * are accessible.
  */
@@ -434,6 +465,14 @@
 	}
 }
 
+static unsigned long uv_hub_ipi_value(int apicid, int vector, int mode)
+{
+	return (1UL << UVH_IPI_INT_SEND_SHFT) |
+			((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
+			(mode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
+			(vector << UVH_IPI_INT_VECTOR_SHFT);
+}
+
 static inline void uv_hub_send_ipi(int pnode, int apicid, int vector)
 {
 	unsigned long val;
@@ -442,10 +481,7 @@
 	if (vector == NMI_VECTOR)
 		dmode = dest_NMI;
 
-	val = (1UL << UVH_IPI_INT_SEND_SHFT) |
-			((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
-			(dmode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
-			(vector << UVH_IPI_INT_VECTOR_SHFT);
+	val = uv_hub_ipi_value(apicid, vector, dmode);
 	uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
 }
 
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 59cdfa4..2e837f5 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -48,7 +48,7 @@
 	 * P4, Core and beyond CPUs
 	 */
 	if (c->x86_vendor == X86_VENDOR_INTEL &&
-	    (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 14)))
+	    (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
 			flags->bm_control = 0;
 }
 EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index b990b5c..23824fe 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -19,7 +19,7 @@
 
 #include <linux/pci.h>
 #include <linux/gfp.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/debugfs.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
@@ -1162,7 +1162,7 @@
 
 	address = (address % APERTURE_RANGE_SIZE) >> PAGE_SHIFT;
 
-	iommu_area_free(range->bitmap, address, pages);
+	bitmap_clear(range->bitmap, address, pages);
 
 }
 
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c
index 63a88e1..b0206a2 100644
--- a/arch/x86/kernel/bios_uv.c
+++ b/arch/x86/kernel/bios_uv.c
@@ -101,21 +101,17 @@
 }
 
 int
-uv_bios_mq_watchlist_alloc(int blade, unsigned long addr, unsigned int mq_size,
+uv_bios_mq_watchlist_alloc(unsigned long addr, unsigned int mq_size,
 			   unsigned long *intr_mmr_offset)
 {
-	union uv_watchlist_u size_blade;
 	u64 watchlist;
 	s64 ret;
 
-	size_blade.size = mq_size;
-	size_blade.blade = blade;
-
 	/*
 	 * bios returns watchlist number or negative error number.
 	 */
 	ret = (int)uv_bios_call_irqsave(UV_BIOS_WATCHLIST_ALLOC, addr,
-			size_blade.val, (u64)intr_mmr_offset,
+			mq_size, (u64)intr_mmr_offset,
 			(u64)&watchlist, 0);
 	if (ret < BIOS_STATUS_SUCCESS)
 		return ret;
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 472763d..73734ba 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -74,7 +74,7 @@
 	m->finished = 0;
 }
 
-static cpumask_t mce_inject_cpumask;
+static cpumask_var_t mce_inject_cpumask;
 
 static int mce_raise_notify(struct notifier_block *self,
 			    unsigned long val, void *data)
@@ -82,9 +82,9 @@
 	struct die_args *args = (struct die_args *)data;
 	int cpu = smp_processor_id();
 	struct mce *m = &__get_cpu_var(injectm);
-	if (val != DIE_NMI_IPI || !cpu_isset(cpu, mce_inject_cpumask))
+	if (val != DIE_NMI_IPI || !cpumask_test_cpu(cpu, mce_inject_cpumask))
 		return NOTIFY_DONE;
-	cpu_clear(cpu, mce_inject_cpumask);
+	cpumask_clear_cpu(cpu, mce_inject_cpumask);
 	if (m->inject_flags & MCJ_EXCEPTION)
 		raise_exception(m, args->regs);
 	else if (m->status)
@@ -148,22 +148,22 @@
 		unsigned long start;
 		int cpu;
 		get_online_cpus();
-		mce_inject_cpumask = cpu_online_map;
-		cpu_clear(get_cpu(), mce_inject_cpumask);
+		cpumask_copy(mce_inject_cpumask, cpu_online_mask);
+		cpumask_clear_cpu(get_cpu(), mce_inject_cpumask);
 		for_each_online_cpu(cpu) {
 			struct mce *mcpu = &per_cpu(injectm, cpu);
 			if (!mcpu->finished ||
 			    MCJ_CTX(mcpu->inject_flags) != MCJ_CTX_RANDOM)
-				cpu_clear(cpu, mce_inject_cpumask);
+				cpumask_clear_cpu(cpu, mce_inject_cpumask);
 		}
-		if (!cpus_empty(mce_inject_cpumask))
-			apic->send_IPI_mask(&mce_inject_cpumask, NMI_VECTOR);
+		if (!cpumask_empty(mce_inject_cpumask))
+			apic->send_IPI_mask(mce_inject_cpumask, NMI_VECTOR);
 		start = jiffies;
-		while (!cpus_empty(mce_inject_cpumask)) {
+		while (!cpumask_empty(mce_inject_cpumask)) {
 			if (!time_before(jiffies, start + 2*HZ)) {
 				printk(KERN_ERR
 				"Timeout waiting for mce inject NMI %lx\n",
-					*cpus_addr(mce_inject_cpumask));
+					*cpumask_bits(mce_inject_cpumask));
 				break;
 			}
 			cpu_relax();
@@ -210,6 +210,8 @@
 
 static int inject_init(void)
 {
+	if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
+		return -ENOMEM;
 	printk(KERN_INFO "Machine check injector initialized\n");
 	mce_chrdev_ops.write = mce_write;
 	register_die_notifier(&mce_raise_nb);
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 50b9c22..44a8e0d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -725,22 +725,61 @@
 /*
  * System calls that need a pt_regs pointer.
  */
-#define PTREGSCALL(name) \
+#define PTREGSCALL0(name) \
 	ALIGN; \
 ptregs_##name: \
 	leal 4(%esp),%eax; \
 	jmp sys_##name;
 
-PTREGSCALL(iopl)
-PTREGSCALL(fork)
-PTREGSCALL(clone)
-PTREGSCALL(vfork)
-PTREGSCALL(execve)
-PTREGSCALL(sigaltstack)
-PTREGSCALL(sigreturn)
-PTREGSCALL(rt_sigreturn)
-PTREGSCALL(vm86)
-PTREGSCALL(vm86old)
+#define PTREGSCALL1(name) \
+	ALIGN; \
+ptregs_##name: \
+	leal 4(%esp),%edx; \
+	movl (PT_EBX+4)(%esp),%eax; \
+	jmp sys_##name;
+
+#define PTREGSCALL2(name) \
+	ALIGN; \
+ptregs_##name: \
+	leal 4(%esp),%ecx; \
+	movl (PT_ECX+4)(%esp),%edx; \
+	movl (PT_EBX+4)(%esp),%eax; \
+	jmp sys_##name;
+
+#define PTREGSCALL3(name) \
+	ALIGN; \
+ptregs_##name: \
+	leal 4(%esp),%eax; \
+	pushl %eax; \
+	movl PT_EDX(%eax),%ecx; \
+	movl PT_ECX(%eax),%edx; \
+	movl PT_EBX(%eax),%eax; \
+	call sys_##name; \
+	addl $4,%esp; \
+	ret
+
+PTREGSCALL1(iopl)
+PTREGSCALL0(fork)
+PTREGSCALL0(vfork)
+PTREGSCALL3(execve)
+PTREGSCALL2(sigaltstack)
+PTREGSCALL0(sigreturn)
+PTREGSCALL0(rt_sigreturn)
+PTREGSCALL2(vm86)
+PTREGSCALL1(vm86old)
+
+/* Clone is an oddball.  The 4th arg is in %edi */
+	ALIGN;
+ptregs_clone:
+	leal 4(%esp),%eax
+	pushl %eax
+	pushl PT_EDI(%eax)
+	movl PT_EDX(%eax),%ecx
+	movl PT_ECX(%eax),%edx
+	movl PT_EBX(%eax),%eax
+	call sys_clone
+	addl $8,%esp
+	ret
 
 .macro FIXUP_ESPFIX_STACK
 /*
@@ -1008,12 +1047,8 @@
 ENTRY(kernel_thread_helper)
 	pushl $0		# fake return address for unwinder
 	CFI_STARTPROC
-	movl %edx,%eax
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
-	call *%ebx
-	push %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	movl %edi,%eax
+	call *%esi
 	call do_exit
 	ud2			# padding for call trace
 	CFI_ENDPROC
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 673f693..0697ff1 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1166,63 +1166,20 @@
 	jmp  2b
 	.previous
 
-/*
- * Create a kernel thread.
- *
- * C extern interface:
- *	extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
- *
- * asm input arguments:
- *	rdi: fn, rsi: arg, rdx: flags
- */
-ENTRY(kernel_thread)
-	CFI_STARTPROC
-	FAKE_STACK_FRAME $child_rip
-	SAVE_ALL
-
-	# rdi: flags, rsi: usp, rdx: will be &pt_regs
-	movq %rdx,%rdi
-	orq  kernel_thread_flags(%rip),%rdi
-	movq $-1, %rsi
-	movq %rsp, %rdx
-
-	xorl %r8d,%r8d
-	xorl %r9d,%r9d
-
-	# clone now
-	call do_fork
-	movq %rax,RAX(%rsp)
-	xorl %edi,%edi
-
-	/*
-	 * It isn't worth to check for reschedule here,
-	 * so internally to the x86_64 port you can rely on kernel_thread()
-	 * not to reschedule the child before returning, this avoids the need
-	 * of hacks for example to fork off the per-CPU idle tasks.
-	 * [Hopefully no generic code relies on the reschedule -AK]
-	 */
-	RESTORE_ALL
-	UNFAKE_STACK_FRAME
-	ret
-	CFI_ENDPROC
-END(kernel_thread)
-
-ENTRY(child_rip)
+ENTRY(kernel_thread_helper)
 	pushq $0		# fake return address
 	CFI_STARTPROC
 	/*
 	 * Here we are in the child and the registers are set as they were
 	 * at kernel_thread() invocation in the parent.
 	 */
-	movq %rdi, %rax
-	movq %rsi, %rdi
-	call *%rax
+	call *%rsi
 	# exit
 	mov %eax, %edi
 	call do_exit
 	ud2			# padding for call trace
 	CFI_ENDPROC
-END(child_rip)
+END(kernel_thread_helper)
 
 /*
  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 99c4d30..8eec0ec 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -103,9 +103,10 @@
  * on system-call entry - see also fork() and the signal handling
  * code.
  */
-static int do_iopl(unsigned int level, struct pt_regs *regs)
+long sys_iopl(unsigned int level, struct pt_regs *regs)
 {
 	unsigned int old = (regs->flags >> 12) & 3;
+	struct thread_struct *t = &current->thread;
 
 	if (level > 3)
 		return -EINVAL;
@@ -115,29 +116,8 @@
 			return -EPERM;
 	}
 	regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
+	t->iopl = level << 12;
+	set_iopl_mask(t->iopl);
 
 	return 0;
 }
-
-#ifdef CONFIG_X86_32
-long sys_iopl(struct pt_regs *regs)
-{
-	unsigned int level = regs->bx;
-	struct thread_struct *t = &current->thread;
-	int rc;
-
-	rc = do_iopl(level, regs);
-	if (rc < 0)
-		goto out;
-
-	t->iopl = level << 12;
-	set_iopl_mask(t->iopl);
-out:
-	return rc;
-}
-#else
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
-{
-	return do_iopl(level, regs);
-}
-#endif
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 5534499..572b07e 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -172,11 +172,10 @@
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	unsigned int cpu;
+	struct cpuinfo_x86 *c;
 
 	cpu = iminor(file->f_path.dentry->d_inode);
-
 	if (cpu >= nr_cpu_ids || !cpu_online(cpu))
 		return -ENXIO;	/* No such CPU */
 
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index c563e4c..2bbde60 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 #include <linux/crash_dump.h>
 #include <linux/dma-mapping.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -212,7 +212,7 @@
 
 	spin_lock_irqsave(&tbl->it_lock, flags);
 
-	iommu_area_reserve(tbl->it_map, index, npages);
+	bitmap_set(tbl->it_map, index, npages);
 
 	spin_unlock_irqrestore(&tbl->it_lock, flags);
 }
@@ -303,7 +303,7 @@
 
 	spin_lock_irqsave(&tbl->it_lock, flags);
 
-	iommu_area_free(tbl->it_map, entry, npages);
+	bitmap_clear(tbl->it_map, entry, npages);
 
 	spin_unlock_irqrestore(&tbl->it_lock, flags);
 }
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index fcc2f2b..75e14e2 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -120,15 +120,12 @@
 
 void __init pci_iommu_alloc(void)
 {
-	int use_swiotlb;
-
-	use_swiotlb = pci_swiotlb_init();
 #ifdef CONFIG_X86_64
 	/* free the range so iommu could get some range less than 4G */
 	dma32_free_bootmem();
 #endif
-	if (use_swiotlb)
-		return;
+	if (pci_swiotlb_detect())
+		goto out;
 
 	gart_iommu_hole_init();
 
@@ -138,6 +135,8 @@
 
 	/* needs to be called after gart_iommu_hole_init */
 	amd_iommu_detect();
+out:
+	pci_swiotlb_init();
 }
 
 void *dma_generic_alloc_coherent(struct device *dev, size_t size,
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 56c0e73..34de53b 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/topology.h>
 #include <linux/interrupt.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 #include <linux/kdebug.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
@@ -126,7 +126,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
-	iommu_area_free(iommu_gart_bitmap, offset, size);
+	bitmap_clear(iommu_gart_bitmap, offset, size);
 	if (offset >= next_bit)
 		next_bit = offset + size;
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -792,7 +792,7 @@
 	 * Out of IOMMU space handling.
 	 * Reserve some invalid pages at the beginning of the GART.
 	 */
-	iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES);
+	bitmap_set(iommu_gart_bitmap, 0, EMERGENCY_PAGES);
 
 	pr_info("PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n",
 	       iommu_size >> 20);
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index e3c0a66..7d2829d 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -43,12 +43,12 @@
 };
 
 /*
- * pci_swiotlb_init - initialize swiotlb if necessary
+ * pci_swiotlb_detect - set swiotlb to 1 if necessary
  *
  * This returns non-zero if we are forced to use swiotlb (by the boot
  * option).
  */
-int __init pci_swiotlb_init(void)
+int __init pci_swiotlb_detect(void)
 {
 	int use_swiotlb = swiotlb | swiotlb_force;
 
@@ -60,10 +60,13 @@
 	if (swiotlb_force)
 		swiotlb = 1;
 
+	return use_swiotlb;
+}
+
+void __init pci_swiotlb_init(void)
+{
 	if (swiotlb) {
 		swiotlb_init(0);
 		dma_ops = &swiotlb_dma_ops;
 	}
-
-	return use_swiotlb;
 }
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 7a7bd4e..98c2cde 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -255,6 +255,76 @@
 		       NULL, NULL);
 }
 
+long
+sys_clone(unsigned long clone_flags, unsigned long newsp,
+	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->sp;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+}
+
+/*
+ * This gets run with %si containing the
+ * function to call, and %di containing
+ * the "args".
+ */
+extern void kernel_thread_helper(void);
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.si = (unsigned long) fn;
+	regs.di = (unsigned long) arg;
+
+#ifdef CONFIG_X86_32
+	regs.ds = __USER_DS;
+	regs.es = __USER_DS;
+	regs.fs = __KERNEL_PERCPU;
+	regs.gs = __KERNEL_STACK_CANARY;
+#endif
+
+	regs.orig_ax = -1;
+	regs.ip = (unsigned long) kernel_thread_helper;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | 0x2;
+
+	/* Ok, create the new process.. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * sys_execve() executes a new program.
+ */
+long sys_execve(char __user *name, char __user * __user *argv,
+		char __user * __user *envp, struct pt_regs *regs)
+{
+	long error;
+	char *filename;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return error;
+	error = do_execve(filename, argv, envp, regs);
+
+#ifdef CONFIG_X86_32
+	if (error == 0) {
+		/* Make sure we don't return using sysenter.. */
+                set_thread_flag(TIF_IRET);
+        }
+#endif
+
+	putname(filename);
+	return error;
+}
 
 /*
  * Idle related variables and functions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 120b887..9c517b5 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -180,39 +180,6 @@
 	show_trace(NULL, regs, &regs->sp, regs->bp);
 }
 
-/*
- * This gets run with %bx containing the
- * function to call, and %dx containing
- * the "args".
- */
-extern void kernel_thread_helper(void);
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.bx = (unsigned long) fn;
-	regs.dx = (unsigned long) arg;
-
-	regs.ds = __USER_DS;
-	regs.es = __USER_DS;
-	regs.fs = __KERNEL_PERCPU;
-	regs.gs = __KERNEL_STACK_CANARY;
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void release_thread(struct task_struct *dead_task)
 {
 	BUG_ON(dead_task->mm);
@@ -424,46 +391,6 @@
 	return prev_p;
 }
 
-int sys_clone(struct pt_regs *regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-	int __user *parent_tidptr, *child_tidptr;
-
-	clone_flags = regs->bx;
-	newsp = regs->cx;
-	parent_tidptr = (int __user *)regs->dx;
-	child_tidptr = (int __user *)regs->di;
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
-}
-
-/*
- * sys_execve() executes a new program.
- */
-int sys_execve(struct pt_regs *regs)
-{
-	int error;
-	char *filename;
-
-	filename = getname((char __user *) regs->bx);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename,
-			(char __user * __user *) regs->cx,
-			(char __user * __user *) regs->dx,
-			regs);
-	if (error == 0) {
-		/* Make sure we don't return using sysenter.. */
-		set_thread_flag(TIF_IRET);
-	}
-	putname(filename);
-out:
-	return error;
-}
-
 #define top_esp                (THREAD_SIZE - sizeof(unsigned long))
 #define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
 
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e5ab0cd..52fbd0c 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -57,8 +57,6 @@
 DEFINE_PER_CPU(unsigned long, old_rsp);
 static DEFINE_PER_CPU(unsigned char, is_idle);
 
-unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
-
 static ATOMIC_NOTIFIER_HEAD(idle_notifier);
 
 void idle_notifier_register(struct notifier_block *n)
@@ -273,8 +271,9 @@
 	*childregs = *regs;
 
 	childregs->ax = 0;
-	childregs->sp = sp;
-	if (sp == ~0UL)
+	if (user_mode(regs))
+		childregs->sp = sp;
+	else
 		childregs->sp = (unsigned long)childregs;
 
 	p->thread.sp = (unsigned long) childregs;
@@ -508,25 +507,6 @@
 	return prev_p;
 }
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage
-long sys_execve(char __user *name, char __user * __user *argv,
-		char __user * __user *envp, struct pt_regs *regs)
-{
-	long error;
-	char *filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 void set_personality_64bit(void)
 {
 	/* inherit personality from parent */
@@ -541,15 +521,6 @@
 	current->personality &= ~READ_IMPLIES_EXEC;
 }
 
-asmlinkage long
-sys_clone(unsigned long clone_flags, unsigned long newsp,
-	  void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
-{
-	if (!newsp)
-		newsp = regs->sp;
-	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long stack;
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 7079dda..017d937 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -509,14 +509,14 @@
 {
 	if (kbuf) {
 		unsigned long *k = kbuf;
-		while (count > 0) {
+		while (count >= sizeof(*k)) {
 			*k++ = getreg(target, pos);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		unsigned long __user *u = ubuf;
-		while (count > 0) {
+		while (count >= sizeof(*u)) {
 			if (__put_user(getreg(target, pos), u++))
 				return -EFAULT;
 			count -= sizeof(*u);
@@ -535,14 +535,14 @@
 	int ret = 0;
 	if (kbuf) {
 		const unsigned long *k = kbuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*k) && !ret) {
 			ret = putreg(target, pos, *k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		const unsigned long  __user *u = ubuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*u) && !ret) {
 			unsigned long word;
 			ret = __get_user(word, u++);
 			if (ret)
@@ -1458,14 +1458,14 @@
 {
 	if (kbuf) {
 		compat_ulong_t *k = kbuf;
-		while (count > 0) {
+		while (count >= sizeof(*k)) {
 			getreg32(target, pos, k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		compat_ulong_t __user *u = ubuf;
-		while (count > 0) {
+		while (count >= sizeof(*u)) {
 			compat_ulong_t word;
 			getreg32(target, pos, &word);
 			if (__put_user(word, u++))
@@ -1486,14 +1486,14 @@
 	int ret = 0;
 	if (kbuf) {
 		const compat_ulong_t *k = kbuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*k) && !ret) {
 			ret = putreg32(target, pos, *k++);
 			count -= sizeof(*k);
 			pos += sizeof(*k);
 		}
 	} else {
 		const compat_ulong_t __user *u = ubuf;
-		while (count > 0 && !ret) {
+		while (count >= sizeof(*u) && !ret) {
 			compat_ulong_t word;
 			ret = __get_user(word, u++);
 			if (ret)
@@ -1676,21 +1676,33 @@
 #endif
 }
 
+static void fill_sigtrap_info(struct task_struct *tsk,
+				struct pt_regs *regs,
+				int error_code, int si_code,
+				struct siginfo *info)
+{
+	tsk->thread.trap_no = 1;
+	tsk->thread.error_code = error_code;
+
+	memset(info, 0, sizeof(*info));
+	info->si_signo = SIGTRAP;
+	info->si_code = si_code;
+	info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL;
+}
+
+void user_single_step_siginfo(struct task_struct *tsk,
+				struct pt_regs *regs,
+				struct siginfo *info)
+{
+	fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info);
+}
+
 void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
 					 int error_code, int si_code)
 {
 	struct siginfo info;
 
-	tsk->thread.trap_no = 1;
-	tsk->thread.error_code = error_code;
-
-	memset(&info, 0, sizeof(info));
-	info.si_signo = SIGTRAP;
-	info.si_code = si_code;
-
-	/* User-mode ip? */
-	info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL;
-
+	fill_sigtrap_info(tsk, regs, error_code, si_code, &info);
 	/* Send us the fake SIGTRAP */
 	force_sig_info(SIGTRAP, &info, tsk);
 }
@@ -1755,29 +1767,22 @@
 
 asmregparm void syscall_trace_leave(struct pt_regs *regs)
 {
+	bool step;
+
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_exit(regs, regs->ax);
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
-		tracehook_report_syscall_exit(regs, 0);
-
 	/*
 	 * If TIF_SYSCALL_EMU is set, we only get here because of
 	 * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
 	 * We already reported this syscall instruction in
-	 * syscall_trace_enter(), so don't do any more now.
+	 * syscall_trace_enter().
 	 */
-	if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
-		return;
-
-	/*
-	 * If we are single-stepping, synthesize a trap to follow the
-	 * system call instruction.
-	 */
-	if (test_thread_flag(TIF_SINGLESTEP) &&
-	    tracehook_consider_fatal_signal(current, SIGTRAP))
-		send_sigtrap(current, regs, 0, TRAP_BRKPT);
+	step = unlikely(test_thread_flag(TIF_SINGLESTEP)) &&
+			!test_thread_flag(TIF_SYSCALL_EMU);
+	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, step);
 }
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 74fe6d8..4fd173c 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -545,22 +545,12 @@
 }
 #endif /* CONFIG_X86_32 */
 
-#ifdef CONFIG_X86_32
-int sys_sigaltstack(struct pt_regs *regs)
-{
-	const stack_t __user *uss = (const stack_t __user *)regs->bx;
-	stack_t __user *uoss = (stack_t __user *)regs->cx;
-
-	return do_sigaltstack(uss, uoss, regs->sp);
-}
-#else /* !CONFIG_X86_32 */
-asmlinkage long
+long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 		struct pt_regs *regs)
 {
 	return do_sigaltstack(uss, uoss, regs->sp);
 }
-#endif /* CONFIG_X86_32 */
 
 /*
  * Do a signal return; undo the signal stack.
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 9c4e625..5ffb5622 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -197,9 +197,8 @@
 static int do_vm86_irq_handling(int subfunction, int irqnumber);
 static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
 
-int sys_vm86old(struct pt_regs *regs)
+int sys_vm86old(struct vm86_struct __user *v86, struct pt_regs *regs)
 {
-	struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs->bx;
 	struct kernel_vm86_struct info; /* declare this _on top_,
 					 * this avoids wasting of stack space.
 					 * This remains on the stack until we
@@ -227,7 +226,7 @@
 }
 
 
-int sys_vm86(struct pt_regs *regs)
+int sys_vm86(unsigned long cmd, unsigned long arg, struct pt_regs *regs)
 {
 	struct kernel_vm86_struct info; /* declare this _on top_,
 					 * this avoids wasting of stack space.
@@ -239,12 +238,12 @@
 	struct vm86plus_struct __user *v86;
 
 	tsk = current;
-	switch (regs->bx) {
+	switch (cmd) {
 	case VM86_REQUEST_IRQ:
 	case VM86_FREE_IRQ:
 	case VM86_GET_IRQ_BITS:
 	case VM86_GET_AND_RESET_IRQ:
-		ret = do_vm86_irq_handling(regs->bx, (int)regs->cx);
+		ret = do_vm86_irq_handling(cmd, (int)arg);
 		goto out;
 	case VM86_PLUS_INSTALL_CHECK:
 		/*
@@ -261,7 +260,7 @@
 	ret = -EPERM;
 	if (tsk->thread.saved_sp0)
 		goto out;
-	v86 = (struct vm86plus_struct __user *)regs->cx;
+	v86 = (struct vm86plus_struct __user *)arg;
 	tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
 				       offsetof(struct kernel_vm86_struct, regs32) -
 				       sizeof(info.regs));
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index f3f2104..f92a0da 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -319,9 +319,7 @@
 		__brk_limit = .;
 	}
 
-	.end : AT(ADDR(.end) - LOAD_OFFSET) {
-		_end = .;
-	}
+	_end = .;
 
         STABS_DEBUG
         DWARF_DEBUG
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index a102976..619f7f8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -17,8 +17,6 @@
 EXPORT_SYMBOL(mcount);
 #endif
 
-EXPORT_SYMBOL(kernel_thread);
-
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
@@ -56,4 +54,6 @@
 
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(init_level4_pgt);
-EXPORT_SYMBOL(load_gs_index);
+#ifndef CONFIG_PARAVIRT
+EXPORT_SYMBOL(native_load_gs_index);
+#endif
diff --git a/arch/x86/tools/gen-insn-attr-x86.awk b/arch/x86/tools/gen-insn-attr-x86.awk
index e34e92a..7a68506 100644
--- a/arch/x86/tools/gen-insn-attr-x86.awk
+++ b/arch/x86/tools/gen-insn-attr-x86.awk
@@ -226,12 +226,12 @@
 }
 
 # convert operands to flags.
-function convert_operands(opnd,       i,imm,mod)
+function convert_operands(count,opnd,       i,j,imm,mod)
 {
 	imm = null
 	mod = null
-	for (i in opnd) {
-		i  = opnd[i]
+	for (j = 1; j <= count; j++) {
+		i = opnd[j]
 		if (match(i, imm_expr) == 1) {
 			if (!imm_flag[i])
 				semantic_error("Unknown imm opnd: " i)
@@ -282,8 +282,8 @@
 		# parse one opcode
 		if (match($i, opnd_expr)) {
 			opnd = $i
-			split($(i++), opnds, ",")
-			flags = convert_operands(opnds)
+			count = split($(i++), opnds, ",")
+			flags = convert_operands(count, opnds)
 		}
 		if (match($i, ext_expr))
 			ext = $(i++)
diff --git a/arch/xtensa/include/asm/asm-offsets.h b/arch/xtensa/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/xtensa/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/xtensa/include/asm/elf.h b/arch/xtensa/include/asm/elf.h
index c3f53e7..5eb6d69 100644
--- a/arch/xtensa/include/asm/elf.h
+++ b/arch/xtensa/include/asm/elf.h
@@ -123,7 +123,6 @@
 #define ELF_CLASS	ELFCLASS32
 #define ELF_ARCH	EM_XTENSA
 
-#define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /*
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h
index 4352dbe..efcf33b 100644
--- a/arch/xtensa/include/asm/syscall.h
+++ b/arch/xtensa/include/asm/syscall.h
@@ -12,7 +12,6 @@
 struct sigaction;
 asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
-asmlinkage long xtensa_pipe(int __user *);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h
index fbf318b..528042c 100644
--- a/arch/xtensa/include/asm/unistd.h
+++ b/arch/xtensa/include/asm/unistd.h
@@ -94,7 +94,7 @@
 #define __NR_mknod 				 36
 __SYSCALL( 36, sys_mknod, 3)
 #define __NR_pipe 				 37
-__SYSCALL( 37, xtensa_pipe, 1)
+__SYSCALL( 37, sys_pipe, 1)
 #define __NR_unlink 				 38
 __SYSCALL( 38, sys_unlink, 1)
 #define __NR_rmdir 				 39
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
index 1e67bab..816e6d0 100644
--- a/arch/xtensa/kernel/syscall.c
+++ b/arch/xtensa/kernel/syscall.c
@@ -39,24 +39,6 @@
 #include <asm/unistd.h>
 };
 
-/*
- * xtensa_pipe() is the normal C calling standard for creating a pipe. It's not
- * the way unix traditional does this, though.
- */
-
-asmlinkage long xtensa_pipe(int __user *userfds)
-{
-	int fd[2];
-	int error;
-
-	error = do_pipe_flags(fd, 0);
-	if (!error) {
-		if (copy_to_user(userfds, fd, 2 * sizeof(int)))
-			error = -EFAULT;
-	}
-	return error;
-}
-
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
 {
 	unsigned long ret;
diff --git a/block/blk-settings.c b/block/blk-settings.c
index dd1f1e0..6ae118d 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -554,11 +554,18 @@
 		ret = -1;
 	}
 
+	/*
+	 * Temporarily disable discard granularity. It's currently buggy
+	 * since we default to 0 for discard_granularity, hence this
+	 * "failure" will always trigger for non-zero offsets.
+	 */
+#if 0
 	if (offset &&
 	    (offset & (b->discard_granularity - 1)) != b->discard_alignment) {
 		t->discard_misaligned = 1;
 		ret = -1;
 	}
+#endif
 
 	/* If top has no alignment offset, inherit from bottom */
 	if (!t->alignment_offset)
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index d672cfe..cb423f5 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/autoconf.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 0d2cdb8..97991ac 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -100,7 +100,8 @@
 	struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits);
 	cpumask_var_t tmp;
 	int cpu;
-	unsigned long min_weight = -1, preferred_cpu;
+	unsigned long min_weight = -1;
+	unsigned long uninitialized_var(preferred_cpu);
 
 	if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
 		return;
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index ab83919..61edb15 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -296,6 +296,11 @@
 			acpi_status validate_status,
 			union acpi_operand_object **return_object_ptr);
 
+void
+acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
+			     u8 package_type,
+			     union acpi_operand_object *obj_desc);
+
 /*
  * nssearch - Namespace searching and entry
  */
@@ -354,9 +359,7 @@
 			 const char *internal_name,
 			 u32 * converted_name_length, char **converted_name);
 
-struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle);
-
-acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node);
+struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle);
 
 void acpi_ns_terminate(void);
 
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index b39d682..64062b1 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -180,7 +180,11 @@
 	u8 sync_level;
 	union acpi_operand_object *mutex;
 	u8 *aml_start;
-	ACPI_INTERNAL_METHOD implementation;
+	union {
+		ACPI_INTERNAL_METHOD implementation;
+		union acpi_operand_object *handler;
+	} extra;
+
 	u32 aml_length;
 	u8 thread_count;
 	acpi_owner_id owner_id;
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 567a489..e786f9f 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -414,7 +414,7 @@
 	/* Invoke an internal method if necessary */
 
 	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-		status = obj_desc->method.implementation(next_walk_state);
+		status = obj_desc->method.extra.implementation(next_walk_state);
 		if (status == AE_OK) {
 			status = AE_CTRL_TERMINATE;
 		}
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 10fc785..b40513d 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -212,18 +212,19 @@
 		case ACPI_TYPE_BUFFER:
 
 			/*
-			 * These types we will allow, but we will change the type. This
-			 * enables some existing code of the form:
+			 * These types we will allow, but we will change the type.
+			 * This enables some existing code of the form:
 			 *
 			 *  Name (DEB, 0)
 			 *  Scope (DEB) { ... }
 			 *
-			 * Note: silently change the type here. On the second pass, we will report
-			 * a warning
+			 * Note: silently change the type here. On the second pass,
+			 * we will report a warning
 			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					  "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
-					  path,
+					  "Type override - [%4.4s] had invalid type (%s) "
+					  "for Scope operator, changed to type ANY\n",
+					  acpi_ut_get_node_name(node),
 					  acpi_ut_get_type_name(node->type)));
 
 			node->type = ACPI_TYPE_ANY;
@@ -235,8 +236,10 @@
 			/* All other types are an error */
 
 			ACPI_ERROR((AE_INFO,
-				    "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)",
-				    acpi_ut_get_type_name(node->type), path));
+				    "Invalid type (%s) for target of "
+				    "Scope operator [%4.4s] (Cannot override)",
+				    acpi_ut_get_type_name(node->type),
+				    acpi_ut_get_node_name(node)));
 
 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 		}
@@ -697,15 +700,16 @@
 		case ACPI_TYPE_BUFFER:
 
 			/*
-			 * These types we will allow, but we will change the type. This
-			 * enables some existing code of the form:
+			 * These types we will allow, but we will change the type.
+			 * This enables some existing code of the form:
 			 *
 			 *  Name (DEB, 0)
 			 *  Scope (DEB) { ... }
 			 */
 			ACPI_WARNING((AE_INFO,
-				      "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)",
-				      buffer_ptr,
+				      "Type override - [%4.4s] had invalid type (%s) "
+				      "for Scope operator, changed to type ANY\n",
+				      acpi_ut_get_node_name(node),
 				      acpi_ut_get_type_name(node->type)));
 
 			node->type = ACPI_TYPE_ANY;
@@ -717,9 +721,10 @@
 			/* All other types are an error */
 
 			ACPI_ERROR((AE_INFO,
-				    "Invalid type (%s) for target of Scope operator [%4.4s]",
+				    "Invalid type (%s) for target of "
+				    "Scope operator [%4.4s] (Cannot override)",
 				    acpi_ut_get_type_name(node->type),
-				    buffer_ptr));
+				    acpi_ut_get_node_name(node)));
 
 			return (AE_AML_OPERAND_TYPE);
 		}
@@ -1047,9 +1052,22 @@
 			}
 
 			/*
-			 * If we are executing a method, initialize the region
+			 * The op_region is not fully parsed at this time. The only valid
+			 * argument is the space_id. (We must save the address of the
+			 * AML of the address and length operands)
+			 *
+			 * If we have a valid region, initialize it. The namespace is
+			 * unlocked at this point.
+			 *
+			 * Need to unlock interpreter if it is locked (if we are running
+			 * a control method), in order to allow _REG methods to be run
+			 * during acpi_ev_initialize_region.
 			 */
 			if (walk_state->method_node) {
+				/*
+				 * Executing a method: initialize the region and unlock
+				 * the interpreter
+				 */
 				status =
 				    acpi_ex_create_region(op->named.data,
 							  op->named.length,
@@ -1058,21 +1076,17 @@
 				if (ACPI_FAILURE(status)) {
 					return (status);
 				}
+
+				acpi_ex_exit_interpreter();
 			}
 
-			/*
-			 * The op_region is not fully parsed at this time. Only valid
-			 * argument is the space_id. (We must save the address of the
-			 * AML of the address and length operands)
-			 */
-
-			/*
-			 * If we have a valid region, initialize it
-			 * Namespace is NOT locked at this point.
-			 */
 			status =
 			    acpi_ev_initialize_region
 			    (acpi_ns_get_attached_object(node), FALSE);
+			if (walk_state->method_node) {
+				acpi_ex_enter_interpreter();
+			}
+
 			if (ACPI_FAILURE(status)) {
 				/*
 				 *  If AE_NOT_EXIST is returned, it is not fatal
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 0bc807c..5336d91 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -718,7 +718,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	if (!node) {
 		return (AE_BAD_PARAMETER);
 	}
@@ -1087,7 +1087,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	if (!node) {
 		return (AE_BAD_PARAMETER);
 	}
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index cf29c49..ff16805 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -575,6 +575,21 @@
 				handler_obj = obj_desc->thermal_zone.handler;
 				break;
 
+			case ACPI_TYPE_METHOD:
+				/*
+				 * If we are executing module level code, the original
+				 * Node's object was replaced by this Method object and we
+				 * saved the handler in the method object.
+				 *
+				 * See acpi_ns_exec_module_code
+				 */
+				if (obj_desc->method.
+				    flags & AOPOBJ_MODULE_LEVEL) {
+					handler_obj =
+					    obj_desc->method.extra.handler;
+				}
+				break;
+
 			default:
 				/* Ignore other objects */
 				break;
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 10b8543..2fe0809 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -259,7 +259,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(device);
+	node = acpi_ns_validate_handle(device);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -425,7 +425,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(device);
+	node = acpi_ns_validate_handle(device);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 4721f58..eed7a38 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -610,7 +610,7 @@
 		return (status);
 	}
 
-	node = acpi_ns_map_handle_to_node(gpe_device);
+	node = acpi_ns_validate_handle(gpe_device);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -698,7 +698,7 @@
 		return (status);
 	}
 
-	node = acpi_ns_map_handle_to_node(gpe_device);
+	node = acpi_ns_validate_handle(gpe_device);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 7c3d2d3..c98aa7c 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -89,7 +89,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(device);
+	node = acpi_ns_validate_handle(device);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -155,7 +155,7 @@
 
 	/* Convert and validate the device handle */
 
-	node = acpi_ns_map_handle_to_node(device);
+	node = acpi_ns_validate_handle(device);
 	if (!node ||
 	    ((node->type != ACPI_TYPE_DEVICE) &&
 	     (node->type != ACPI_TYPE_PROCESSOR) &&
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index 2f01142..3c456bd 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -375,6 +375,15 @@
 		return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
 	}
 
+	/* Must have a valid thread ID */
+
+	if (!walk_state->thread) {
+		ACPI_ERROR((AE_INFO,
+			    "Cannot release Mutex [%4.4s], null thread info",
+			    acpi_ut_get_node_name(obj_desc->mutex.node)));
+		return_ACPI_STATUS(AE_AML_INTERNAL);
+	}
+
 	/*
 	 * The Mutex is owned, but this thread must be the owner.
 	 * Special case for Global Lock, any thread can release
@@ -392,15 +401,6 @@
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
-	/* Must have a valid thread ID */
-
-	if (!walk_state->thread) {
-		ACPI_ERROR((AE_INFO,
-			    "Cannot release Mutex [%4.4s], null thread info",
-			    acpi_ut_get_node_name(obj_desc->mutex.node)));
-		return_ACPI_STATUS(AE_AML_INTERNAL);
-	}
-
 	/*
 	 * The sync level of the mutex must be equal to the current sync level. In
 	 * other words, the current level means that at least one mutex at that
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 9c3cdbe..d622ba7 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -165,7 +165,7 @@
 
 				obj_desc->method.method_flags =
 				    AML_METHOD_INTERNAL_ONLY;
-				obj_desc->method.implementation =
+				obj_desc->method.extra.implementation =
 				    acpi_ut_osi_implementation;
 #endif
 				break;
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 2deb986..e37836e 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -180,7 +180,7 @@
 		return (AE_OK);
 	}
 
-	this_node = acpi_ns_map_handle_to_node(obj_handle);
+	this_node = acpi_ns_validate_handle(obj_handle);
 	if (!this_node) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n",
 				  obj_handle));
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index f771e97..af9fe91 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -381,6 +381,18 @@
 				    method_obj->method.next_object);
 	type = acpi_ns_get_type(parent_node);
 
+	/*
+	 * Get the region handler and save it in the method object. We may need
+	 * this if an operation region declaration causes a _REG method to be run.
+	 *
+	 * We can't do this in acpi_ps_link_module_code because
+	 * acpi_gbl_root_node->Object is NULL at PASS1.
+	 */
+	if ((type == ACPI_TYPE_DEVICE) && parent_node->object) {
+		method_obj->method.extra.handler =
+		    parent_node->object->device.handler;
+	}
+
 	/* Must clear next_object (acpi_ns_attach_object needs the field) */
 
 	method_obj->method.next_object = NULL;
@@ -415,6 +427,12 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
 			  method_obj->method.aml_start));
 
+	/* Delete a possible implicit return value (in slack mode) */
+
+	if (info->return_object) {
+		acpi_ut_remove_reference(info->return_object);
+	}
+
 	/* Detach the temporary method object */
 
 	acpi_ns_detach_object(parent_node);
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index af8e6bc..8f9a487 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -232,7 +232,7 @@
 
 	ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
 
-	node = acpi_ns_map_handle_to_node(target_handle);
+	node = acpi_ns_validate_handle(target_handle);
 	if (!node) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index b05f429..d34fa59 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -216,29 +216,38 @@
 	data->pathname = pathname;
 
 	/*
-	 * Check that the type of the return object is what is expected for
-	 * this predefined name
+	 * Check that the type of the main return object is what is expected
+	 * for this predefined name
 	 */
 	status = acpi_ns_check_object_type(data, return_object_ptr,
 					   predefined->info.expected_btypes,
 					   ACPI_NOT_PACKAGE_ELEMENT);
 	if (ACPI_FAILURE(status)) {
-		goto check_validation_status;
-	}
-
-	/* For returned Package objects, check the type of all sub-objects */
-
-	if (return_object->common.type == ACPI_TYPE_PACKAGE) {
-		status = acpi_ns_check_package(data, return_object_ptr);
+		goto exit;
 	}
 
 	/*
-	 * Perform additional, more complicated repairs on a per-name
-	 * basis.
+	 * For returned Package objects, check the type of all sub-objects.
+	 * Note: Package may have been newly created by call above.
+	 */
+	if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) {
+		status = acpi_ns_check_package(data, return_object_ptr);
+		if (ACPI_FAILURE(status)) {
+			goto exit;
+		}
+	}
+
+	/*
+	 * The return object was OK, or it was successfully repaired above.
+	 * Now make some additional checks such as verifying that package
+	 * objects are sorted correctly (if required) or buffer objects have
+	 * the correct data width (bytes vs. dwords). These repairs are
+	 * performed on a per-name basis, i.e., the code is specific to
+	 * particular predefined names.
 	 */
 	status = acpi_ns_complex_repairs(data, node, status, return_object_ptr);
 
-check_validation_status:
+exit:
 	/*
 	 * If the object validation failed or if we successfully repaired one
 	 * or more objects, mark the parent node to suppress further warning
@@ -427,6 +436,13 @@
 			  data->pathname, package->ret_info.type,
 			  return_object->package.count));
 
+	/*
+	 * For variable-length Packages, we can safely remove all embedded
+	 * and trailing NULL package elements
+	 */
+	acpi_ns_remove_null_elements(data, package->ret_info.type,
+				     return_object);
+
 	/* Extract package count and elements array */
 
 	elements = return_object->package.elements;
@@ -461,11 +477,11 @@
 		if (count < expected_count) {
 			goto package_too_small;
 		} else if (count > expected_count) {
-			ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
-					      data->node_flags,
-					      "Return Package is larger than needed - "
-					      "found %u, expected %u", count,
-					      expected_count));
+			ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+					  "%s: Return Package is larger than needed - "
+					  "found %u, expected %u\n",
+					  data->pathname, count,
+					  expected_count));
 		}
 
 		/* Validate all elements of the returned package */
@@ -680,53 +696,18 @@
 	union acpi_operand_object *sub_package;
 	union acpi_operand_object **sub_elements;
 	acpi_status status;
-	u8 non_trailing_null = FALSE;
 	u32 expected_count;
 	u32 i;
 	u32 j;
 
-	/* Validate each sub-Package in the parent Package */
-
+	/*
+	 * Validate each sub-Package in the parent Package
+	 *
+	 * NOTE: assumes list of sub-packages contains no NULL elements.
+	 * Any NULL elements should have been removed by earlier call
+	 * to acpi_ns_remove_null_elements.
+	 */
 	for (i = 0; i < count; i++) {
-		/*
-		 * Handling for NULL package elements. For now, we will simply allow
-		 * a parent package with trailing NULL elements. This can happen if
-		 * the package was defined to be longer than the initializer list.
-		 * This is legal as per the ACPI specification. It is often used
-		 * to allow for dynamic initialization of a Package.
-		 *
-		 * A future enhancement may be to simply truncate the package to
-		 * remove the trailing NULL elements.
-		 */
-		if (!(*elements)) {
-			if (!non_trailing_null) {
-
-				/* Ensure the remaining elements are all NULL */
-
-				for (j = 1; j < (count - i + 1); j++) {
-					if (elements[j]) {
-						non_trailing_null = TRUE;
-					}
-				}
-
-				if (!non_trailing_null) {
-
-					/* Ignore the trailing NULL elements */
-
-					return (AE_OK);
-				}
-			}
-
-			/* There are trailing non-null elements, issue warning */
-
-			ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
-					      data->node_flags,
-					      "Found NULL element at package index %u",
-					      i));
-			elements++;
-			continue;
-		}
-
 		sub_package = *elements;
 		sub_elements = sub_package->package.elements;
 
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index d563f1a..4fd1bdb 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -45,13 +45,52 @@
 #include "accommon.h"
 #include "acnamesp.h"
 #include "acinterp.h"
-#include "acpredef.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsrepair")
 
 /*******************************************************************************
  *
+ * This module attempts to repair or convert objects returned by the
+ * predefined methods to an object type that is expected, as per the ACPI
+ * specification. The need for this code is dictated by the many machines that
+ * return incorrect types for the standard predefined methods. Performing these
+ * conversions here, in one place, eliminates the need for individual ACPI
+ * device drivers to do the same. Note: Most of these conversions are different
+ * than the internal object conversion routines used for implicit object
+ * conversion.
+ *
+ * The following conversions can be performed as necessary:
+ *
+ * Integer -> String
+ * Integer -> Buffer
+ * String  -> Integer
+ * String  -> Buffer
+ * Buffer  -> Integer
+ * Buffer  -> String
+ * Buffer  -> Package of Integers
+ * Package -> Package of one Package
+ *
+ ******************************************************************************/
+/* Local prototypes */
+static acpi_status
+acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object);
+
+static acpi_status
+acpi_ns_convert_to_string(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object);
+
+static acpi_status
+acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object);
+
+static acpi_status
+acpi_ns_convert_to_package(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object);
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_repair_object
  *
  * PARAMETERS:  Data                - Pointer to validation data structure
@@ -68,6 +107,7 @@
  *              not expected.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_ns_repair_object(struct acpi_predefined_data *data,
 		      u32 expected_btypes,
@@ -76,98 +116,46 @@
 {
 	union acpi_operand_object *return_object = *return_object_ptr;
 	union acpi_operand_object *new_object;
-	acpi_size length;
 	acpi_status status;
 
+	ACPI_FUNCTION_NAME(ns_repair_object);
+
 	/*
 	 * At this point, we know that the type of the returned object was not
 	 * one of the expected types for this predefined name. Attempt to
-	 * repair the object. Only a limited number of repairs are possible.
+	 * repair the object by converting it to one of the expected object
+	 * types for this predefined name.
 	 */
-	switch (return_object->common.type) {
-	case ACPI_TYPE_BUFFER:
-
-		/* Does the method/object legally return a string? */
-
-		if (!(expected_btypes & ACPI_RTYPE_STRING)) {
-			return (AE_AML_OPERAND_TYPE);
+	if (expected_btypes & ACPI_RTYPE_INTEGER) {
+		status = acpi_ns_convert_to_integer(return_object, &new_object);
+		if (ACPI_SUCCESS(status)) {
+			goto object_repaired;
 		}
-
-		/*
-		 * Have a Buffer, expected a String, convert. Use a to_string
-		 * conversion, no transform performed on the buffer data. The best
-		 * example of this is the _BIF method, where the string data from
-		 * the battery is often (incorrectly) returned as buffer object(s).
-		 */
-		length = 0;
-		while ((length < return_object->buffer.length) &&
-		       (return_object->buffer.pointer[length])) {
-			length++;
-		}
-
-		/* Allocate a new string object */
-
-		new_object = acpi_ut_create_string_object(length);
-		if (!new_object) {
-			return (AE_NO_MEMORY);
-		}
-
-		/*
-		 * Copy the raw buffer data with no transform. String is already NULL
-		 * terminated at Length+1.
-		 */
-		ACPI_MEMCPY(new_object->string.pointer,
-			    return_object->buffer.pointer, length);
-		break;
-
-	case ACPI_TYPE_INTEGER:
-
-		/* 1) Does the method/object legally return a buffer? */
-
-		if (expected_btypes & ACPI_RTYPE_BUFFER) {
-			/*
-			 * Convert the Integer to a packed-byte buffer. _MAT needs
-			 * this sometimes, if a read has been performed on a Field
-			 * object that is less than or equal to the global integer
-			 * size (32 or 64 bits).
-			 */
-			status =
-			    acpi_ex_convert_to_buffer(return_object,
-						      &new_object);
-			if (ACPI_FAILURE(status)) {
-				return (status);
-			}
-		}
-
-		/* 2) Does the method/object legally return a string? */
-
-		else if (expected_btypes & ACPI_RTYPE_STRING) {
-			/*
-			 * The only supported Integer-to-String conversion is to convert
-			 * an integer of value 0 to a NULL string. The last element of
-			 * _BIF and _BIX packages occasionally need this fix.
-			 */
-			if (return_object->integer.value != 0) {
-				return (AE_AML_OPERAND_TYPE);
-			}
-
-			/* Allocate a new NULL string object */
-
-			new_object = acpi_ut_create_string_object(0);
-			if (!new_object) {
-				return (AE_NO_MEMORY);
-			}
-		} else {
-			return (AE_AML_OPERAND_TYPE);
-		}
-		break;
-
-	default:
-
-		/* We cannot repair this object */
-
-		return (AE_AML_OPERAND_TYPE);
 	}
+	if (expected_btypes & ACPI_RTYPE_STRING) {
+		status = acpi_ns_convert_to_string(return_object, &new_object);
+		if (ACPI_SUCCESS(status)) {
+			goto object_repaired;
+		}
+	}
+	if (expected_btypes & ACPI_RTYPE_BUFFER) {
+		status = acpi_ns_convert_to_buffer(return_object, &new_object);
+		if (ACPI_SUCCESS(status)) {
+			goto object_repaired;
+		}
+	}
+	if (expected_btypes & ACPI_RTYPE_PACKAGE) {
+		status = acpi_ns_convert_to_package(return_object, &new_object);
+		if (ACPI_SUCCESS(status)) {
+			goto object_repaired;
+		}
+	}
+
+	/* We cannot repair this object */
+
+	return (AE_AML_OPERAND_TYPE);
+
+      object_repaired:
 
 	/* Object was successfully repaired */
 
@@ -185,19 +173,18 @@
 			return_object->common.reference_count--;
 		}
 
-		ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
-				      "Converted %s to expected %s at index %u",
-				      acpi_ut_get_object_type_name
-				      (return_object),
-				      acpi_ut_get_object_type_name(new_object),
-				      package_index));
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s: Converted %s to expected %s at index %u\n",
+				  data->pathname,
+				  acpi_ut_get_object_type_name(return_object),
+				  acpi_ut_get_object_type_name(new_object),
+				  package_index));
 	} else {
-		ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
-				      "Converted %s to expected %s",
-				      acpi_ut_get_object_type_name
-				      (return_object),
-				      acpi_ut_get_object_type_name
-				      (new_object)));
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s: Converted %s to expected %s\n",
+				  data->pathname,
+				  acpi_ut_get_object_type_name(return_object),
+				  acpi_ut_get_object_type_name(new_object)));
 	}
 
 	/* Delete old object, install the new return object */
@@ -210,6 +197,315 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ns_convert_to_integer
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_status status;
+	u64 value = 0;
+	u32 i;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_STRING:
+
+		/* String-to-Integer conversion */
+
+		status = acpi_ut_strtoul64(original_object->string.pointer,
+					   ACPI_ANY_BASE, &value);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+		break;
+
+	case ACPI_TYPE_BUFFER:
+
+		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
+
+		if (original_object->buffer.length > 8) {
+			return (AE_AML_OPERAND_TYPE);
+		}
+
+		/* Extract each buffer byte to create the integer */
+
+		for (i = 0; i < original_object->buffer.length; i++) {
+			value |=
+			    ((u64) original_object->buffer.
+			     pointer[i] << (i * 8));
+		}
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	new_object = acpi_ut_create_integer_object(value);
+	if (!new_object) {
+		return (AE_NO_MEMORY);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_string
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_convert_to_string(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_size length;
+	acpi_status status;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_INTEGER:
+		/*
+		 * Integer-to-String conversion. Commonly, convert
+		 * an integer of value 0 to a NULL string. The last element of
+		 * _BIF and _BIX packages occasionally need this fix.
+		 */
+		if (original_object->integer.value == 0) {
+
+			/* Allocate a new NULL string object */
+
+			new_object = acpi_ut_create_string_object(0);
+			if (!new_object) {
+				return (AE_NO_MEMORY);
+			}
+		} else {
+			status =
+			    acpi_ex_convert_to_string(original_object,
+						      &new_object,
+						      ACPI_IMPLICIT_CONVERT_HEX);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+		}
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		/*
+		 * Buffer-to-String conversion. Use a to_string
+		 * conversion, no transform performed on the buffer data. The best
+		 * example of this is the _BIF method, where the string data from
+		 * the battery is often (incorrectly) returned as buffer object(s).
+		 */
+		length = 0;
+		while ((length < original_object->buffer.length) &&
+		       (original_object->buffer.pointer[length])) {
+			length++;
+		}
+
+		/* Allocate a new string object */
+
+		new_object = acpi_ut_create_string_object(length);
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/*
+		 * Copy the raw buffer data with no transform. String is already NULL
+		 * terminated at Length+1.
+		 */
+		ACPI_MEMCPY(new_object->string.pointer,
+			    original_object->buffer.pointer, length);
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_buffer
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
+			  union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	acpi_status status;
+	union acpi_operand_object **elements;
+	u32 *dword_buffer;
+	u32 count;
+	u32 i;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_INTEGER:
+		/*
+		 * Integer-to-Buffer conversion.
+		 * Convert the Integer to a packed-byte buffer. _MAT and other
+		 * objects need this sometimes, if a read has been performed on a
+		 * Field object that is less than or equal to the global integer
+		 * size (32 or 64 bits).
+		 */
+		status =
+		    acpi_ex_convert_to_buffer(original_object, &new_object);
+		if (ACPI_FAILURE(status)) {
+			return (status);
+		}
+		break;
+
+	case ACPI_TYPE_STRING:
+
+		/* String-to-Buffer conversion. Simple data copy */
+
+		new_object =
+		    acpi_ut_create_buffer_object(original_object->string.
+						 length);
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		ACPI_MEMCPY(new_object->buffer.pointer,
+			    original_object->string.pointer,
+			    original_object->string.length);
+		break;
+
+	case ACPI_TYPE_PACKAGE:
+		/*
+		 * This case is often seen for predefined names that must return a
+		 * Buffer object with multiple DWORD integers within. For example,
+		 * _FDE and _GTM. The Package can be converted to a Buffer.
+		 */
+
+		/* All elements of the Package must be integers */
+
+		elements = original_object->package.elements;
+		count = original_object->package.count;
+
+		for (i = 0; i < count; i++) {
+			if ((!*elements) ||
+			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
+				return (AE_AML_OPERAND_TYPE);
+			}
+			elements++;
+		}
+
+		/* Create the new buffer object to replace the Package */
+
+		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Copy the package elements (integers) to the buffer as DWORDs */
+
+		elements = original_object->package.elements;
+		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
+
+		for (i = 0; i < count; i++) {
+			*dword_buffer = (u32) (*elements)->integer.value;
+			dword_buffer++;
+			elements++;
+		}
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_convert_to_package
+ *
+ * PARAMETERS:  original_object     - Object to be converted
+ *              return_object       - Where the new converted object is returned
+ *
+ * RETURN:      Status. AE_OK if conversion was successful.
+ *
+ * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
+ *              the buffer is converted to a single integer package element.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_convert_to_package(union acpi_operand_object *original_object,
+			   union acpi_operand_object **return_object)
+{
+	union acpi_operand_object *new_object;
+	union acpi_operand_object **elements;
+	u32 length;
+	u8 *buffer;
+
+	switch (original_object->common.type) {
+	case ACPI_TYPE_BUFFER:
+
+		/* Buffer-to-Package conversion */
+
+		length = original_object->buffer.length;
+		new_object = acpi_ut_create_package_object(length);
+		if (!new_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Convert each buffer byte to an integer package element */
+
+		elements = new_object->package.elements;
+		buffer = original_object->buffer.pointer;
+
+		while (length--) {
+			*elements =
+			    acpi_ut_create_integer_object((u64) *buffer);
+			if (!*elements) {
+				acpi_ut_remove_reference(new_object);
+				return (AE_NO_MEMORY);
+			}
+			elements++;
+			buffer++;
+		}
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	*return_object = new_object;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_repair_package_list
  *
  * PARAMETERS:  Data                - Pointer to validation data structure
@@ -238,6 +534,8 @@
 {
 	union acpi_operand_object *pkg_obj_desc;
 
+	ACPI_FUNCTION_NAME(ns_repair_package_list);
+
 	/*
 	 * Create the new outer package and populate it. The new package will
 	 * have a single element, the lone subpackage.
@@ -254,8 +552,9 @@
 	*obj_desc_ptr = pkg_obj_desc;
 	data->flags |= ACPI_OBJECT_REPAIRED;
 
-	ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
-			      "Repaired Incorrectly formed Package"));
+	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+			  "%s: Repaired incorrectly formed Package\n",
+			  data->pathname));
 
 	return (AE_OK);
 }
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index d07b686..f13691c 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -45,6 +45,7 @@
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
+#include "acpredef.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsrepair2")
@@ -74,6 +75,10 @@
 		   union acpi_operand_object **return_object_ptr);
 
 static acpi_status
+acpi_ns_repair_FDE(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr);
+
+static acpi_status
 acpi_ns_repair_PSS(struct acpi_predefined_data *data,
 		   union acpi_operand_object **return_object_ptr);
 
@@ -89,9 +94,6 @@
 			  u8 sort_direction, char *sort_key_name);
 
 static acpi_status
-acpi_ns_remove_null_elements(union acpi_operand_object *package);
-
-static acpi_status
 acpi_ns_sort_list(union acpi_operand_object **elements,
 		  u32 count, u32 index, u8 sort_direction);
 
@@ -104,17 +106,27 @@
  * This table contains the names of the predefined methods for which we can
  * perform more complex repairs.
  *
- * _ALR: Sort the list ascending by ambient_illuminance if necessary
- * _PSS: Sort the list descending by Power if necessary
- * _TSS: Sort the list descending by Power if necessary
+ * As necessary:
+ *
+ * _ALR: Sort the list ascending by ambient_illuminance
+ * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
+ * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
+ * _PSS: Sort the list descending by Power
+ * _TSS: Sort the list descending by Power
  */
 static const struct acpi_repair_info acpi_ns_repairable_names[] = {
 	{"_ALR", acpi_ns_repair_ALR},
+	{"_FDE", acpi_ns_repair_FDE},
+	{"_GTM", acpi_ns_repair_FDE},	/* _GTM has same repair as _FDE */
 	{"_PSS", acpi_ns_repair_PSS},
 	{"_TSS", acpi_ns_repair_TSS},
 	{{0, 0, 0, 0}, NULL}	/* Table terminator */
 };
 
+#define ACPI_FDE_FIELD_COUNT        5
+#define ACPI_FDE_BYTE_BUFFER_SIZE   5
+#define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (u32))
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_ns_complex_repairs
@@ -215,6 +227,94 @@
 
 /******************************************************************************
  *
+ * FUNCTION:    acpi_ns_repair_FDE
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
+ *              value is a Buffer of 5 DWORDs. This function repairs a common
+ *              problem where the return value is a Buffer of BYTEs, not
+ *              DWORDs.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_FDE(struct acpi_predefined_data *data,
+		   union acpi_operand_object **return_object_ptr)
+{
+	union acpi_operand_object *return_object = *return_object_ptr;
+	union acpi_operand_object *buffer_object;
+	u8 *byte_buffer;
+	u32 *dword_buffer;
+	u32 i;
+
+	ACPI_FUNCTION_NAME(ns_repair_FDE);
+
+	switch (return_object->common.type) {
+	case ACPI_TYPE_BUFFER:
+
+		/* This is the expected type. Length should be (at least) 5 DWORDs */
+
+		if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) {
+			return (AE_OK);
+		}
+
+		/* We can only repair if we have exactly 5 BYTEs */
+
+		if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
+			ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+					      data->node_flags,
+					      "Incorrect return buffer length %u, expected %u",
+					      return_object->buffer.length,
+					      ACPI_FDE_DWORD_BUFFER_SIZE));
+
+			return (AE_AML_OPERAND_TYPE);
+		}
+
+		/* Create the new (larger) buffer object */
+
+		buffer_object =
+		    acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE);
+		if (!buffer_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		/* Expand each byte to a DWORD */
+
+		byte_buffer = return_object->buffer.pointer;
+		dword_buffer =
+		    ACPI_CAST_PTR(u32, buffer_object->buffer.pointer);
+
+		for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
+			*dword_buffer = (u32) *byte_buffer;
+			dword_buffer++;
+			byte_buffer++;
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s Expanded Byte Buffer to expected DWord Buffer\n",
+				  data->pathname));
+		break;
+
+	default:
+		return (AE_AML_OPERAND_TYPE);
+	}
+
+	/* Delete the original return object, return the new buffer object */
+
+	acpi_ut_remove_reference(return_object);
+	*return_object_ptr = buffer_object;
+
+	data->flags |= ACPI_OBJECT_REPAIRED;
+	return (AE_OK);
+}
+
+/******************************************************************************
+ *
  * FUNCTION:    acpi_ns_repair_TSS
  *
  * PARAMETERS:  Data                - Pointer to validation data structure
@@ -345,6 +445,8 @@
 	u32 previous_value;
 	acpi_status status;
 
+	ACPI_FUNCTION_NAME(ns_check_sorted_list);
+
 	/* The top-level object must be a package */
 
 	if (return_object->common.type != ACPI_TYPE_PACKAGE) {
@@ -352,24 +454,10 @@
 	}
 
 	/*
-	 * Detect any NULL package elements and remove them from the
-	 * package.
-	 *
-	 * TBD: We may want to do this for all predefined names that
-	 * return a variable-length package of packages.
+	 * NOTE: assumes list of sub-packages contains no NULL elements.
+	 * Any NULL elements should have been removed by earlier call
+	 * to acpi_ns_remove_null_elements.
 	 */
-	status = acpi_ns_remove_null_elements(return_object);
-	if (status == AE_NULL_ENTRY) {
-		ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
-				      "NULL elements removed from package"));
-
-		/* Exit if package is now zero length */
-
-		if (!return_object->package.count) {
-			return (AE_NULL_ENTRY);
-		}
-	}
-
 	outer_elements = return_object->package.elements;
 	outer_element_count = return_object->package.count;
 	if (!outer_element_count) {
@@ -422,10 +510,9 @@
 
 			data->flags |= ACPI_OBJECT_REPAIRED;
 
-			ACPI_INFO_PREDEFINED((AE_INFO, data->pathname,
-					      data->node_flags,
-					      "Repaired unsorted list - now sorted by %s",
-					      sort_key_name));
+			ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+					  "%s: Repaired unsorted list - now sorted by %s\n",
+					  data->pathname, sort_key_name));
 			return (AE_OK);
 		}
 
@@ -440,36 +527,63 @@
  *
  * FUNCTION:    acpi_ns_remove_null_elements
  *
- * PARAMETERS:  obj_desc            - A Package object
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              package_type        - An acpi_return_package_types value
+ *              obj_desc            - A Package object
  *
- * RETURN:      Status. AE_NULL_ENTRY means that one or more elements were
- *              removed.
+ * RETURN:      None.
  *
- * DESCRIPTION: Remove all NULL package elements and update the package count.
+ * DESCRIPTION: Remove all NULL package elements from packages that contain
+ *              a variable number of sub-packages.
  *
  *****************************************************************************/
 
-static acpi_status
-acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
+void
+acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
+			     u8 package_type,
+			     union acpi_operand_object *obj_desc)
 {
 	union acpi_operand_object **source;
 	union acpi_operand_object **dest;
-	acpi_status status = AE_OK;
 	u32 count;
 	u32 new_count;
 	u32 i;
 
+	ACPI_FUNCTION_NAME(ns_remove_null_elements);
+
+	/*
+	 * PTYPE1 packages contain no subpackages.
+	 * PTYPE2 packages contain a variable number of sub-packages. We can
+	 * safely remove all NULL elements from the PTYPE2 packages.
+	 */
+	switch (package_type) {
+	case ACPI_PTYPE1_FIXED:
+	case ACPI_PTYPE1_VAR:
+	case ACPI_PTYPE1_OPTION:
+		return;
+
+	case ACPI_PTYPE2:
+	case ACPI_PTYPE2_COUNT:
+	case ACPI_PTYPE2_PKG_COUNT:
+	case ACPI_PTYPE2_FIXED:
+	case ACPI_PTYPE2_MIN:
+	case ACPI_PTYPE2_REV_FIXED:
+		break;
+
+	default:
+		return;
+	}
+
 	count = obj_desc->package.count;
 	new_count = count;
 
 	source = obj_desc->package.elements;
 	dest = source;
 
-	/* Examine all elements of the package object */
+	/* Examine all elements of the package object, remove nulls */
 
 	for (i = 0; i < count; i++) {
 		if (!*source) {
-			status = AE_NULL_ENTRY;
 			new_count--;
 		} else {
 			*dest = *source;
@@ -478,15 +592,18 @@
 		source++;
 	}
 
-	if (status == AE_NULL_ENTRY) {
+	/* Update parent package if any null elements were removed */
+
+	if (new_count < count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s: Found and removed %u NULL elements\n",
+				  data->pathname, (count - new_count)));
 
 		/* NULL terminate list and update the package count */
 
 		*dest = NULL;
 		obj_desc->package.count = new_count;
 	}
-
-	return (status);
 }
 
 /******************************************************************************
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index ea55ab4..47d91e6 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -671,24 +671,25 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_map_handle_to_node
+ * FUNCTION:    acpi_ns_validate_handle
  *
- * PARAMETERS:  Handle          - Handle to be converted to an Node
+ * PARAMETERS:  Handle          - Handle to be validated and typecast to a
+ *                                namespace node.
  *
- * RETURN:      A Name table entry pointer
+ * RETURN:      A pointer to a namespace node
  *
- * DESCRIPTION: Convert a namespace handle to a real Node
+ * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
+ *              cases for the root node.
  *
- * Note: Real integer handles would allow for more verification
+ * NOTE: Real integer handles would allow for more verification
  *       and keep all pointers within this subsystem - however this introduces
- *       more (and perhaps unnecessary) overhead.
- *
- * The current implemenation is basically a placeholder until such time comes
- * that it is needed.
+ *       more overhead and has not been necessary to this point. Drivers
+ *       holding handles are typically notified before a node becomes invalid
+ *       due to a table unload.
  *
  ******************************************************************************/
 
-struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
+struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
 {
 
 	ACPI_FUNCTION_ENTRY();
@@ -710,42 +711,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_convert_entry_to_handle
- *
- * PARAMETERS:  Node          - Node to be converted to a Handle
- *
- * RETURN:      A user handle
- *
- * DESCRIPTION: Convert a real Node to a namespace handle
- *
- ******************************************************************************/
-
-acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node)
-{
-
-	/*
-	 * Simple implementation for now;
-	 */
-	return ((acpi_handle) node);
-
-/* Example future implementation ---------------------
-
-	if (!Node)
-	{
-		return (NULL);
-	}
-
-	if (Node == acpi_gbl_root_node)
-	{
-		return (ACPI_ROOT_OBJECT);
-	}
-
-	return ((acpi_handle) Node);
-------------------------------------------------------*/
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ns_terminate
  *
  * PARAMETERS:  none
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index f2bd1da..f0c0892 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -190,7 +190,7 @@
 
 	/* Convert and validate the device handle */
 
-	info->prefix_node = acpi_ns_map_handle_to_node(handle);
+	info->prefix_node = acpi_ns_validate_handle(handle);
 	if (!info->prefix_node) {
 		status = AE_BAD_PARAMETER;
 		goto cleanup;
@@ -552,7 +552,7 @@
 		return (status);
 	}
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
 		return (status);
@@ -729,7 +729,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -775,7 +775,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -822,7 +822,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(obj_handle);
+	node = acpi_ns_validate_handle(obj_handle);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index ddc84af..e611dd9 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -93,7 +93,7 @@
 	/* Convert a parent handle to a prefix node */
 
 	if (parent) {
-		prefix_node = acpi_ns_map_handle_to_node(parent);
+		prefix_node = acpi_ns_validate_handle(parent);
 		if (!prefix_node) {
 			return (AE_BAD_PARAMETER);
 		}
@@ -114,7 +114,7 @@
 
 		if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) {
 			*ret_handle =
-			    acpi_ns_convert_entry_to_handle(acpi_gbl_root_node);
+			    ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
 			return (AE_OK);
 		}
 	} else if (!prefix_node) {
@@ -129,7 +129,7 @@
 	status =
 	    acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
 	if (ACPI_SUCCESS(status)) {
-		*ret_handle = acpi_ns_convert_entry_to_handle(node);
+		*ret_handle = ACPI_CAST_PTR(acpi_handle, node);
 	}
 
 	return (status);
@@ -186,7 +186,7 @@
 		return (status);
 	}
 
-	node = acpi_ns_map_handle_to_node(handle);
+	node = acpi_ns_validate_handle(handle);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -291,7 +291,7 @@
 		goto cleanup;
 	}
 
-	node = acpi_ns_map_handle_to_node(handle);
+	node = acpi_ns_validate_handle(handle);
 	if (!node) {
 		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		return (AE_BAD_PARAMETER);
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 4071bad..0cc6ba0 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -79,7 +79,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(handle);
+	node = acpi_ns_validate_handle(handle);
 	if (!node) {
 		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		return (AE_BAD_PARAMETER);
@@ -132,7 +132,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(handle);
+	node = acpi_ns_validate_handle(handle);
 	if (!node) {
 		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		return (AE_BAD_PARAMETER);
@@ -182,7 +182,7 @@
 
 	/* Convert and validate the handle */
 
-	node = acpi_ns_map_handle_to_node(handle);
+	node = acpi_ns_validate_handle(handle);
 	if (!node) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
@@ -191,7 +191,7 @@
 	/* Get the parent entry */
 
 	parent_node = acpi_ns_get_parent_node(node);
-	*ret_handle = acpi_ns_convert_entry_to_handle(parent_node);
+	*ret_handle = ACPI_CAST_PTR(acpi_handle, parent_node);
 
 	/* Return exception if parent is null */
 
@@ -251,7 +251,7 @@
 
 		/* Start search at the beginning of the specified scope */
 
-		parent_node = acpi_ns_map_handle_to_node(parent);
+		parent_node = acpi_ns_validate_handle(parent);
 		if (!parent_node) {
 			status = AE_BAD_PARAMETER;
 			goto unlock_and_exit;
@@ -260,7 +260,7 @@
 		/* Non-null handle, ignore the parent */
 		/* Convert and validate the handle */
 
-		child_node = acpi_ns_map_handle_to_node(child);
+		child_node = acpi_ns_validate_handle(child);
 		if (!child_node) {
 			status = AE_BAD_PARAMETER;
 			goto unlock_and_exit;
@@ -276,7 +276,7 @@
 	}
 
 	if (ret_handle) {
-		*ret_handle = acpi_ns_convert_entry_to_handle(node);
+		*ret_handle = ACPI_CAST_PTR(acpi_handle, node);
 	}
 
       unlock_and_exit:
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index 12934ad..d0c1b91 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -287,7 +287,8 @@
 	/* Invoke an internal method if necessary */
 
 	if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
-		status = info->obj_desc->method.implementation(walk_state);
+		status =
+		    info->obj_desc->method.extra.implementation(walk_state);
 		info->return_object = walk_state->return_desc;
 
 		/* Cleanup states */
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 395212b..f27feb4 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -104,7 +104,7 @@
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	node = acpi_ns_map_handle_to_node(device_handle);
+	node = acpi_ns_validate_handle(device_handle);
 	if (!node) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 0f0c64b..f857c5e 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -323,11 +323,11 @@
  * RETURN:      Status
  *
  * DESCRIPTION: This function is called to place a package object in a user
- *              buffer.  A package object by definition contains other objects.
+ *              buffer. A package object by definition contains other objects.
  *
  *              The buffer is assumed to have sufficient space for the object.
- *              The caller must have verified the buffer length needed using the
- *              acpi_ut_get_object_size function before calling this function.
+ *              The caller must have verified the buffer length needed using
+ *              the acpi_ut_get_object_size function before calling this function.
  *
  ******************************************************************************/
 
@@ -382,12 +382,12 @@
  * FUNCTION:    acpi_ut_copy_iobject_to_eobject
  *
  * PARAMETERS:  internal_object     - The internal object to be converted
- *              buffer_ptr          - Where the object is returned
+ *              ret_buffer          - Where the object is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to build an API object to be returned to
- *              the caller.
+ * DESCRIPTION: This function is called to build an API object to be returned
+ *              to the caller.
  *
  ******************************************************************************/
 
@@ -626,7 +626,7 @@
  * PARAMETERS:  external_object     - The external object to be converted
  *              internal_object     - Where the internal object is returned
  *
- * RETURN:      Status              - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: Converts an external object to an internal object.
  *
@@ -665,7 +665,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Simple copy of one internal object to another.  Reference count
+ * DESCRIPTION: Simple copy of one internal object to another. Reference count
  *              of the destination object is preserved.
  *
  ******************************************************************************/
@@ -897,10 +897,11 @@
  *
  * FUNCTION:    acpi_ut_copy_ipackage_to_ipackage
  *
- * PARAMETERS:  *source_obj     - Pointer to the source package object
- *              *dest_obj       - Where the internal object is returned
+ * PARAMETERS:  source_obj      - Pointer to the source package object
+ *              dest_obj        - Where the internal object is returned
+ *              walk_state      - Current Walk state descriptor
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to copy an internal package object
  *              into another internal package object.
@@ -953,9 +954,9 @@
  *
  * FUNCTION:    acpi_ut_copy_iobject_to_iobject
  *
- * PARAMETERS:  walk_state          - Current walk state
- *              source_desc         - The internal object to be copied
+ * PARAMETERS:  source_desc         - The internal object to be copied
  *              dest_desc           - Where the copied object is returned
+ *              walk_state          - Current walk state
  *
  * RETURN:      Status
  *
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 3f4602b..cada73f 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -831,7 +831,7 @@
 					dev_name(&device->dev), event,
 					acpi_battery_present(battery));
 #ifdef CONFIG_ACPI_SYSFS_POWER
-	/* acpi_batter_update could remove power_supply object */
+	/* acpi_battery_update could remove power_supply object */
 	if (battery->bat.dev)
 		kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
 #endif
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 7411915..65f7e33 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -344,6 +344,152 @@
 
 EXPORT_SYMBOL(acpi_bus_can_wakeup);
 
+static void acpi_print_osc_error(acpi_handle handle,
+	struct acpi_osc_context *context, char *error)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
+	int i;
+
+	if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
+		printk(KERN_DEBUG "%s\n", error);
+	else {
+		printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
+		kfree(buffer.pointer);
+	}
+	printk(KERN_DEBUG"_OSC request data:");
+	for (i = 0; i < context->cap.length; i += sizeof(u32))
+		printk("%x ", *((u32 *)(context->cap.pointer + i)));
+	printk("\n");
+}
+
+static u8 hex_val(unsigned char c)
+{
+	return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;
+}
+
+static acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
+{
+	int i;
+	static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
+		24, 26, 28, 30, 32, 34};
+
+	if (strlen(str) != 36)
+		return AE_BAD_PARAMETER;
+	for (i = 0; i < 36; i++) {
+		if (i == 8 || i == 13 || i == 18 || i == 23) {
+			if (str[i] != '-')
+				return AE_BAD_PARAMETER;
+		} else if (!isxdigit(str[i]))
+			return AE_BAD_PARAMETER;
+	}
+	for (i = 0; i < 16; i++) {
+		uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4;
+		uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]);
+	}
+	return AE_OK;
+}
+
+acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
+{
+	acpi_status status;
+	struct acpi_object_list input;
+	union acpi_object in_params[4];
+	union acpi_object *out_obj;
+	u8 uuid[16];
+	u32 errors;
+
+	if (!context)
+		return AE_ERROR;
+	if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
+		return AE_ERROR;
+	context->ret.length = ACPI_ALLOCATE_BUFFER;
+	context->ret.pointer = NULL;
+
+	/* Setting up input parameters */
+	input.count = 4;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= 16;
+	in_params[0].buffer.pointer	= uuid;
+	in_params[1].type 		= ACPI_TYPE_INTEGER;
+	in_params[1].integer.value 	= context->rev;
+	in_params[2].type 		= ACPI_TYPE_INTEGER;
+	in_params[2].integer.value	= context->cap.length/sizeof(u32);
+	in_params[3].type		= ACPI_TYPE_BUFFER;
+	in_params[3].buffer.length 	= context->cap.length;
+	in_params[3].buffer.pointer 	= context->cap.pointer;
+
+	status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	/* return buffer should have the same length as cap buffer */
+	if (context->ret.length != context->cap.length)
+		return AE_NULL_OBJECT;
+
+	out_obj = context->ret.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		acpi_print_osc_error(handle, context,
+			"_OSC evaluation returned wrong type");
+		status = AE_TYPE;
+		goto out_kfree;
+	}
+	/* Need to ignore the bit0 in result code */
+	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+	if (errors) {
+		if (errors & OSC_REQUEST_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC request failed");
+		if (errors & OSC_INVALID_UUID_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC invalid UUID");
+		if (errors & OSC_INVALID_REVISION_ERROR)
+			acpi_print_osc_error(handle, context,
+				"_OSC invalid revision");
+		if (errors & OSC_CAPABILITIES_MASK_ERROR) {
+			if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
+			    & OSC_QUERY_ENABLE)
+				goto out_success;
+			status = AE_SUPPORT;
+			goto out_kfree;
+		}
+		status = AE_ERROR;
+		goto out_kfree;
+	}
+out_success:
+	return AE_OK;
+
+out_kfree:
+	kfree(context->ret.pointer);
+	context->ret.pointer = NULL;
+	return status;
+}
+EXPORT_SYMBOL(acpi_run_osc);
+
+static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
+static void acpi_bus_osc_support(void)
+{
+	u32 capbuf[2];
+	struct acpi_osc_context context = {
+		.uuid_str = sb_uuid_str,
+		.rev = 1,
+		.cap.length = 8,
+		.cap.pointer = capbuf,
+	};
+	acpi_handle handle;
+
+	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
+	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
+#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR
+	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
+#endif
+	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
+		return;
+	if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
+		kfree(context.ret.pointer);
+	/* do we need to check the returned cap? Sounds no */
+}
+
 /* --------------------------------------------------------------------------
                                 Event Management
    -------------------------------------------------------------------------- */
@@ -734,6 +880,8 @@
 	status = acpi_ec_ecdt_probe();
 	/* Ignore result. Not having an ECDT is not fatal. */
 
+	acpi_bus_osc_support();
+
 	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 0c9c6a9..8a95e83 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -282,6 +282,13 @@
 	if (ret == NOTIFY_DONE)
 		ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
 						   device);
+	if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
+		/*
+		 * It is also regarded as success if the notifier_chain
+		 * returns NOTIFY_OK or NOTIFY_DONE.
+		 */
+		ret = 0;
+	}
 	return ret;
 }
 
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 8a690c3..cc421b7 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
+#include <linux/debugfs.h>
 #include <asm/uaccess.h>
 #include <acpi/acpi_drivers.h>
 
@@ -196,6 +197,80 @@
 		  NULL, 0644);
 
 /* --------------------------------------------------------------------------
+				DebugFS Interface
+   -------------------------------------------------------------------------- */
+
+static ssize_t cm_write(struct file *file, const char __user *user_buf,
+			size_t count, loff_t *ppos)
+{
+	static char *buf;
+	static int uncopied_bytes;
+	struct acpi_table_header table;
+	acpi_status status;
+
+	if (!(*ppos)) {
+		/* parse the table header to get the table length */
+		if (count <= sizeof(struct acpi_table_header))
+			return -EINVAL;
+		if (copy_from_user(&table, user_buf,
+			sizeof(struct acpi_table_header)))
+			return -EFAULT;
+		uncopied_bytes = table.length;
+		buf = kzalloc(uncopied_bytes, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+	}
+
+	if (uncopied_bytes < count) {
+		kfree(buf);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(buf + (*ppos), user_buf, count)) {
+		kfree(buf);
+		return -EFAULT;
+	}
+
+	uncopied_bytes -= count;
+	*ppos += count;
+
+	if (!uncopied_bytes) {
+		status = acpi_install_method(buf);
+		kfree(buf);
+		if (ACPI_FAILURE(status))
+			return -EINVAL;
+		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+	}
+
+	return count;
+}
+
+static const struct file_operations cm_fops = {
+	.write = cm_write,
+};
+
+static int acpi_debugfs_init(void)
+{
+	struct dentry *acpi_dir, *cm_dentry;
+
+	acpi_dir = debugfs_create_dir("acpi", NULL);
+	if (!acpi_dir)
+		goto err;
+
+	cm_dentry = debugfs_create_file("custom_method", S_IWUGO,
+					acpi_dir, NULL, &cm_fops);
+	if (!cm_dentry)
+		goto err;
+
+	return 0;
+
+err:
+	if (acpi_dir)
+		debugfs_remove(acpi_dir);
+	return -EINVAL;
+}
+
+/* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
 #ifdef CONFIG_ACPI_PROCFS
@@ -286,7 +361,7 @@
 };
 #endif
 
-int __init acpi_debug_init(void)
+int __init acpi_procfs_init(void)
 {
 #ifdef CONFIG_ACPI_PROCFS
 	struct proc_dir_entry *entry;
@@ -321,3 +396,10 @@
 	return 0;
 #endif
 }
+
+int __init acpi_debug_init(void)
+{
+	acpi_debugfs_init();
+	acpi_procfs_init();
+	return 0;
+}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 30be3c1..bbc2c13 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -50,7 +50,6 @@
 	" before undocking");
 
 static struct atomic_notifier_head dock_notifier_list;
-static char dock_device_name[] = "dock";
 
 static const struct acpi_device_id dock_device_ids[] = {
 	{"LNXDOCK", 0},
@@ -93,40 +92,30 @@
  *                         Dock Dependent device functions                   *
  *****************************************************************************/
 /**
- *  alloc_dock_dependent_device - allocate and init a dependent device
- *  @handle: the acpi_handle of the dependent device
+ * add_dock_dependent_device - associate a device with the dock station
+ * @ds: The dock station
+ * @handle: handle of the dependent device
  *
- *  Allocate memory for a dependent device structure for a device referenced
- *  by the acpi handle
+ * Add the dependent device to the dock's dependent device list.
  */
-static struct dock_dependent_device *
-alloc_dock_dependent_device(acpi_handle handle)
+static int
+add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
 {
 	struct dock_dependent_device *dd;
 
 	dd = kzalloc(sizeof(*dd), GFP_KERNEL);
-	if (dd) {
-		dd->handle = handle;
-		INIT_LIST_HEAD(&dd->list);
-		INIT_LIST_HEAD(&dd->hotplug_list);
-	}
-	return dd;
-}
+	if (!dd)
+		return -ENOMEM;
 
-/**
- * add_dock_dependent_device - associate a device with the dock station
- * @ds: The dock station
- * @dd: The dependent device
- *
- * Add the dependent device to the dock's dependent device list.
- */
-static void
-add_dock_dependent_device(struct dock_station *ds,
-			  struct dock_dependent_device *dd)
-{
+	dd->handle = handle;
+	INIT_LIST_HEAD(&dd->list);
+	INIT_LIST_HEAD(&dd->hotplug_list);
+
 	spin_lock(&ds->dd_lock);
 	list_add_tail(&dd->list, &ds->dependent_devices);
 	spin_unlock(&ds->dd_lock);
+
+	return 0;
 }
 
 /**
@@ -249,6 +238,7 @@
 static int is_ejectable_bay(acpi_handle handle)
 {
 	acpi_handle phandle;
+
 	if (!is_ejectable(handle))
 		return 0;
 	if (is_battery(handle) || is_ata(handle))
@@ -275,14 +265,13 @@
 
 	if (is_dock(handle))
 		return 1;
-	list_for_each_entry(dock_station, &dock_stations, sibling) {
+
+	list_for_each_entry(dock_station, &dock_stations, sibling)
 		if (find_dock_dependent_device(dock_station, handle))
 			return 1;
-	}
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(is_dock_device);
 
 /**
@@ -305,8 +294,6 @@
 	return 0;
 }
 
-
-
 /**
  * dock_create_acpi_device - add new devices to acpi
  * @handle - handle of the device to add
@@ -320,7 +307,7 @@
  */
 static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
 {
-	struct acpi_device *device = NULL;
+	struct acpi_device *device;
 	struct acpi_device *parent_device;
 	acpi_handle parent;
 	int ret;
@@ -337,8 +324,7 @@
 		ret = acpi_bus_add(&device, parent_device, handle,
 			ACPI_BUS_TYPE_DEVICE);
 		if (ret) {
-			pr_debug("error adding bus, %x\n",
-				-ret);
+			pr_debug("error adding bus, %x\n", -ret);
 			return NULL;
 		}
 	}
@@ -364,7 +350,6 @@
 	}
 }
 
-
 /**
  * hotplug_dock_devices - insert or remove devices on the dock station
  * @ds: the dock station
@@ -384,10 +369,9 @@
 	/*
 	 * First call driver specific hotplug functions
 	 */
-	list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
+	list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
 		if (dd->ops && dd->ops->handler)
 			dd->ops->handler(dd->handle, event, dd->context);
-	}
 
 	/*
 	 * Now make sure that an acpi_device is created for each
@@ -426,6 +410,7 @@
 	list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
 		if (dd->ops && dd->ops->uevent)
 			dd->ops->uevent(dd->handle, event, dd->context);
+
 	if (num != DOCK_EVENT)
 		kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
 }
@@ -456,8 +441,8 @@
 	arg.type = ACPI_TYPE_INTEGER;
 	arg.integer.value = 1;
 
-	if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0",
-					      &arg_list, NULL)))
+	status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL);
+	if (ACPI_FAILURE(status))
 		pr_debug("Failed to evaluate _EJ0!\n");
 }
 
@@ -577,7 +562,6 @@
 
 	return atomic_notifier_chain_register(&dock_notifier_list, nb);
 }
-
 EXPORT_SYMBOL_GPL(register_dock_notifier);
 
 /**
@@ -591,7 +575,6 @@
 
 	atomic_notifier_chain_unregister(&dock_notifier_list, nb);
 }
-
 EXPORT_SYMBOL_GPL(unregister_dock_notifier);
 
 /**
@@ -636,7 +619,6 @@
 
 	return ret;
 }
-
 EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
 
 /**
@@ -657,7 +639,6 @@
 			dock_del_hotplug_device(dock_station, dd);
 	}
 }
-
 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
 
 /**
@@ -772,7 +753,7 @@
 
 static void acpi_dock_deferred_cb(void *context)
 {
-	struct dock_data *data = (struct dock_data *)context;
+	struct dock_data *data = context;
 
 	dock_notify(data->handle, data->event, data->ds);
 	kfree(data);
@@ -782,23 +763,22 @@
 	unsigned long event, void *data)
 {
 	struct dock_station *dock_station;
-	acpi_handle handle = (acpi_handle)data;
+	acpi_handle handle = data;
 
 	if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
 	   && event != ACPI_NOTIFY_EJECT_REQUEST)
 		return 0;
 	list_for_each_entry(dock_station, &dock_stations, sibling) {
 		if (dock_station->handle == handle) {
-			struct dock_data *dock_data;
+			struct dock_data *dd;
 
-			dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL);
-			if (!dock_data)
+			dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+			if (!dd)
 				return 0;
-			dock_data->handle = handle;
-			dock_data->event = event;
-			dock_data->ds = dock_station;
-			acpi_os_hotplug_execute(acpi_dock_deferred_cb,
-				dock_data);
+			dd->handle = handle;
+			dd->event = event;
+			dd->ds = dock_station;
+			acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
 			return 0 ;
 		}
 	}
@@ -826,7 +806,6 @@
 	acpi_status status;
 	acpi_handle tmp, parent;
 	struct dock_station *ds = context;
-	struct dock_dependent_device *dd;
 
 	status = acpi_bus_get_ejd(handle, &tmp);
 	if (ACPI_FAILURE(status)) {
@@ -840,11 +819,9 @@
 			goto fdd_out;
 	}
 
-	if (tmp == ds->handle) {
-		dd = alloc_dock_dependent_device(handle);
-		if (dd)
-			add_dock_dependent_device(ds, dd);
-	}
+	if (tmp == ds->handle)
+		add_dock_dependent_device(ds, handle);
+
 fdd_out:
 	return AE_OK;
 }
@@ -857,8 +834,7 @@
 {
 	struct acpi_device *tmp;
 
-	struct dock_station *dock_station = *((struct dock_station **)
-		dev->platform_data);
+	struct dock_station *dock_station = dev->platform_data;
 
 	if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
 		return snprintf(buf, PAGE_SIZE, "1\n");
@@ -872,8 +848,7 @@
 static ssize_t show_flags(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
-	struct dock_station *dock_station = *((struct dock_station **)
-		dev->platform_data);
+	struct dock_station *dock_station = dev->platform_data;
 	return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
 
 }
@@ -886,8 +861,7 @@
 			   const char *buf, size_t count)
 {
 	int ret;
-	struct dock_station *dock_station = *((struct dock_station **)
-		dev->platform_data);
+	struct dock_station *dock_station = dev->platform_data;
 
 	if (!count)
 		return -EINVAL;
@@ -905,8 +879,7 @@
 			     struct device_attribute *attr, char *buf)
 {
 	unsigned long long lbuf;
-	struct dock_station *dock_station = *((struct dock_station **)
-		dev->platform_data);
+	struct dock_station *dock_station = dev->platform_data;
 	acpi_status status = acpi_evaluate_integer(dock_station->handle,
 					"_UID", NULL, &lbuf);
 	if (ACPI_FAILURE(status))
@@ -919,8 +892,7 @@
 static ssize_t show_dock_type(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	struct dock_station *dock_station = *((struct dock_station **)
-		dev->platform_data);
+	struct dock_station *dock_station = dev->platform_data;
 	char *type;
 
 	if (dock_station->flags & DOCK_IS_DOCK)
@@ -936,6 +908,19 @@
 }
 static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
 
+static struct attribute *dock_attributes[] = {
+	&dev_attr_docked.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_undock.attr,
+	&dev_attr_uid.attr,
+	&dev_attr_type.attr,
+	NULL
+};
+
+static struct attribute_group dock_attribute_group = {
+	.attrs = dock_attributes
+};
+
 /**
  * dock_add - add a new dock station
  * @handle: the dock station handle
@@ -945,39 +930,30 @@
  */
 static int dock_add(acpi_handle handle)
 {
-	int ret;
-	struct dock_dependent_device *dd;
-	struct dock_station *dock_station;
-	struct platform_device *dock_device;
+	int ret, id;
+	struct dock_station ds, *dock_station;
+	struct platform_device *dd;
 
-	/* allocate & initialize the dock_station private data */
-	dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
-	if (!dock_station)
-		return -ENOMEM;
+	id = dock_station_count;
+	dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds));
+	if (IS_ERR(dd))
+		return PTR_ERR(dd);
+
+	dock_station = dd->dev.platform_data;
+
 	dock_station->handle = handle;
+	dock_station->dock_device = dd;
 	dock_station->last_dock_time = jiffies - HZ;
-	INIT_LIST_HEAD(&dock_station->dependent_devices);
-	INIT_LIST_HEAD(&dock_station->hotplug_devices);
-	INIT_LIST_HEAD(&dock_station->sibling);
-	spin_lock_init(&dock_station->dd_lock);
-	mutex_init(&dock_station->hp_lock);
-	ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
 
-	/* initialize platform device stuff */
-	dock_station->dock_device =
-		platform_device_register_simple(dock_device_name,
-			dock_station_count, NULL, 0);
-	dock_device = dock_station->dock_device;
-	if (IS_ERR(dock_device)) {
-		kfree(dock_station);
-		dock_station = NULL;
-		return PTR_ERR(dock_device);
-	}
-	platform_device_add_data(dock_device, &dock_station,
-		sizeof(struct dock_station *));
+	mutex_init(&dock_station->hp_lock);
+	spin_lock_init(&dock_station->dd_lock);
+	INIT_LIST_HEAD(&dock_station->sibling);
+	INIT_LIST_HEAD(&dock_station->hotplug_devices);
+	ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
+	INIT_LIST_HEAD(&dock_station->dependent_devices);
 
 	/* we want the dock device to send uevents */
-	dev_set_uevent_suppress(&dock_device->dev, 0);
+	dev_set_uevent_suppress(&dd->dev, 0);
 
 	if (is_dock(handle))
 		dock_station->flags |= DOCK_IS_DOCK;
@@ -986,47 +962,9 @@
 	if (is_battery(handle))
 		dock_station->flags |= DOCK_IS_BAT;
 
-	ret = device_create_file(&dock_device->dev, &dev_attr_docked);
-	if (ret) {
-		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
-		platform_device_unregister(dock_device);
-		kfree(dock_station);
-		dock_station = NULL;
-		return ret;
-	}
-	ret = device_create_file(&dock_device->dev, &dev_attr_undock);
-	if (ret) {
-		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
-		device_remove_file(&dock_device->dev, &dev_attr_docked);
-		platform_device_unregister(dock_device);
-		kfree(dock_station);
-		dock_station = NULL;
-		return ret;
-	}
-	ret = device_create_file(&dock_device->dev, &dev_attr_uid);
-	if (ret) {
-		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
-		device_remove_file(&dock_device->dev, &dev_attr_docked);
-		device_remove_file(&dock_device->dev, &dev_attr_undock);
-		platform_device_unregister(dock_device);
-		kfree(dock_station);
-		dock_station = NULL;
-		return ret;
-	}
-	ret = device_create_file(&dock_device->dev, &dev_attr_flags);
-	if (ret) {
-		printk(KERN_ERR "Error %d adding sysfs file\n", ret);
-		device_remove_file(&dock_device->dev, &dev_attr_docked);
-		device_remove_file(&dock_device->dev, &dev_attr_undock);
-		device_remove_file(&dock_device->dev, &dev_attr_uid);
-		platform_device_unregister(dock_device);
-		kfree(dock_station);
-		dock_station = NULL;
-		return ret;
-	}
-	ret = device_create_file(&dock_device->dev, &dev_attr_type);
+	ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
 	if (ret)
-		printk(KERN_ERR"Error %d adding sysfs file\n", ret);
+		goto err_unregister;
 
 	/* Find dependent devices */
 	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -1034,58 +972,43 @@
 			    dock_station, NULL);
 
 	/* add the dock station as a device dependent on itself */
-	dd = alloc_dock_dependent_device(handle);
-	if (!dd) {
-		kfree(dock_station);
-		dock_station = NULL;
-		ret = -ENOMEM;
-		goto dock_add_err_unregister;
-	}
-	add_dock_dependent_device(dock_station, dd);
+	ret = add_dock_dependent_device(dock_station, handle);
+	if (ret)
+		goto err_rmgroup;
 
 	dock_station_count++;
 	list_add(&dock_station->sibling, &dock_stations);
 	return 0;
 
-dock_add_err_unregister:
-	device_remove_file(&dock_device->dev, &dev_attr_type);
-	device_remove_file(&dock_device->dev, &dev_attr_docked);
-	device_remove_file(&dock_device->dev, &dev_attr_undock);
-	device_remove_file(&dock_device->dev, &dev_attr_uid);
-	device_remove_file(&dock_device->dev, &dev_attr_flags);
-	platform_device_unregister(dock_device);
-	kfree(dock_station);
-	dock_station = NULL;
+err_rmgroup:
+	sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
+err_unregister:
+	platform_device_unregister(dd);
+	printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
 	return ret;
 }
 
 /**
  * dock_remove - free up resources related to the dock station
  */
-static int dock_remove(struct dock_station *dock_station)
+static int dock_remove(struct dock_station *ds)
 {
 	struct dock_dependent_device *dd, *tmp;
-	struct platform_device *dock_device = dock_station->dock_device;
+	struct platform_device *dock_device = ds->dock_device;
 
 	if (!dock_station_count)
 		return 0;
 
 	/* remove dependent devices */
-	list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices,
-				 list)
-	    kfree(dd);
+	list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list)
+		kfree(dd);
+
+	list_del(&ds->sibling);
 
 	/* cleanup sysfs */
-	device_remove_file(&dock_device->dev, &dev_attr_type);
-	device_remove_file(&dock_device->dev, &dev_attr_docked);
-	device_remove_file(&dock_device->dev, &dev_attr_undock);
-	device_remove_file(&dock_device->dev, &dev_attr_uid);
-	device_remove_file(&dock_device->dev, &dev_attr_flags);
+	sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group);
 	platform_device_unregister(dock_device);
 
-	/* free dock station memory */
-	kfree(dock_station);
-	dock_station = NULL;
 	return 0;
 }
 
@@ -1103,11 +1026,10 @@
 {
 	acpi_status status = AE_OK;
 
-	if (is_dock(handle)) {
-		if (dock_add(handle) >= 0) {
+	if (is_dock(handle))
+		if (dock_add(handle) >= 0)
 			status = AE_CTRL_TERMINATE;
-		}
-	}
+
 	return status;
 }
 
@@ -1145,8 +1067,7 @@
 
 static void __exit dock_exit(void)
 {
-	struct dock_station *dock_station;
-	struct dock_station *tmp;
+	struct dock_station *tmp, *dock_station;
 
 	unregister_acpi_bus_notifier(&dock_acpi_notifier);
 	list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling)
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index f419849..acf2ab2 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -267,7 +267,7 @@
 		goto end;
 	}
 
-	dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id);
+	dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id);
 
 	device->driver_data = cdev;
 	result = sysfs_create_link(&device->dev.kobj,
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 2be2fb6..7ad48df 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/acpi.h>
+#include <linux/numa.h>
 #include <acpi/acpi_bus.h>
 
 #define PREFIX "ACPI: "
@@ -40,14 +41,14 @@
 
 /* maps to convert between proximity domain and logical node ID */
 static int pxm_to_node_map[MAX_PXM_DOMAINS]
-				= { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL };
+			= { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
 static int node_to_pxm_map[MAX_NUMNODES]
-				= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
+			= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
 
 int pxm_to_node(int pxm)
 {
 	if (pxm < 0)
-		return NID_INVAL;
+		return NUMA_NO_NODE;
 	return pxm_to_node_map[pxm];
 }
 
@@ -68,9 +69,9 @@
 {
 	int node = pxm_to_node_map[pxm];
 
-	if (node < 0){
+	if (node < 0) {
 		if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
-			return NID_INVAL;
+			return NUMA_NO_NODE;
 		node = first_unset_node(nodes_found_map);
 		__acpi_map_pxm_to_node(pxm, node);
 		node_set(node, nodes_found_map);
@@ -79,16 +80,6 @@
 	return node;
 }
 
-#if 0
-void __cpuinit acpi_unmap_pxm_to_node(int node)
-{
-	int pxm = node_to_pxm_map[node];
-	pxm_to_node_map[pxm] = NID_INVAL;
-	node_to_pxm_map[node] = PXM_INVAL;
-	node_clear(node, nodes_found_map);
-}
-#endif  /*  0  */
-
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 7c1c59e..02e8464 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1118,7 +1118,7 @@
 
 /* Check for resource conflicts between ACPI OperationRegions and native
  * drivers */
-int acpi_check_resource_conflict(struct resource *res)
+int acpi_check_resource_conflict(const struct resource *res)
 {
 	struct acpi_res_list *res_list_elem;
 	int ioport;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1af8081..101cce3 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -202,72 +202,24 @@
 		}
 }
 
-static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
-			  0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
+static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
 
 static acpi_status acpi_pci_run_osc(acpi_handle handle,
 				    const u32 *capbuf, u32 *retval)
 {
+	struct acpi_osc_context context = {
+		.uuid_str = pci_osc_uuid_str,
+		.rev = 1,
+		.cap.length = 12,
+		.cap.pointer = (void *)capbuf,
+	};
 	acpi_status status;
-	struct acpi_object_list input;
-	union acpi_object in_params[4];
-	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
-	union acpi_object *out_obj;
-	u32 errors;
 
-	/* Setting up input parameters */
-	input.count = 4;
-	input.pointer = in_params;
-	in_params[0].type 		= ACPI_TYPE_BUFFER;
-	in_params[0].buffer.length 	= 16;
-	in_params[0].buffer.pointer	= OSC_UUID;
-	in_params[1].type 		= ACPI_TYPE_INTEGER;
-	in_params[1].integer.value 	= 1;
-	in_params[2].type 		= ACPI_TYPE_INTEGER;
-	in_params[2].integer.value	= 3;
-	in_params[3].type		= ACPI_TYPE_BUFFER;
-	in_params[3].buffer.length 	= 12;
-	in_params[3].buffer.pointer 	= (u8 *)capbuf;
-
-	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
-	if (ACPI_FAILURE(status))
-		return status;
-
-	if (!output.length)
-		return AE_NULL_OBJECT;
-
-	out_obj = output.pointer;
-	if (out_obj->type != ACPI_TYPE_BUFFER) {
-		printk(KERN_DEBUG "_OSC evaluation returned wrong type\n");
-		status = AE_TYPE;
-		goto out_kfree;
+	status = acpi_run_osc(handle, &context);
+	if (ACPI_SUCCESS(status)) {
+		*retval = *((u32 *)(context.ret.pointer + 8));
+		kfree(context.ret.pointer);
 	}
-	/* Need to ignore the bit0 in result code */
-	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
-	if (errors) {
-		if (errors & OSC_REQUEST_ERROR)
-			printk(KERN_DEBUG "_OSC request failed\n");
-		if (errors & OSC_INVALID_UUID_ERROR)
-			printk(KERN_DEBUG "_OSC invalid UUID\n");
-		if (errors & OSC_INVALID_REVISION_ERROR)
-			printk(KERN_DEBUG "_OSC invalid revision\n");
-		if (errors & OSC_CAPABILITIES_MASK_ERROR) {
-			if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
-				goto out_success;
-			printk(KERN_DEBUG
-			       "Firmware did not grant requested _OSC control\n");
-			status = AE_SUPPORT;
-			goto out_kfree;
-		}
-		status = AE_ERROR;
-		goto out_kfree;
-	}
-out_success:
-	*retval = *((u32 *)(out_obj->buffer.pointer + 8));
-	status = AE_OK;
-
-out_kfree:
-	kfree(output.pointer);
 	return status;
 }
 
@@ -277,10 +229,10 @@
 	u32 support_set, result, capbuf[3];
 
 	/* do _OSC query for all possible controls */
-	support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS);
+	support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS);
 	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
 	capbuf[OSC_SUPPORT_TYPE] = support_set;
-	capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
+	capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
 
 	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
 	if (ACPI_SUCCESS(status)) {
@@ -427,7 +379,7 @@
 	if (ACPI_FAILURE(status))
 		return status;
 
-	control_req = (flags & OSC_CONTROL_MASKS);
+	control_req = (flags & OSC_PCI_CONTROL_MASKS);
 	if (!control_req)
 		return AE_TYPE;
 
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index cb4283f..4173123 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -353,7 +353,7 @@
 			   PDE(inode)->data);
 }
 
-static int acpi_processor_add_fs(struct acpi_device *device)
+static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
 {
 	struct proc_dir_entry *entry = NULL;
 
@@ -722,7 +722,7 @@
 	switch (event) {
 	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
 		saved = pr->performance_platform_limit;
-		acpi_processor_ppc_has_changed(pr);
+		acpi_processor_ppc_has_changed(pr, 1);
 		if (saved == pr->performance_platform_limit)
 			break;
 		acpi_bus_generate_proc_event(device, event,
@@ -758,7 +758,7 @@
 	struct acpi_processor *pr = per_cpu(processors, cpu);
 
 	if (action == CPU_ONLINE && pr) {
-		acpi_processor_ppc_has_changed(pr);
+		acpi_processor_ppc_has_changed(pr, 0);
 		acpi_processor_cst_has_changed(pr);
 		acpi_processor_tstate_has_changed(pr);
 	}
@@ -830,7 +830,7 @@
 	arch_acpi_processor_cleanup_pdc(pr);
 
 #ifdef CONFIG_CPU_FREQ
-	acpi_processor_ppc_has_changed(pr);
+	acpi_processor_ppc_has_changed(pr, 0);
 #endif
 	acpi_processor_get_throttling_info(pr);
 	acpi_processor_get_limit_info(pr);
@@ -845,7 +845,7 @@
 		goto err_power_exit;
 	}
 
-	dev_info(&device->dev, "registered as cooling_device%d\n",
+	dev_dbg(&device->dev, "registered as cooling_device%d\n",
 		 pr->cdev->id);
 
 	result = sysfs_create_link(&device->dev.kobj,
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index bbd066e..d1676b1 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -164,7 +164,7 @@
 		pr->power.timer_broadcast_on_state = state;
 }
 
-static void lapic_timer_propagate_broadcast(void *arg)
+static void __lapic_timer_propagate_broadcast(void *arg)
 {
 	struct acpi_processor *pr = (struct acpi_processor *) arg;
 	unsigned long reason;
@@ -175,6 +175,12 @@
 	clockevents_notify(reason, &pr->id);
 }
 
+static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
+{
+	smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast,
+				 (void *)pr, 1);
+}
+
 /* Power(C) State timer broadcast control */
 static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 				       struct acpi_processor_cx *cx,
@@ -638,8 +644,7 @@
 		working++;
 	}
 
-	smp_call_function_single(pr->id, lapic_timer_propagate_broadcast,
-				 pr, 1);
+	lapic_timer_propagate_broadcast(pr);
 
 	return (working);
 }
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 01e366d..2cabadc 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -152,15 +152,59 @@
 	return 0;
 }
 
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE	0x80
+/*
+ * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
+ * @handle: ACPI processor handle
+ * @status: the status code of _PPC evaluation
+ *	0: success. OSPM is now using the performance state specificed.
+ *	1: failure. OSPM has not changed the number of P-states in use
+ */
+static void acpi_processor_ppc_ost(acpi_handle handle, int status)
+{
+	union acpi_object params[2] = {
+		{.type = ACPI_TYPE_INTEGER,},
+		{.type = ACPI_TYPE_INTEGER,},
+	};
+	struct acpi_object_list arg_list = {2, params};
+	acpi_handle temp;
+
+	params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
+	params[1].integer.value =  status;
+
+	/* when there is no _OST , skip it */
+	if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
+		return;
+
+	acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
+	return;
+}
+
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
 {
 	int ret;
 
-	if (ignore_ppc)
+	if (ignore_ppc) {
+		/*
+		 * Only when it is notification event, the _OST object
+		 * will be evaluated. Otherwise it is skipped.
+		 */
+		if (event_flag)
+			acpi_processor_ppc_ost(pr->handle, 1);
 		return 0;
+	}
 
 	ret = acpi_processor_get_platform_limit(pr);
-
+	/*
+	 * Only when it is notification event, the _OST object
+	 * will be evaluated. Otherwise it is skipped.
+	 */
+	if (event_flag) {
+		if (ret < 0)
+			acpi_processor_ppc_ost(pr->handle, 1);
+		else
+			acpi_processor_ppc_ost(pr->handle, 0);
+	}
 	if (ret < 0)
 		return (ret);
 	else
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 65f6781..9073ada 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1052,6 +1052,13 @@
 				   acpi_device_bid(device));
 		}
 		seq_puts(seq, "\n");
+	} else {
+		seq_printf(seq, "passive (forced):");
+		if (tz->thermal_zone->forced_passive)
+			seq_printf(seq, "        %i C\n",
+				   tz->thermal_zone->forced_passive / 1000);
+		else
+			seq_printf(seq, "<not set>\n");
 	}
 
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index f734b34..25a4c86 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -557,7 +557,7 @@
           memcpy((caddr_t)&cbrVC,(caddr_t)TstSchedTbl,sizeof(cbrVC));
        } /* while */
        // Move this VCI number into this location of the CBR Sched table.
-       memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex,sizeof(TstSchedTbl));
+       memcpy((caddr_t)TstSchedTbl, (caddr_t)&vcIndex, sizeof(*TstSchedTbl));
        dev->CbrRemEntries--;
        toBeAssigned--;
    } /* while */ 
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 989429c..c4c8f2e 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -341,6 +341,64 @@
 }
 #endif
 
+#ifdef CONFIG_MEMORY_FAILURE
+/*
+ * Support for offlining pages of memory
+ */
+
+/* Soft offline a page */
+static ssize_t
+store_soft_offline_page(struct class *class, const char *buf, size_t count)
+{
+	int ret;
+	u64 pfn;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (strict_strtoull(buf, 0, &pfn) < 0)
+		return -EINVAL;
+	pfn >>= PAGE_SHIFT;
+	if (!pfn_valid(pfn))
+		return -ENXIO;
+	ret = soft_offline_page(pfn_to_page(pfn), 0);
+	return ret == 0 ? count : ret;
+}
+
+/* Forcibly offline a page, including killing processes. */
+static ssize_t
+store_hard_offline_page(struct class *class, const char *buf, size_t count)
+{
+	int ret;
+	u64 pfn;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (strict_strtoull(buf, 0, &pfn) < 0)
+		return -EINVAL;
+	pfn >>= PAGE_SHIFT;
+	ret = __memory_failure(pfn, 0, 0);
+	return ret ? ret : count;
+}
+
+static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page);
+static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page);
+
+static __init int memory_fail_init(void)
+{
+	int err;
+
+	err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_soft_offline_page.attr);
+	if (!err)
+		err = sysfs_create_file(&memory_sysdev_class.kset.kobj,
+				&class_attr_hard_offline_page.attr);
+	return err;
+}
+#else
+static inline int memory_fail_init(void)
+{
+	return 0;
+}
+#endif
+
 /*
  * Note that phys_device is optional.  It is here to allow for
  * differentiation between which *physical* devices each
@@ -473,6 +531,9 @@
 	err = memory_probe_init();
 	if (!ret)
 		ret = err;
+	err = memory_fail_init();
+	if (!ret)
+		ret = err;
 	err = block_size_init();
 	if (!ret)
 		ret = err;
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 8aa2443..1a216c1 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -23,8 +23,8 @@
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/resume-trace.h>
-#include <linux/rwsem.h>
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 
 #include "../base.h"
 #include "power.h"
@@ -172,6 +172,13 @@
 		 pm_message_t state)
 {
 	int error = 0;
+	ktime_t calltime, delta, rettime;
+
+	if (initcall_debug) {
+		pr_info("calling  %s+ @ %i\n",
+				dev_name(dev), task_pid_nr(current));
+		calltime = ktime_get();
+	}
 
 	switch (state.event) {
 #ifdef CONFIG_SUSPEND
@@ -219,6 +226,14 @@
 	default:
 		error = -EINVAL;
 	}
+
+	if (initcall_debug) {
+		rettime = ktime_get();
+		delta = ktime_sub(rettime, calltime);
+		pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
+			error, (unsigned long long)ktime_to_ns(delta) >> 10);
+	}
+
 	return error;
 }
 
@@ -236,6 +251,13 @@
 			pm_message_t state)
 {
 	int error = 0;
+	ktime_t calltime, delta, rettime;
+
+	if (initcall_debug) {
+		pr_info("calling  %s_i+ @ %i\n",
+				dev_name(dev), task_pid_nr(current));
+		calltime = ktime_get();
+	}
 
 	switch (state.event) {
 #ifdef CONFIG_SUSPEND
@@ -283,6 +305,14 @@
 	default:
 		error = -EINVAL;
 	}
+
+	if (initcall_debug) {
+		rettime = ktime_get();
+		delta = ktime_sub(rettime, calltime);
+		printk("initcall %s_i+ returned %d after %Ld usecs\n", dev_name(dev),
+			error, (unsigned long long)ktime_to_ns(delta) >> 10);
+	}
+
 	return error;
 }
 
@@ -341,14 +371,11 @@
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (!dev->bus)
-		goto End;
-
-	if (dev->bus->pm) {
+	if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "EARLY ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
 	}
- End:
+
 	TRACE_RESUME(error);
 	return error;
 }
@@ -584,10 +611,7 @@
 {
 	int error = 0;
 
-	if (!dev->bus)
-		return 0;
-
-	if (dev->bus->pm) {
+	if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "LATE ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
 	}
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 5a01ece..40d7720 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -701,15 +701,15 @@
  * @dev: Device to handle.
  * @sync: If set and the device is suspended, resume it synchronously.
  *
- * Increment the usage count of the device and if it was zero previously,
- * resume it or submit a resume request for it, depending on the value of @sync.
+ * Increment the usage count of the device and resume it or submit a resume
+ * request for it, depending on the value of @sync.
  */
 int __pm_runtime_get(struct device *dev, bool sync)
 {
-	int retval = 1;
+	int retval;
 
-	if (atomic_add_return(1, &dev->power.usage_count) == 1)
-		retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
+	atomic_inc(&dev->power.usage_count);
+	retval = sync ? pm_runtime_resume(dev) : pm_request_resume(dev);
 
 	return retval;
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 6f31c94..31be3ac 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -502,7 +502,7 @@
 
 config BFIN_OTP
 	tristate "Blackfin On-Chip OTP Memory Support"
-	depends on BLACKFIN && (BF52x || BF54x)
+	depends on BLACKFIN && (BF51x || BF52x || BF54x)
 	default y
 	help
 	  If you say Y here, you will get support for a character device
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index 26a47dc..53c524e 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -285,6 +285,7 @@
 	.unlocked_ioctl	= efi_rtc_ioctl,
 	.open		= efi_rtc_open,
 	.release	= efi_rtc_close,
+	.llseek		= no_llseek,
 };
 
 static struct miscdevice efi_rtc_dev= {
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index 8070487..cf82fed 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -370,7 +370,7 @@
 			return SI_SM_IDLE;
 
 	case KCS_START_OP:
-		if (state != KCS_IDLE) {
+		if (state != KCS_IDLE_STATE) {
 			start_error_recovery(kcs,
 					     "State machine not idle at start");
 			break;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index d2e6980..679cd08 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -64,6 +64,7 @@
 #include <linux/dmi.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/pnp.h>
 
 #ifdef CONFIG_PPC_OF
 #include <linux/of_device.h>
@@ -1919,7 +1920,7 @@
 	s8      spmi_id[1]; /* A '\0' terminated array starts here. */
 };
 
-static __devinit int try_init_acpi(struct SPMITable *spmi)
+static __devinit int try_init_spmi(struct SPMITable *spmi)
 {
 	struct smi_info  *info;
 	u8 		 addr_space;
@@ -1940,7 +1941,7 @@
 		return -ENOMEM;
 	}
 
-	info->addr_source = "ACPI";
+	info->addr_source = "SPMI";
 
 	/* Figure out the interface type. */
 	switch (spmi->InterfaceType) {
@@ -2002,7 +2003,7 @@
 	return 0;
 }
 
-static __devinit void acpi_find_bmc(void)
+static __devinit void spmi_find_bmc(void)
 {
 	acpi_status      status;
 	struct SPMITable *spmi;
@@ -2020,9 +2021,106 @@
 		if (status != AE_OK)
 			return;
 
-		try_init_acpi(spmi);
+		try_init_spmi(spmi);
 	}
 }
+
+static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
+				    const struct pnp_device_id *dev_id)
+{
+	struct acpi_device *acpi_dev;
+	struct smi_info *info;
+	acpi_handle handle;
+	acpi_status status;
+	unsigned long long tmp;
+
+	acpi_dev = pnp_acpi_device(dev);
+	if (!acpi_dev)
+		return -ENODEV;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->addr_source = "ACPI";
+
+	handle = acpi_dev->handle;
+
+	/* _IFT tells us the interface type: KCS, BT, etc */
+	status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
+	if (ACPI_FAILURE(status))
+		goto err_free;
+
+	switch (tmp) {
+	case 1:
+		info->si_type = SI_KCS;
+		break;
+	case 2:
+		info->si_type = SI_SMIC;
+		break;
+	case 3:
+		info->si_type = SI_BT;
+		break;
+	default:
+		dev_info(&dev->dev, "unknown interface type %lld\n", tmp);
+		goto err_free;
+	}
+
+	if (pnp_port_valid(dev, 0)) {
+		info->io_setup = port_setup;
+		info->io.addr_type = IPMI_IO_ADDR_SPACE;
+		info->io.addr_data = pnp_port_start(dev, 0);
+	} else if (pnp_mem_valid(dev, 0)) {
+		info->io_setup = mem_setup;
+		info->io.addr_type = IPMI_MEM_ADDR_SPACE;
+		info->io.addr_data = pnp_mem_start(dev, 0);
+	} else {
+		dev_err(&dev->dev, "no I/O or memory address\n");
+		goto err_free;
+	}
+
+	info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = 0;
+
+	/* If _GPE exists, use it; otherwise use standard interrupts */
+	status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
+	if (ACPI_SUCCESS(status)) {
+		info->irq = tmp;
+		info->irq_setup = acpi_gpe_irq_setup;
+	} else if (pnp_irq_valid(dev, 0)) {
+		info->irq = pnp_irq(dev, 0);
+		info->irq_setup = std_irq_setup;
+	}
+
+	info->dev = &acpi_dev->dev;
+	pnp_set_drvdata(dev, info);
+
+	return try_smi_init(info);
+
+err_free:
+	kfree(info);
+	return -EINVAL;
+}
+
+static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
+{
+	struct smi_info *info = pnp_get_drvdata(dev);
+
+	cleanup_one_si(info);
+}
+
+static const struct pnp_device_id pnp_dev_table[] = {
+	{"IPI0001", 0},
+	{"", 0},
+};
+
+static struct pnp_driver ipmi_pnp_driver = {
+	.name		= DEVICE_NAME,
+	.probe		= ipmi_pnp_probe,
+	.remove		= __devexit_p(ipmi_pnp_remove),
+	.id_table	= pnp_dev_table,
+};
 #endif
 
 #ifdef CONFIG_DMI
@@ -2202,7 +2300,6 @@
 	int rv;
 	int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
 	struct smi_info *info;
-	int first_reg_offset = 0;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -2241,9 +2338,6 @@
 	info->addr_source_cleanup = ipmi_pci_cleanup;
 	info->addr_source_data = pdev;
 
-	if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID)
-		first_reg_offset = 1;
-
 	if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
 		info->io_setup = port_setup;
 		info->io.addr_type = IPMI_IO_ADDR_SPACE;
@@ -3108,7 +3202,10 @@
 #endif
 
 #ifdef CONFIG_ACPI
-	acpi_find_bmc();
+	spmi_find_bmc();
+#endif
+#ifdef CONFIG_PNP
+	pnp_register_driver(&ipmi_pnp_driver);
 #endif
 
 #ifdef CONFIG_PCI
@@ -3233,6 +3330,9 @@
 #ifdef CONFIG_PCI
 	pci_unregister_driver(&ipmi_pci_driver);
 #endif
+#ifdef CONFIG_PNP
+	pnp_unregister_driver(&ipmi_pnp_driver);
+#endif
 
 #ifdef CONFIG_PPC_OF
 	of_unregister_platform_driver(&ipmi_of_platform_driver);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 5619007..f706b1d 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -233,7 +233,8 @@
 }
 
 /*
- * Making beeps and bells.
+ * Making beeps and bells. Note that we prefer beeps to bells, but when
+ * shutting the sound off we do both.
  */
 
 static int kd_sound_helper(struct input_handle *handle, void *data)
@@ -242,9 +243,12 @@
 	struct input_dev *dev = handle->dev;
 
 	if (test_bit(EV_SND, dev->evbit)) {
-		if (test_bit(SND_TONE, dev->sndbit))
+		if (test_bit(SND_TONE, dev->sndbit)) {
 			input_inject_event(handle, EV_SND, SND_TONE, *hz);
-		if (test_bit(SND_BELL, handle->dev->sndbit))
+			if (*hz)
+				return 0;
+		}
+		if (test_bit(SND_BELL, dev->sndbit))
 			input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
 	}
 
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 44203ff..1ae2de7 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -339,7 +339,7 @@
 
 static void moom_callback(struct work_struct *ignored)
 {
-	out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0);
+	out_of_memory(node_zonelist(0, GFP_KERNEL), GFP_KERNEL, 0, NULL);
 }
 
 static DECLARE_WORK(moom_work, moom_callback);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e43fbc6..50faa1f 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -164,6 +164,9 @@
 int global_cursor_default = -1;
 module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
 
+static int cur_default = CUR_DEFAULT;
+module_param(cur_default, int, S_IRUGO | S_IWUSR);
+
 /*
  * ignore_poke: don't unblank the screen when things are typed.  This is
  * mainly for the privacy of braille terminal users.
@@ -1636,7 +1639,7 @@
 	/* do not do set_leds here because this causes an endless tasklet loop
 	   when the keyboard hasn't been initialized yet */
 
-	vc->vc_cursor_type = CUR_DEFAULT;
+	vc->vc_cursor_type = cur_default;
 	vc->vc_complement_mask = vc->vc_s_complement_mask;
 
 	default_attr(vc);
@@ -1838,7 +1841,7 @@
 				if (vc->vc_par[0])
 					vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
 				else
-					vc->vc_cursor_type = CUR_DEFAULT;
+					vc->vc_cursor_type = cur_default;
 				return;
 			}
 			break;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index eb140ff..e02d74b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -111,6 +111,24 @@
 	help
 	  Enable support for the Renesas SuperH DMA controllers.
 
+config COH901318
+	bool "ST-Ericsson COH901318 DMA support"
+	select DMA_ENGINE
+	depends on ARCH_U300
+	help
+	  Enable support for ST-Ericsson COH 901 318 DMA.
+
+config AMCC_PPC440SPE_ADMA
+	tristate "AMCC PPC440SPe ADMA support"
+	depends on 440SPe || 440SP
+	select DMA_ENGINE
+	select ARCH_HAS_ASYNC_TX_FIND_CHANNEL
+	help
+	  Enable support for the AMCC PPC440SPe RAID engines.
+
+config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
+	bool
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index eca71ba..807053d 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -10,3 +10,5 @@
 obj-$(CONFIG_MX3_IPU) += ipu/
 obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
 obj-$(CONFIG_SH_DMAE) += shdma.o
+obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
+obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
new file mode 100644
index 0000000..4a99cd9
--- /dev/null
+++ b/drivers/dma/coh901318.c
@@ -0,0 +1,1325 @@
+/*
+ * driver/dma/coh901318.c
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * DMA driver for COH 901 318
+ * Author: Per Friden <per.friden@stericsson.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/fs.h> /* everything... */
+#include <linux/slab.h> /* kmalloc() */
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <mach/coh901318.h>
+
+#include "coh901318_lli.h"
+
+#define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
+
+#ifdef VERBOSE_DEBUG
+#define COH_DBG(x) ({ if (1) x; 0; })
+#else
+#define COH_DBG(x) ({ if (0) x; 0; })
+#endif
+
+struct coh901318_desc {
+	struct dma_async_tx_descriptor desc;
+	struct list_head node;
+	struct scatterlist *sg;
+	unsigned int sg_len;
+	struct coh901318_lli *data;
+	enum dma_data_direction dir;
+	int pending_irqs;
+	unsigned long flags;
+};
+
+struct coh901318_base {
+	struct device *dev;
+	void __iomem *virtbase;
+	struct coh901318_pool pool;
+	struct powersave pm;
+	struct dma_device dma_slave;
+	struct dma_device dma_memcpy;
+	struct coh901318_chan *chans;
+	struct coh901318_platform *platform;
+};
+
+struct coh901318_chan {
+	spinlock_t lock;
+	int allocated;
+	int completed;
+	int id;
+	int stopped;
+
+	struct work_struct free_work;
+	struct dma_chan chan;
+
+	struct tasklet_struct tasklet;
+
+	struct list_head active;
+	struct list_head queue;
+	struct list_head free;
+
+	unsigned long nbr_active_done;
+	unsigned long busy;
+	int pending_irqs;
+
+	struct coh901318_base *base;
+};
+
+static void coh901318_list_print(struct coh901318_chan *cohc,
+				 struct coh901318_lli *lli)
+{
+	struct coh901318_lli *l;
+	dma_addr_t addr =  virt_to_phys(lli);
+	int i = 0;
+
+	while (addr) {
+		l = phys_to_virt(addr);
+		dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%x"
+			 ", dst 0x%x, link 0x%x link_virt 0x%p\n",
+			 i, l, l->control, l->src_addr, l->dst_addr,
+			 l->link_addr, phys_to_virt(l->link_addr));
+		i++;
+		addr = l->link_addr;
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#define COH901318_DEBUGFS_ASSIGN(x, y) (x = y)
+
+static struct coh901318_base *debugfs_dma_base;
+static struct dentry *dma_dentry;
+
+static int coh901318_debugfs_open(struct inode *inode, struct file *file)
+{
+
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static int coh901318_debugfs_read(struct file *file, char __user *buf,
+				  size_t count, loff_t *f_pos)
+{
+	u64 started_channels = debugfs_dma_base->pm.started_channels;
+	int pool_count = debugfs_dma_base->pool.debugfs_pool_counter;
+	int i;
+	int ret = 0;
+	char *dev_buf;
+	char *tmp;
+	int dev_size;
+
+	dev_buf = kmalloc(4*1024, GFP_KERNEL);
+	if (dev_buf == NULL)
+		goto err_kmalloc;
+	tmp = dev_buf;
+
+	tmp += sprintf(tmp, "DMA -- enable dma channels\n");
+
+	for (i = 0; i < debugfs_dma_base->platform->max_channels; i++)
+		if (started_channels & (1 << i))
+			tmp += sprintf(tmp, "channel %d\n", i);
+
+	tmp += sprintf(tmp, "Pool alloc nbr %d\n", pool_count);
+	dev_size = tmp  - dev_buf;
+
+	/* No more to read if offset != 0 */
+	if (*f_pos > dev_size)
+		goto out;
+
+	if (count > dev_size - *f_pos)
+		count = dev_size - *f_pos;
+
+	if (copy_to_user(buf, dev_buf + *f_pos, count))
+		ret = -EINVAL;
+	ret = count;
+	*f_pos += count;
+
+ out:
+	kfree(dev_buf);
+	return ret;
+
+ err_kmalloc:
+	return 0;
+}
+
+static const struct file_operations coh901318_debugfs_status_operations = {
+	.owner		= THIS_MODULE,
+	.open		= coh901318_debugfs_open,
+	.read		= coh901318_debugfs_read,
+};
+
+
+static int __init init_coh901318_debugfs(void)
+{
+
+	dma_dentry = debugfs_create_dir("dma", NULL);
+
+	(void) debugfs_create_file("status",
+				   S_IFREG | S_IRUGO,
+				   dma_dentry, NULL,
+				   &coh901318_debugfs_status_operations);
+	return 0;
+}
+
+static void __exit exit_coh901318_debugfs(void)
+{
+	debugfs_remove_recursive(dma_dentry);
+}
+
+module_init(init_coh901318_debugfs);
+module_exit(exit_coh901318_debugfs);
+#else
+
+#define COH901318_DEBUGFS_ASSIGN(x, y)
+
+#endif /* CONFIG_DEBUG_FS */
+
+static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct coh901318_chan, chan);
+}
+
+static inline dma_addr_t
+cohc_dev_addr(struct coh901318_chan *cohc)
+{
+	return cohc->base->platform->chan_conf[cohc->id].dev_addr;
+}
+
+static inline const struct coh901318_params *
+cohc_chan_param(struct coh901318_chan *cohc)
+{
+	return &cohc->base->platform->chan_conf[cohc->id].param;
+}
+
+static inline const struct coh_dma_channel *
+cohc_chan_conf(struct coh901318_chan *cohc)
+{
+	return &cohc->base->platform->chan_conf[cohc->id];
+}
+
+static void enable_powersave(struct coh901318_chan *cohc)
+{
+	unsigned long flags;
+	struct powersave *pm = &cohc->base->pm;
+
+	spin_lock_irqsave(&pm->lock, flags);
+
+	pm->started_channels &= ~(1ULL << cohc->id);
+
+	if (!pm->started_channels) {
+		/* DMA no longer intends to access memory */
+		cohc->base->platform->access_memory_state(cohc->base->dev,
+							  false);
+	}
+
+	spin_unlock_irqrestore(&pm->lock, flags);
+}
+static void disable_powersave(struct coh901318_chan *cohc)
+{
+	unsigned long flags;
+	struct powersave *pm = &cohc->base->pm;
+
+	spin_lock_irqsave(&pm->lock, flags);
+
+	if (!pm->started_channels) {
+		/* DMA intends to access memory */
+		cohc->base->platform->access_memory_state(cohc->base->dev,
+							  true);
+	}
+
+	pm->started_channels |= (1ULL << cohc->id);
+
+	spin_unlock_irqrestore(&pm->lock, flags);
+}
+
+static inline int coh901318_set_ctrl(struct coh901318_chan *cohc, u32 control)
+{
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	writel(control,
+	       virtbase + COH901318_CX_CTRL +
+	       COH901318_CX_CTRL_SPACING * channel);
+	return 0;
+}
+
+static inline int coh901318_set_conf(struct coh901318_chan *cohc, u32 conf)
+{
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	writel(conf,
+	       virtbase + COH901318_CX_CFG +
+	       COH901318_CX_CFG_SPACING*channel);
+	return 0;
+}
+
+
+static int coh901318_start(struct coh901318_chan *cohc)
+{
+	u32 val;
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	disable_powersave(cohc);
+
+	val = readl(virtbase + COH901318_CX_CFG +
+		    COH901318_CX_CFG_SPACING * channel);
+
+	/* Enable channel */
+	val |= COH901318_CX_CFG_CH_ENABLE;
+	writel(val, virtbase + COH901318_CX_CFG +
+	       COH901318_CX_CFG_SPACING * channel);
+
+	return 0;
+}
+
+static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
+				      struct coh901318_lli *data)
+{
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	BUG_ON(readl(virtbase + COH901318_CX_STAT +
+		     COH901318_CX_STAT_SPACING*channel) &
+	       COH901318_CX_STAT_ACTIVE);
+
+	writel(data->src_addr,
+	       virtbase + COH901318_CX_SRC_ADDR +
+	       COH901318_CX_SRC_ADDR_SPACING * channel);
+
+	writel(data->dst_addr, virtbase +
+	       COH901318_CX_DST_ADDR +
+	       COH901318_CX_DST_ADDR_SPACING * channel);
+
+	writel(data->link_addr, virtbase + COH901318_CX_LNK_ADDR +
+	       COH901318_CX_LNK_ADDR_SPACING * channel);
+
+	writel(data->control, virtbase + COH901318_CX_CTRL +
+	       COH901318_CX_CTRL_SPACING * channel);
+
+	return 0;
+}
+static dma_cookie_t
+coh901318_assign_cookie(struct coh901318_chan *cohc,
+			struct coh901318_desc *cohd)
+{
+	dma_cookie_t cookie = cohc->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	cohc->chan.cookie = cookie;
+	cohd->desc.cookie = cookie;
+
+	return cookie;
+}
+
+static struct coh901318_desc *
+coh901318_desc_get(struct coh901318_chan *cohc)
+{
+	struct coh901318_desc *desc;
+
+	if (list_empty(&cohc->free)) {
+		/* alloc new desc because we're out of used ones
+		 * TODO: alloc a pile of descs instead of just one,
+		 * avoid many small allocations.
+		 */
+		desc = kmalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
+		if (desc == NULL)
+			goto out;
+		INIT_LIST_HEAD(&desc->node);
+	} else {
+		/* Reuse an old desc. */
+		desc = list_first_entry(&cohc->free,
+					struct coh901318_desc,
+					node);
+		list_del(&desc->node);
+	}
+
+ out:
+	return desc;
+}
+
+static void
+coh901318_desc_free(struct coh901318_chan *cohc, struct coh901318_desc *cohd)
+{
+	list_add_tail(&cohd->node, &cohc->free);
+}
+
+/* call with irq lock held */
+static void
+coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
+{
+	list_add_tail(&desc->node, &cohc->active);
+
+	BUG_ON(cohc->pending_irqs != 0);
+
+	cohc->pending_irqs = desc->pending_irqs;
+}
+
+static struct coh901318_desc *
+coh901318_first_active_get(struct coh901318_chan *cohc)
+{
+	struct coh901318_desc *d;
+
+	if (list_empty(&cohc->active))
+		return NULL;
+
+	d = list_first_entry(&cohc->active,
+			     struct coh901318_desc,
+			     node);
+	return d;
+}
+
+static void
+coh901318_desc_remove(struct coh901318_desc *cohd)
+{
+	list_del(&cohd->node);
+}
+
+static void
+coh901318_desc_queue(struct coh901318_chan *cohc, struct coh901318_desc *desc)
+{
+	list_add_tail(&desc->node, &cohc->queue);
+}
+
+static struct coh901318_desc *
+coh901318_first_queued(struct coh901318_chan *cohc)
+{
+	struct coh901318_desc *d;
+
+	if (list_empty(&cohc->queue))
+		return NULL;
+
+	d = list_first_entry(&cohc->queue,
+			     struct coh901318_desc,
+			     node);
+	return d;
+}
+
+/*
+ * DMA start/stop controls
+ */
+u32 coh901318_get_bytes_left(struct dma_chan *chan)
+{
+	unsigned long flags;
+	u32 ret;
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* Read transfer count value */
+	ret = readl(cohc->base->virtbase +
+		    COH901318_CX_CTRL+COH901318_CX_CTRL_SPACING *
+		    cohc->id) & COH901318_CX_CTRL_TC_VALUE_MASK;
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(coh901318_get_bytes_left);
+
+
+/* Stops a transfer without losing data. Enables power save.
+   Use this function in conjunction with coh901318_continue(..)
+*/
+void coh901318_stop(struct dma_chan *chan)
+{
+	u32 val;
+	unsigned long flags;
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* Disable channel in HW */
+	val = readl(virtbase + COH901318_CX_CFG +
+		    COH901318_CX_CFG_SPACING * channel);
+
+	/* Stopping infinit transfer */
+	if ((val & COH901318_CX_CTRL_TC_ENABLE) == 0 &&
+	    (val & COH901318_CX_CFG_CH_ENABLE))
+		cohc->stopped = 1;
+
+
+	val &= ~COH901318_CX_CFG_CH_ENABLE;
+	/* Enable twice, HW bug work around */
+	writel(val, virtbase + COH901318_CX_CFG +
+	       COH901318_CX_CFG_SPACING * channel);
+	writel(val, virtbase + COH901318_CX_CFG +
+	       COH901318_CX_CFG_SPACING * channel);
+
+	/* Spin-wait for it to actually go inactive */
+	while (readl(virtbase + COH901318_CX_STAT+COH901318_CX_STAT_SPACING *
+		     channel) & COH901318_CX_STAT_ACTIVE)
+		cpu_relax();
+
+	/* Check if we stopped an active job */
+	if ((readl(virtbase + COH901318_CX_CTRL+COH901318_CX_CTRL_SPACING *
+		   channel) & COH901318_CX_CTRL_TC_VALUE_MASK) > 0)
+		cohc->stopped = 1;
+
+	enable_powersave(cohc);
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+}
+EXPORT_SYMBOL(coh901318_stop);
+
+/* Continues a transfer that has been stopped via 300_dma_stop(..).
+   Power save is handled.
+*/
+void coh901318_continue(struct dma_chan *chan)
+{
+	u32 val;
+	unsigned long flags;
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	int channel = cohc->id;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	disable_powersave(cohc);
+
+	if (cohc->stopped) {
+		/* Enable channel in HW */
+		val = readl(cohc->base->virtbase + COH901318_CX_CFG +
+			    COH901318_CX_CFG_SPACING * channel);
+
+		val |= COH901318_CX_CFG_CH_ENABLE;
+
+		writel(val, cohc->base->virtbase + COH901318_CX_CFG +
+		       COH901318_CX_CFG_SPACING*channel);
+
+		cohc->stopped = 0;
+	}
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+}
+EXPORT_SYMBOL(coh901318_continue);
+
+bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
+{
+	unsigned int ch_nr = (unsigned int) chan_id;
+
+	if (ch_nr == to_coh901318_chan(chan)->id)
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL(coh901318_filter_id);
+
+/*
+ * DMA channel allocation
+ */
+static int coh901318_config(struct coh901318_chan *cohc,
+			    struct coh901318_params *param)
+{
+	unsigned long flags;
+	const struct coh901318_params *p;
+	int channel = cohc->id;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	if (param)
+		p = param;
+	else
+		p = &cohc->base->platform->chan_conf[channel].param;
+
+	/* Clear any pending BE or TC interrupt */
+	if (channel < 32) {
+		writel(1 << channel, virtbase + COH901318_BE_INT_CLEAR1);
+		writel(1 << channel, virtbase + COH901318_TC_INT_CLEAR1);
+	} else {
+		writel(1 << (channel - 32), virtbase +
+		       COH901318_BE_INT_CLEAR2);
+		writel(1 << (channel - 32), virtbase +
+		       COH901318_TC_INT_CLEAR2);
+	}
+
+	coh901318_set_conf(cohc, p->config);
+	coh901318_set_ctrl(cohc, p->ctrl_lli_last);
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	return 0;
+}
+
+/* must lock when calling this function
+ * start queued jobs, if any
+ * TODO: start all queued jobs in one go
+ *
+ * Returns descriptor if queued job is started otherwise NULL.
+ * If the queue is empty NULL is returned.
+ */
+static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc)
+{
+	struct coh901318_desc *cohd_que;
+
+	/* start queued jobs, if any
+	 * TODO: transmit all queued jobs in one go
+	 */
+	cohd_que = coh901318_first_queued(cohc);
+
+	if (cohd_que != NULL) {
+		/* Remove from queue */
+		coh901318_desc_remove(cohd_que);
+		/* initiate DMA job */
+		cohc->busy = 1;
+
+		coh901318_desc_submit(cohc, cohd_que);
+
+		coh901318_prep_linked_list(cohc, cohd_que->data);
+
+		/* start dma job */
+		coh901318_start(cohc);
+
+	}
+
+	return cohd_que;
+}
+
+static void dma_tasklet(unsigned long data)
+{
+	struct coh901318_chan *cohc = (struct coh901318_chan *) data;
+	struct coh901318_desc *cohd_fin;
+	unsigned long flags;
+	dma_async_tx_callback callback;
+	void *callback_param;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* get first active entry from list */
+	cohd_fin = coh901318_first_active_get(cohc);
+
+	BUG_ON(cohd_fin->pending_irqs == 0);
+
+	if (cohd_fin == NULL)
+		goto err;
+
+	cohd_fin->pending_irqs--;
+	cohc->completed = cohd_fin->desc.cookie;
+
+	BUG_ON(cohc->nbr_active_done && cohd_fin == NULL);
+
+	if (cohc->nbr_active_done == 0)
+		return;
+
+	if (!cohd_fin->pending_irqs) {
+		/* release the lli allocation*/
+		coh901318_lli_free(&cohc->base->pool, &cohd_fin->data);
+	}
+
+	dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d pending_irqs %d"
+		 " nbr_active_done %ld\n", __func__,
+		 cohc->id, cohc->pending_irqs, cohc->nbr_active_done);
+
+	/* callback to client */
+	callback = cohd_fin->desc.callback;
+	callback_param = cohd_fin->desc.callback_param;
+
+	if (!cohd_fin->pending_irqs) {
+		coh901318_desc_remove(cohd_fin);
+
+		/* return desc to free-list */
+		coh901318_desc_free(cohc, cohd_fin);
+	}
+
+	if (cohc->nbr_active_done)
+		cohc->nbr_active_done--;
+
+	if (cohc->nbr_active_done) {
+		if (cohc_chan_conf(cohc)->priority_high)
+			tasklet_hi_schedule(&cohc->tasklet);
+		else
+			tasklet_schedule(&cohc->tasklet);
+	}
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	if (callback)
+		callback(callback_param);
+
+	return;
+
+ err:
+	spin_unlock_irqrestore(&cohc->lock, flags);
+	dev_err(COHC_2_DEV(cohc), "[%s] No active dma desc\n", __func__);
+}
+
+
+/* called from interrupt context */
+static void dma_tc_handle(struct coh901318_chan *cohc)
+{
+	BUG_ON(!cohc->allocated && (list_empty(&cohc->active) ||
+				    list_empty(&cohc->queue)));
+
+	if (!cohc->allocated)
+		return;
+
+	BUG_ON(cohc->pending_irqs == 0);
+
+	cohc->pending_irqs--;
+	cohc->nbr_active_done++;
+
+	if (cohc->pending_irqs == 0 && coh901318_queue_start(cohc) == NULL)
+		cohc->busy = 0;
+
+	BUG_ON(list_empty(&cohc->active));
+
+	if (cohc_chan_conf(cohc)->priority_high)
+		tasklet_hi_schedule(&cohc->tasklet);
+	else
+		tasklet_schedule(&cohc->tasklet);
+}
+
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+	u32 status1;
+	u32 status2;
+	int i;
+	int ch;
+	struct coh901318_base *base  = dev_id;
+	struct coh901318_chan *cohc;
+	void __iomem *virtbase = base->virtbase;
+
+	status1 = readl(virtbase + COH901318_INT_STATUS1);
+	status2 = readl(virtbase + COH901318_INT_STATUS2);
+
+	if (unlikely(status1 == 0 && status2 == 0)) {
+		dev_warn(base->dev, "spurious DMA IRQ from no channel!\n");
+		return IRQ_HANDLED;
+	}
+
+	/* TODO: consider handle IRQ in tasklet here to
+	 *       minimize interrupt latency */
+
+	/* Check the first 32 DMA channels for IRQ */
+	while (status1) {
+		/* Find first bit set, return as a number. */
+		i = ffs(status1) - 1;
+		ch = i;
+
+		cohc = &base->chans[ch];
+		spin_lock(&cohc->lock);
+
+		/* Mask off this bit */
+		status1 &= ~(1 << i);
+		/* Check the individual channel bits */
+		if (test_bit(i, virtbase + COH901318_BE_INT_STATUS1)) {
+			dev_crit(COHC_2_DEV(cohc),
+				 "DMA bus error on channel %d!\n", ch);
+			BUG_ON(1);
+			/* Clear BE interrupt */
+			__set_bit(i, virtbase + COH901318_BE_INT_CLEAR1);
+		} else {
+			/* Caused by TC, really? */
+			if (unlikely(!test_bit(i, virtbase +
+					       COH901318_TC_INT_STATUS1))) {
+				dev_warn(COHC_2_DEV(cohc),
+					 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
+				/* Clear TC interrupt */
+				BUG_ON(1);
+				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
+			} else {
+				/* Enable powersave if transfer has finished */
+				if (!(readl(virtbase + COH901318_CX_STAT +
+					    COH901318_CX_STAT_SPACING*ch) &
+				      COH901318_CX_STAT_ENABLED)) {
+					enable_powersave(cohc);
+				}
+
+				/* Must clear TC interrupt before calling
+				 * dma_tc_handle
+				 * in case tc_handle initate a new dma job
+				 */
+				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
+
+				dma_tc_handle(cohc);
+			}
+		}
+		spin_unlock(&cohc->lock);
+	}
+
+	/* Check the remaining 32 DMA channels for IRQ */
+	while (status2) {
+		/* Find first bit set, return as a number. */
+		i = ffs(status2) - 1;
+		ch = i + 32;
+		cohc = &base->chans[ch];
+		spin_lock(&cohc->lock);
+
+		/* Mask off this bit */
+		status2 &= ~(1 << i);
+		/* Check the individual channel bits */
+		if (test_bit(i, virtbase + COH901318_BE_INT_STATUS2)) {
+			dev_crit(COHC_2_DEV(cohc),
+				 "DMA bus error on channel %d!\n", ch);
+			/* Clear BE interrupt */
+			BUG_ON(1);
+			__set_bit(i, virtbase + COH901318_BE_INT_CLEAR2);
+		} else {
+			/* Caused by TC, really? */
+			if (unlikely(!test_bit(i, virtbase +
+					       COH901318_TC_INT_STATUS2))) {
+				dev_warn(COHC_2_DEV(cohc),
+					 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
+				/* Clear TC interrupt */
+				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
+				BUG_ON(1);
+			} else {
+				/* Enable powersave if transfer has finished */
+				if (!(readl(virtbase + COH901318_CX_STAT +
+					    COH901318_CX_STAT_SPACING*ch) &
+				      COH901318_CX_STAT_ENABLED)) {
+					enable_powersave(cohc);
+				}
+				/* Must clear TC interrupt before calling
+				 * dma_tc_handle
+				 * in case tc_handle initate a new dma job
+				 */
+				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
+
+				dma_tc_handle(cohc);
+			}
+		}
+		spin_unlock(&cohc->lock);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int coh901318_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct coh901318_chan	*cohc = to_coh901318_chan(chan);
+
+	dev_vdbg(COHC_2_DEV(cohc), "[%s] DMA channel %d\n",
+		 __func__, cohc->id);
+
+	if (chan->client_count > 1)
+		return -EBUSY;
+
+	coh901318_config(cohc, NULL);
+
+	cohc->allocated = 1;
+	cohc->completed = chan->cookie = 1;
+
+	return 1;
+}
+
+static void
+coh901318_free_chan_resources(struct dma_chan *chan)
+{
+	struct coh901318_chan	*cohc = to_coh901318_chan(chan);
+	int channel = cohc->id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* Disable HW */
+	writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CFG +
+	       COH901318_CX_CFG_SPACING*channel);
+	writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CTRL +
+	       COH901318_CX_CTRL_SPACING*channel);
+
+	cohc->allocated = 0;
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	chan->device->device_terminate_all(chan);
+}
+
+
+static dma_cookie_t
+coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct coh901318_desc *cohd = container_of(tx, struct coh901318_desc,
+						   desc);
+	struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	tx->cookie = coh901318_assign_cookie(cohc, cohd);
+
+	coh901318_desc_queue(cohc, cohd);
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+
+	return tx->cookie;
+}
+
+static struct dma_async_tx_descriptor *
+coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		      size_t size, unsigned long flags)
+{
+	struct coh901318_lli *data;
+	struct coh901318_desc *cohd;
+	unsigned long flg;
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	int lli_len;
+	u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
+
+	spin_lock_irqsave(&cohc->lock, flg);
+
+	dev_vdbg(COHC_2_DEV(cohc),
+		 "[%s] channel %d src 0x%x dest 0x%x size %d\n",
+		 __func__, cohc->id, src, dest, size);
+
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Trigger interrupt after last lli */
+		ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
+
+	lli_len = size >> MAX_DMA_PACKET_SIZE_SHIFT;
+	if ((lli_len << MAX_DMA_PACKET_SIZE_SHIFT) < size)
+		lli_len++;
+
+	data = coh901318_lli_alloc(&cohc->base->pool, lli_len);
+
+	if (data == NULL)
+		goto err;
+
+	cohd = coh901318_desc_get(cohc);
+	cohd->sg = NULL;
+	cohd->sg_len = 0;
+	cohd->data = data;
+
+	cohd->pending_irqs =
+		coh901318_lli_fill_memcpy(
+				&cohc->base->pool, data, src, size, dest,
+				cohc_chan_param(cohc)->ctrl_lli_chained,
+				ctrl_last);
+	cohd->flags = flags;
+
+	COH_DBG(coh901318_list_print(cohc, data));
+
+	dma_async_tx_descriptor_init(&cohd->desc, chan);
+
+	cohd->desc.tx_submit = coh901318_tx_submit;
+
+	spin_unlock_irqrestore(&cohc->lock, flg);
+
+	return &cohd->desc;
+ err:
+	spin_unlock_irqrestore(&cohc->lock, flg);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+			unsigned int sg_len, enum dma_data_direction direction,
+			unsigned long flags)
+{
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	struct coh901318_lli *data;
+	struct coh901318_desc *cohd;
+	struct scatterlist *sg;
+	int len = 0;
+	int size;
+	int i;
+	u32 ctrl_chained = cohc_chan_param(cohc)->ctrl_lli_chained;
+	u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
+	u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
+	unsigned long flg;
+
+	if (!sgl)
+		goto out;
+	if (sgl->length == 0)
+		goto out;
+
+	spin_lock_irqsave(&cohc->lock, flg);
+
+	dev_vdbg(COHC_2_DEV(cohc), "[%s] sg_len %d dir %d\n",
+		 __func__, sg_len, direction);
+
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Trigger interrupt after last lli */
+		ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
+
+	cohd = coh901318_desc_get(cohc);
+	cohd->sg = NULL;
+	cohd->sg_len = 0;
+	cohd->dir = direction;
+
+	if (direction == DMA_TO_DEVICE) {
+		u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
+			COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
+
+		ctrl_chained |= tx_flags;
+		ctrl_last |= tx_flags;
+		ctrl |= tx_flags;
+	} else if (direction == DMA_FROM_DEVICE) {
+		u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
+			COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
+
+		ctrl_chained |= rx_flags;
+		ctrl_last |= rx_flags;
+		ctrl |= rx_flags;
+	} else
+		goto err_direction;
+
+	dma_async_tx_descriptor_init(&cohd->desc, chan);
+
+	cohd->desc.tx_submit = coh901318_tx_submit;
+
+
+	/* The dma only supports transmitting packages up to
+	 * MAX_DMA_PACKET_SIZE. Calculate to total number of
+	 * dma elemts required to send the entire sg list
+	 */
+	for_each_sg(sgl, sg, sg_len, i) {
+		unsigned int factor;
+		size = sg_dma_len(sg);
+
+		if (size <= MAX_DMA_PACKET_SIZE) {
+			len++;
+			continue;
+		}
+
+		factor = size >> MAX_DMA_PACKET_SIZE_SHIFT;
+		if ((factor << MAX_DMA_PACKET_SIZE_SHIFT) < size)
+			factor++;
+
+		len += factor;
+	}
+
+	data = coh901318_lli_alloc(&cohc->base->pool, len);
+
+	if (data == NULL)
+		goto err_dma_alloc;
+
+	/* initiate allocated data list */
+	cohd->pending_irqs =
+		coh901318_lli_fill_sg(&cohc->base->pool, data, sgl, sg_len,
+				      cohc_dev_addr(cohc),
+				      ctrl_chained,
+				      ctrl,
+				      ctrl_last,
+				      direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
+	cohd->data = data;
+
+	cohd->flags = flags;
+
+	COH_DBG(coh901318_list_print(cohc, data));
+
+	spin_unlock_irqrestore(&cohc->lock, flg);
+
+	return &cohd->desc;
+ err_dma_alloc:
+ err_direction:
+	coh901318_desc_remove(cohd);
+	coh901318_desc_free(cohc, cohd);
+	spin_unlock_irqrestore(&cohc->lock, flg);
+ out:
+	return NULL;
+}
+
+static enum dma_status
+coh901318_is_tx_complete(struct dma_chan *chan,
+			 dma_cookie_t cookie, dma_cookie_t *done,
+			 dma_cookie_t *used)
+{
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	int ret;
+
+	last_complete = cohc->completed;
+	last_used = chan->cookie;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return ret;
+}
+
+static void
+coh901318_issue_pending(struct dma_chan *chan)
+{
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* Busy means that pending jobs are already being processed */
+	if (!cohc->busy)
+		coh901318_queue_start(cohc);
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+}
+
+static void
+coh901318_terminate_all(struct dma_chan *chan)
+{
+	unsigned long flags;
+	struct coh901318_chan *cohc = to_coh901318_chan(chan);
+	struct coh901318_desc *cohd;
+	void __iomem *virtbase = cohc->base->virtbase;
+
+	coh901318_stop(chan);
+
+	spin_lock_irqsave(&cohc->lock, flags);
+
+	/* Clear any pending BE or TC interrupt */
+	if (cohc->id < 32) {
+		writel(1 << cohc->id, virtbase + COH901318_BE_INT_CLEAR1);
+		writel(1 << cohc->id, virtbase + COH901318_TC_INT_CLEAR1);
+	} else {
+		writel(1 << (cohc->id - 32), virtbase +
+		       COH901318_BE_INT_CLEAR2);
+		writel(1 << (cohc->id - 32), virtbase +
+		       COH901318_TC_INT_CLEAR2);
+	}
+
+	enable_powersave(cohc);
+
+	while ((cohd = coh901318_first_active_get(cohc))) {
+		/* release the lli allocation*/
+		coh901318_lli_free(&cohc->base->pool, &cohd->data);
+
+		coh901318_desc_remove(cohd);
+
+		/* return desc to free-list */
+		coh901318_desc_free(cohc, cohd);
+	}
+
+	while ((cohd = coh901318_first_queued(cohc))) {
+		/* release the lli allocation*/
+		coh901318_lli_free(&cohc->base->pool, &cohd->data);
+
+		coh901318_desc_remove(cohd);
+
+		/* return desc to free-list */
+		coh901318_desc_free(cohc, cohd);
+	}
+
+
+	cohc->nbr_active_done = 0;
+	cohc->busy = 0;
+	cohc->pending_irqs = 0;
+
+	spin_unlock_irqrestore(&cohc->lock, flags);
+}
+void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
+			 struct coh901318_base *base)
+{
+	int chans_i;
+	int i = 0;
+	struct coh901318_chan *cohc;
+
+	INIT_LIST_HEAD(&dma->channels);
+
+	for (chans_i = 0; pick_chans[chans_i] != -1; chans_i += 2) {
+		for (i = pick_chans[chans_i]; i <= pick_chans[chans_i+1]; i++) {
+			cohc = &base->chans[i];
+
+			cohc->base = base;
+			cohc->chan.device = dma;
+			cohc->id = i;
+
+			/* TODO: do we really need this lock if only one
+			 * client is connected to each channel?
+			 */
+
+			spin_lock_init(&cohc->lock);
+
+			cohc->pending_irqs = 0;
+			cohc->nbr_active_done = 0;
+			cohc->busy = 0;
+			INIT_LIST_HEAD(&cohc->free);
+			INIT_LIST_HEAD(&cohc->active);
+			INIT_LIST_HEAD(&cohc->queue);
+
+			tasklet_init(&cohc->tasklet, dma_tasklet,
+				     (unsigned long) cohc);
+
+			list_add_tail(&cohc->chan.device_node,
+				      &dma->channels);
+		}
+	}
+}
+
+static int __init coh901318_probe(struct platform_device *pdev)
+{
+	int err = 0;
+	struct coh901318_platform *pdata;
+	struct coh901318_base *base;
+	int irq;
+	struct resource *io;
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!io)
+		goto err_get_resource;
+
+	/* Map DMA controller registers to virtual memory */
+	if (request_mem_region(io->start,
+			       resource_size(io),
+			       pdev->dev.driver->name) == NULL) {
+		err = -EBUSY;
+		goto err_request_mem;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		goto err_no_platformdata;
+
+	base = kmalloc(ALIGN(sizeof(struct coh901318_base), 4) +
+		       pdata->max_channels *
+		       sizeof(struct coh901318_chan),
+		       GFP_KERNEL);
+	if (!base)
+		goto err_alloc_coh_dma_channels;
+
+	base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4);
+
+	base->virtbase = ioremap(io->start, resource_size(io));
+	if (!base->virtbase) {
+		err = -ENOMEM;
+		goto err_no_ioremap;
+	}
+
+	base->dev = &pdev->dev;
+	base->platform = pdata;
+	spin_lock_init(&base->pm.lock);
+	base->pm.started_channels = 0;
+
+	COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base);
+
+	platform_set_drvdata(pdev, base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		goto err_no_irq;
+
+	err = request_irq(irq, dma_irq_handler, IRQF_DISABLED,
+			  "coh901318", base);
+	if (err) {
+		dev_crit(&pdev->dev,
+			 "Cannot allocate IRQ for DMA controller!\n");
+		goto err_request_irq;
+	}
+
+	err = coh901318_pool_create(&base->pool, &pdev->dev,
+				    sizeof(struct coh901318_lli),
+				    32);
+	if (err)
+		goto err_pool_create;
+
+	/* init channels for device transfers */
+	coh901318_base_init(&base->dma_slave,  base->platform->chans_slave,
+			    base);
+
+	dma_cap_zero(base->dma_slave.cap_mask);
+	dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask);
+
+	base->dma_slave.device_alloc_chan_resources = coh901318_alloc_chan_resources;
+	base->dma_slave.device_free_chan_resources = coh901318_free_chan_resources;
+	base->dma_slave.device_prep_slave_sg = coh901318_prep_slave_sg;
+	base->dma_slave.device_is_tx_complete = coh901318_is_tx_complete;
+	base->dma_slave.device_issue_pending = coh901318_issue_pending;
+	base->dma_slave.device_terminate_all = coh901318_terminate_all;
+	base->dma_slave.dev = &pdev->dev;
+
+	err = dma_async_device_register(&base->dma_slave);
+
+	if (err)
+		goto err_register_slave;
+
+	/* init channels for memcpy */
+	coh901318_base_init(&base->dma_memcpy, base->platform->chans_memcpy,
+			    base);
+
+	dma_cap_zero(base->dma_memcpy.cap_mask);
+	dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
+
+	base->dma_memcpy.device_alloc_chan_resources = coh901318_alloc_chan_resources;
+	base->dma_memcpy.device_free_chan_resources = coh901318_free_chan_resources;
+	base->dma_memcpy.device_prep_dma_memcpy = coh901318_prep_memcpy;
+	base->dma_memcpy.device_is_tx_complete = coh901318_is_tx_complete;
+	base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
+	base->dma_memcpy.device_terminate_all = coh901318_terminate_all;
+	base->dma_memcpy.dev = &pdev->dev;
+	err = dma_async_device_register(&base->dma_memcpy);
+
+	if (err)
+		goto err_register_memcpy;
+
+	dev_dbg(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
+		(u32) base->virtbase);
+
+	return err;
+
+ err_register_memcpy:
+	dma_async_device_unregister(&base->dma_slave);
+ err_register_slave:
+	coh901318_pool_destroy(&base->pool);
+ err_pool_create:
+	free_irq(platform_get_irq(pdev, 0), base);
+ err_request_irq:
+ err_no_irq:
+	iounmap(base->virtbase);
+ err_no_ioremap:
+	kfree(base);
+ err_alloc_coh_dma_channels:
+ err_no_platformdata:
+	release_mem_region(pdev->resource->start,
+			   resource_size(pdev->resource));
+ err_request_mem:
+ err_get_resource:
+	return err;
+}
+
+static int __exit coh901318_remove(struct platform_device *pdev)
+{
+	struct coh901318_base *base = platform_get_drvdata(pdev);
+
+	dma_async_device_unregister(&base->dma_memcpy);
+	dma_async_device_unregister(&base->dma_slave);
+	coh901318_pool_destroy(&base->pool);
+	free_irq(platform_get_irq(pdev, 0), base);
+	kfree(base);
+	iounmap(base->virtbase);
+	release_mem_region(pdev->resource->start,
+			   resource_size(pdev->resource));
+	return 0;
+}
+
+
+static struct platform_driver coh901318_driver = {
+	.remove = __exit_p(coh901318_remove),
+	.driver = {
+		.name	= "coh901318",
+	},
+};
+
+int __init coh901318_init(void)
+{
+	return platform_driver_probe(&coh901318_driver, coh901318_probe);
+}
+subsys_initcall(coh901318_init);
+
+void __exit coh901318_exit(void)
+{
+	platform_driver_unregister(&coh901318_driver);
+}
+module_exit(coh901318_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Per Friden");
diff --git a/drivers/dma/coh901318_lli.c b/drivers/dma/coh901318_lli.c
new file mode 100644
index 0000000..f5120f2
--- /dev/null
+++ b/drivers/dma/coh901318_lli.c
@@ -0,0 +1,318 @@
+/*
+ * driver/dma/coh901318_lli.c
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Support functions for handling lli for dma
+ * Author: Per Friden <per.friden@stericsson.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/dmapool.h>
+#include <linux/memory.h>
+#include <mach/coh901318.h>
+
+#include "coh901318_lli.h"
+
+#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
+#define DEBUGFS_POOL_COUNTER_RESET(pool) (pool->debugfs_pool_counter = 0)
+#define DEBUGFS_POOL_COUNTER_ADD(pool, add) (pool->debugfs_pool_counter += add)
+#else
+#define DEBUGFS_POOL_COUNTER_RESET(pool)
+#define DEBUGFS_POOL_COUNTER_ADD(pool, add)
+#endif
+
+static struct coh901318_lli *
+coh901318_lli_next(struct coh901318_lli *data)
+{
+	if (data == NULL || data->link_addr == 0)
+		return NULL;
+
+	return (struct coh901318_lli *) data->virt_link_addr;
+}
+
+int coh901318_pool_create(struct coh901318_pool *pool,
+			  struct device *dev,
+			  size_t size, size_t align)
+{
+	spin_lock_init(&pool->lock);
+	pool->dev = dev;
+	pool->dmapool = dma_pool_create("lli_pool", dev, size, align, 0);
+
+	DEBUGFS_POOL_COUNTER_RESET(pool);
+	return 0;
+}
+
+int coh901318_pool_destroy(struct coh901318_pool *pool)
+{
+
+	dma_pool_destroy(pool->dmapool);
+	return 0;
+}
+
+struct coh901318_lli *
+coh901318_lli_alloc(struct coh901318_pool *pool, unsigned int len)
+{
+	int i;
+	struct coh901318_lli *head;
+	struct coh901318_lli *lli;
+	struct coh901318_lli *lli_prev;
+	dma_addr_t phy;
+
+	if (len == 0)
+		goto err;
+
+	spin_lock(&pool->lock);
+
+	head = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy);
+
+	if (head == NULL)
+		goto err;
+
+	DEBUGFS_POOL_COUNTER_ADD(pool, 1);
+
+	lli = head;
+	lli->phy_this = phy;
+
+	for (i = 1; i < len; i++) {
+		lli_prev = lli;
+
+		lli = dma_pool_alloc(pool->dmapool, GFP_NOWAIT, &phy);
+
+		if (lli == NULL)
+			goto err_clean_up;
+
+		DEBUGFS_POOL_COUNTER_ADD(pool, 1);
+		lli->phy_this = phy;
+
+		lli_prev->link_addr = phy;
+		lli_prev->virt_link_addr = lli;
+	}
+
+	lli->link_addr = 0x00000000U;
+
+	spin_unlock(&pool->lock);
+
+	return head;
+
+ err:
+	spin_unlock(&pool->lock);
+	return NULL;
+
+ err_clean_up:
+	lli_prev->link_addr = 0x00000000U;
+	spin_unlock(&pool->lock);
+	coh901318_lli_free(pool, &head);
+	return NULL;
+}
+
+void coh901318_lli_free(struct coh901318_pool *pool,
+			struct coh901318_lli **lli)
+{
+	struct coh901318_lli *l;
+	struct coh901318_lli *next;
+
+	if (lli == NULL)
+		return;
+
+	l = *lli;
+
+	if (l == NULL)
+		return;
+
+	spin_lock(&pool->lock);
+
+	while (l->link_addr) {
+		next = l->virt_link_addr;
+		dma_pool_free(pool->dmapool, l, l->phy_this);
+		DEBUGFS_POOL_COUNTER_ADD(pool, -1);
+		l = next;
+	}
+	dma_pool_free(pool->dmapool, l, l->phy_this);
+	DEBUGFS_POOL_COUNTER_ADD(pool, -1);
+
+	spin_unlock(&pool->lock);
+	*lli = NULL;
+}
+
+int
+coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
+			  struct coh901318_lli *lli,
+			  dma_addr_t source, unsigned int size,
+			  dma_addr_t destination, u32 ctrl_chained,
+			  u32 ctrl_eom)
+{
+	int s = size;
+	dma_addr_t src = source;
+	dma_addr_t dst = destination;
+
+	lli->src_addr = src;
+	lli->dst_addr = dst;
+
+	while (lli->link_addr) {
+		lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE;
+		lli->src_addr = src;
+		lli->dst_addr = dst;
+
+		s -= MAX_DMA_PACKET_SIZE;
+		lli = coh901318_lli_next(lli);
+
+		src += MAX_DMA_PACKET_SIZE;
+		dst += MAX_DMA_PACKET_SIZE;
+	}
+
+	lli->control = ctrl_eom | s;
+	lli->src_addr = src;
+	lli->dst_addr = dst;
+
+	/* One irq per single transfer */
+	return 1;
+}
+
+int
+coh901318_lli_fill_single(struct coh901318_pool *pool,
+			  struct coh901318_lli *lli,
+			  dma_addr_t buf, unsigned int size,
+			  dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_eom,
+			  enum dma_data_direction dir)
+{
+	int s = size;
+	dma_addr_t src;
+	dma_addr_t dst;
+
+
+	if (dir == DMA_TO_DEVICE) {
+		src = buf;
+		dst = dev_addr;
+
+	} else if (dir == DMA_FROM_DEVICE) {
+
+		src = dev_addr;
+		dst = buf;
+	} else {
+		return -EINVAL;
+	}
+
+	while (lli->link_addr) {
+		size_t block_size = MAX_DMA_PACKET_SIZE;
+		lli->control = ctrl_chained | MAX_DMA_PACKET_SIZE;
+
+		/* If we are on the next-to-final block and there will
+		 * be less than half a DMA packet left for the last
+		 * block, then we want to make this block a little
+		 * smaller to balance the sizes. This is meant to
+		 * avoid too small transfers if the buffer size is
+		 * (MAX_DMA_PACKET_SIZE*N + 1) */
+		if (s < (MAX_DMA_PACKET_SIZE + MAX_DMA_PACKET_SIZE/2))
+			block_size = MAX_DMA_PACKET_SIZE/2;
+
+		s -= block_size;
+		lli->src_addr = src;
+		lli->dst_addr = dst;
+
+		lli = coh901318_lli_next(lli);
+
+		if (dir == DMA_TO_DEVICE)
+			src += block_size;
+		else if (dir == DMA_FROM_DEVICE)
+			dst += block_size;
+	}
+
+	lli->control = ctrl_eom | s;
+	lli->src_addr = src;
+	lli->dst_addr = dst;
+
+	/* One irq per single transfer */
+	return 1;
+}
+
+int
+coh901318_lli_fill_sg(struct coh901318_pool *pool,
+		      struct coh901318_lli *lli,
+		      struct scatterlist *sgl, unsigned int nents,
+		      dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl,
+		      u32 ctrl_last,
+		      enum dma_data_direction dir, u32 ctrl_irq_mask)
+{
+	int i;
+	struct scatterlist *sg;
+	u32 ctrl_sg;
+	dma_addr_t src = 0;
+	dma_addr_t dst = 0;
+	int nbr_of_irq = 0;
+	u32 bytes_to_transfer;
+	u32 elem_size;
+
+	if (lli == NULL)
+		goto err;
+
+	spin_lock(&pool->lock);
+
+	if (dir == DMA_TO_DEVICE)
+		dst = dev_addr;
+	else if (dir == DMA_FROM_DEVICE)
+		src = dev_addr;
+	else
+		goto err;
+
+	for_each_sg(sgl, sg, nents, i) {
+		if (sg_is_chain(sg)) {
+			/* sg continues to the next sg-element don't
+			 * send ctrl_finish until the last
+			 * sg-element in the chain
+			 */
+			ctrl_sg = ctrl_chained;
+		} else if (i == nents - 1)
+			ctrl_sg = ctrl_last;
+		else
+			ctrl_sg = ctrl ? ctrl : ctrl_last;
+
+
+		if ((ctrl_sg & ctrl_irq_mask))
+			nbr_of_irq++;
+
+		if (dir == DMA_TO_DEVICE)
+			/* increment source address */
+			src = sg_dma_address(sg);
+		else
+			/* increment destination address */
+			dst =  sg_dma_address(sg);
+
+		bytes_to_transfer = sg_dma_len(sg);
+
+		while (bytes_to_transfer) {
+			u32 val;
+
+			if (bytes_to_transfer > MAX_DMA_PACKET_SIZE) {
+				elem_size = MAX_DMA_PACKET_SIZE;
+				val = ctrl_chained;
+			} else {
+				elem_size = bytes_to_transfer;
+				val = ctrl_sg;
+			}
+
+			lli->control = val | elem_size;
+			lli->src_addr = src;
+			lli->dst_addr = dst;
+
+			if (dir == DMA_FROM_DEVICE)
+				dst += elem_size;
+			else
+				src += elem_size;
+
+			BUG_ON(lli->link_addr & 3);
+
+			bytes_to_transfer -= elem_size;
+			lli = coh901318_lli_next(lli);
+		}
+
+	}
+	spin_unlock(&pool->lock);
+
+	/* There can be many IRQs per sg transfer */
+	return nbr_of_irq;
+ err:
+	spin_unlock(&pool->lock);
+	return -EINVAL;
+}
diff --git a/drivers/dma/coh901318_lli.h b/drivers/dma/coh901318_lli.h
new file mode 100644
index 0000000..7bf713b
--- /dev/null
+++ b/drivers/dma/coh901318_lli.h
@@ -0,0 +1,124 @@
+/*
+ * driver/dma/coh901318_lli.h
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Support functions for handling lli for coh901318
+ * Author: Per Friden <per.friden@stericsson.com>
+ */
+
+#ifndef COH901318_LLI_H
+#define COH901318_LLI_H
+
+#include <mach/coh901318.h>
+
+struct device;
+
+struct coh901318_pool {
+	spinlock_t lock;
+	struct dma_pool *dmapool;
+	struct device *dev;
+
+#ifdef CONFIG_DEBUG_FS
+	int debugfs_pool_counter;
+#endif
+};
+
+struct device;
+/**
+ * coh901318_pool_create() - Creates an dma pool for lli:s
+ * @pool: pool handle
+ * @dev: dma device
+ * @lli_nbr: number of lli:s in the pool
+ * @algin: adress alignemtn of lli:s
+ * returns 0 on success otherwise none zero
+ */
+int coh901318_pool_create(struct coh901318_pool *pool,
+			  struct device *dev,
+			  size_t lli_nbr, size_t align);
+
+/**
+ * coh901318_pool_destroy() - Destroys the dma pool
+ * @pool: pool handle
+ * returns 0 on success otherwise none zero
+ */
+int coh901318_pool_destroy(struct coh901318_pool *pool);
+
+/**
+ * coh901318_lli_alloc() - Allocates a linked list
+ *
+ * @pool: pool handle
+ * @len: length to list
+ * return: none NULL if success otherwise NULL
+ */
+struct coh901318_lli *
+coh901318_lli_alloc(struct coh901318_pool *pool,
+		    unsigned int len);
+
+/**
+ * coh901318_lli_free() - Returns the linked list items to the pool
+ * @pool: pool handle
+ * @lli: reference to lli pointer to be freed
+ */
+void coh901318_lli_free(struct coh901318_pool *pool,
+			struct coh901318_lli **lli);
+
+/**
+ * coh901318_lli_fill_memcpy() - Prepares the lli:s for dma memcpy
+ * @pool: pool handle
+ * @lli: allocated lli
+ * @src: src address
+ * @size: transfer size
+ * @dst: destination address
+ * @ctrl_chained: ctrl for chained lli
+ * @ctrl_last: ctrl for the last lli
+ * returns number of CPU interrupts for the lli, negative on error.
+ */
+int
+coh901318_lli_fill_memcpy(struct coh901318_pool *pool,
+			  struct coh901318_lli *lli,
+			  dma_addr_t src, unsigned int size,
+			  dma_addr_t dst, u32 ctrl_chained, u32 ctrl_last);
+
+/**
+ * coh901318_lli_fill_single() - Prepares the lli:s for dma single transfer
+ * @pool: pool handle
+ * @lli: allocated lli
+ * @buf: transfer buffer
+ * @size: transfer size
+ * @dev_addr: address of periphal
+ * @ctrl_chained: ctrl for chained lli
+ * @ctrl_last: ctrl for the last lli
+ * @dir: direction of transfer (to or from device)
+ * returns number of CPU interrupts for the lli, negative on error.
+ */
+int
+coh901318_lli_fill_single(struct coh901318_pool *pool,
+			  struct coh901318_lli *lli,
+			  dma_addr_t buf, unsigned int size,
+			  dma_addr_t dev_addr, u32 ctrl_chained, u32 ctrl_last,
+			  enum dma_data_direction dir);
+
+/**
+ * coh901318_lli_fill_single() - Prepares the lli:s for dma scatter list transfer
+ * @pool: pool handle
+ * @lli: allocated lli
+ * @sg: scatter gather list
+ * @nents: number of entries in sg
+ * @dev_addr: address of periphal
+ * @ctrl_chained: ctrl for chained lli
+ * @ctrl: ctrl of middle lli
+ * @ctrl_last: ctrl for the last lli
+ * @dir: direction of transfer (to or from device)
+ * @ctrl_irq_mask: ctrl mask for CPU interrupt
+ * returns number of CPU interrupts for the lli, negative on error.
+ */
+int
+coh901318_lli_fill_sg(struct coh901318_pool *pool,
+		      struct coh901318_lli *lli,
+		      struct scatterlist *sg, unsigned int nents,
+		      dma_addr_t dev_addr, u32 ctrl_chained,
+		      u32 ctrl, u32 ctrl_last,
+		      enum dma_data_direction dir, u32 ctrl_irq_mask);
+
+#endif /* COH901318_LLI_H */
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index a32a4cf..8b90516 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -298,10 +298,6 @@
 
 		total_tests++;
 
-		len = dmatest_random() % test_buf_size + 1;
-		src_off = dmatest_random() % (test_buf_size - len + 1);
-		dst_off = dmatest_random() % (test_buf_size - len + 1);
-
 		/* honor alignment restrictions */
 		if (thread->type == DMA_MEMCPY)
 			align = dev->copy_align;
@@ -310,7 +306,19 @@
 		else if (thread->type == DMA_PQ)
 			align = dev->pq_align;
 
+		if (1 << align > test_buf_size) {
+			pr_err("%u-byte buffer too small for %d-byte alignment\n",
+			       test_buf_size, 1 << align);
+			break;
+		}
+
+		len = dmatest_random() % test_buf_size + 1;
 		len = (len >> align) << align;
+		if (!len)
+			len = 1 << align;
+		src_off = dmatest_random() % (test_buf_size - len + 1);
+		dst_off = dmatest_random() % (test_buf_size - len + 1);
+
 		src_off = (src_off >> align) << align;
 		dst_off = (dst_off >> align) << align;
 
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 645ca8d..ca6e6a0 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1470,7 +1470,7 @@
 		return -ENODEV;
 
 	if (!devm_request_mem_region(&pdev->dev, res->start,
-				res->end - res->start, pdev->name))
+				resource_size(res), pdev->name))
 		return -EBUSY;
 
 	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
@@ -1542,7 +1542,7 @@
 	iop_chan->device = adev;
 
 	iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
-					res->end - res->start);
+					resource_size(res));
 	if (!iop_chan->mmr_base) {
 		ret = -ENOMEM;
 		goto err_free_iop_chan;
diff --git a/drivers/dma/ppc4xx/Makefile b/drivers/dma/ppc4xx/Makefile
new file mode 100644
index 0000000..b3d259b
--- /dev/null
+++ b/drivers/dma/ppc4xx/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += adma.o
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
new file mode 100644
index 0000000..0a3478e
--- /dev/null
+++ b/drivers/dma/ppc4xx/adma.c
@@ -0,0 +1,5027 @@
+/*
+ * Copyright (C) 2006-2009 DENX Software Engineering.
+ *
+ * Author: Yuri Tikhonov <yur@emcraft.com>
+ *
+ * Further porting to arch/powerpc by
+ * 	Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This driver supports the asynchrounous DMA copy and RAID engines available
+ * on the AMCC PPC440SPe Processors.
+ * Based on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
+ * ADMA driver written by D.Williams.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+#include "adma.h"
+
+enum ppc_adma_init_code {
+	PPC_ADMA_INIT_OK = 0,
+	PPC_ADMA_INIT_MEMRES,
+	PPC_ADMA_INIT_MEMREG,
+	PPC_ADMA_INIT_ALLOC,
+	PPC_ADMA_INIT_COHERENT,
+	PPC_ADMA_INIT_CHANNEL,
+	PPC_ADMA_INIT_IRQ1,
+	PPC_ADMA_INIT_IRQ2,
+	PPC_ADMA_INIT_REGISTER
+};
+
+static char *ppc_adma_errors[] = {
+	[PPC_ADMA_INIT_OK] = "ok",
+	[PPC_ADMA_INIT_MEMRES] = "failed to get memory resource",
+	[PPC_ADMA_INIT_MEMREG] = "failed to request memory region",
+	[PPC_ADMA_INIT_ALLOC] = "failed to allocate memory for adev "
+				"structure",
+	[PPC_ADMA_INIT_COHERENT] = "failed to allocate coherent memory for "
+				   "hardware descriptors",
+	[PPC_ADMA_INIT_CHANNEL] = "failed to allocate memory for channel",
+	[PPC_ADMA_INIT_IRQ1] = "failed to request first irq",
+	[PPC_ADMA_INIT_IRQ2] = "failed to request second irq",
+	[PPC_ADMA_INIT_REGISTER] = "failed to register dma async device",
+};
+
+static enum ppc_adma_init_code
+ppc440spe_adma_devices[PPC440SPE_ADMA_ENGINES_NUM];
+
+struct ppc_dma_chan_ref {
+	struct dma_chan *chan;
+	struct list_head node;
+};
+
+/* The list of channels exported by ppc440spe ADMA */
+struct list_head
+ppc440spe_adma_chan_list = LIST_HEAD_INIT(ppc440spe_adma_chan_list);
+
+/* This flag is set when want to refetch the xor chain in the interrupt
+ * handler
+ */
+static u32 do_xor_refetch;
+
+/* Pointer to DMA0, DMA1 CP/CS FIFO */
+static void *ppc440spe_dma_fifo_buf;
+
+/* Pointers to last submitted to DMA0, DMA1 CDBs */
+static struct ppc440spe_adma_desc_slot *chan_last_sub[3];
+static struct ppc440spe_adma_desc_slot *chan_first_cdb[3];
+
+/* Pointer to last linked and submitted xor CB */
+static struct ppc440spe_adma_desc_slot *xor_last_linked;
+static struct ppc440spe_adma_desc_slot *xor_last_submit;
+
+/* This array is used in data-check operations for storing a pattern */
+static char ppc440spe_qword[16];
+
+static atomic_t ppc440spe_adma_err_irq_ref;
+static dcr_host_t ppc440spe_mq_dcr_host;
+static unsigned int ppc440spe_mq_dcr_len;
+
+/* Since RXOR operations use the common register (MQ0_CF2H) for setting-up
+ * the block size in transactions, then we do not allow to activate more than
+ * only one RXOR transactions simultaneously. So use this var to store
+ * the information about is RXOR currently active (PPC440SPE_RXOR_RUN bit is
+ * set) or not (PPC440SPE_RXOR_RUN is clear).
+ */
+static unsigned long ppc440spe_rxor_state;
+
+/* These are used in enable & check routines
+ */
+static u32 ppc440spe_r6_enabled;
+static struct ppc440spe_adma_chan *ppc440spe_r6_tchan;
+static struct completion ppc440spe_r6_test_comp;
+
+static int ppc440spe_adma_dma2rxor_prep_src(
+		struct ppc440spe_adma_desc_slot *desc,
+		struct ppc440spe_rxor *cursor, int index,
+		int src_cnt, u32 addr);
+static void ppc440spe_adma_dma2rxor_set_src(
+		struct ppc440spe_adma_desc_slot *desc,
+		int index, dma_addr_t addr);
+static void ppc440spe_adma_dma2rxor_set_mult(
+		struct ppc440spe_adma_desc_slot *desc,
+		int index, u8 mult);
+
+#ifdef ADMA_LL_DEBUG
+#define ADMA_LL_DBG(x) ({ if (1) x; 0; })
+#else
+#define ADMA_LL_DBG(x) ({ if (0) x; 0; })
+#endif
+
+static void print_cb(struct ppc440spe_adma_chan *chan, void *block)
+{
+	struct dma_cdb *cdb;
+	struct xor_cb *cb;
+	int i;
+
+	switch (chan->device->id) {
+	case 0:
+	case 1:
+		cdb = block;
+
+		pr_debug("CDB at %p [%d]:\n"
+			"\t attr 0x%02x opc 0x%02x cnt 0x%08x\n"
+			"\t sg1u 0x%08x sg1l 0x%08x\n"
+			"\t sg2u 0x%08x sg2l 0x%08x\n"
+			"\t sg3u 0x%08x sg3l 0x%08x\n",
+			cdb, chan->device->id,
+			cdb->attr, cdb->opc, le32_to_cpu(cdb->cnt),
+			le32_to_cpu(cdb->sg1u), le32_to_cpu(cdb->sg1l),
+			le32_to_cpu(cdb->sg2u), le32_to_cpu(cdb->sg2l),
+			le32_to_cpu(cdb->sg3u), le32_to_cpu(cdb->sg3l)
+		);
+		break;
+	case 2:
+		cb = block;
+
+		pr_debug("CB at %p [%d]:\n"
+			"\t cbc 0x%08x cbbc 0x%08x cbs 0x%08x\n"
+			"\t cbtah 0x%08x cbtal 0x%08x\n"
+			"\t cblah 0x%08x cblal 0x%08x\n",
+			cb, chan->device->id,
+			cb->cbc, cb->cbbc, cb->cbs,
+			cb->cbtah, cb->cbtal,
+			cb->cblah, cb->cblal);
+		for (i = 0; i < 16; i++) {
+			if (i && !cb->ops[i].h && !cb->ops[i].l)
+				continue;
+			pr_debug("\t ops[%2d]: h 0x%08x l 0x%08x\n",
+				i, cb->ops[i].h, cb->ops[i].l);
+		}
+		break;
+	}
+}
+
+static void print_cb_list(struct ppc440spe_adma_chan *chan,
+			  struct ppc440spe_adma_desc_slot *iter)
+{
+	for (; iter; iter = iter->hw_next)
+		print_cb(chan, iter->hw_desc);
+}
+
+static void prep_dma_xor_dbg(int id, dma_addr_t dst, dma_addr_t *src,
+			     unsigned int src_cnt)
+{
+	int i;
+
+	pr_debug("\n%s(%d):\nsrc: ", __func__, id);
+	for (i = 0; i < src_cnt; i++)
+		pr_debug("\t0x%016llx ", src[i]);
+	pr_debug("dst:\n\t0x%016llx\n", dst);
+}
+
+static void prep_dma_pq_dbg(int id, dma_addr_t *dst, dma_addr_t *src,
+			    unsigned int src_cnt)
+{
+	int i;
+
+	pr_debug("\n%s(%d):\nsrc: ", __func__, id);
+	for (i = 0; i < src_cnt; i++)
+		pr_debug("\t0x%016llx ", src[i]);
+	pr_debug("dst: ");
+	for (i = 0; i < 2; i++)
+		pr_debug("\t0x%016llx ", dst[i]);
+}
+
+static void prep_dma_pqzero_sum_dbg(int id, dma_addr_t *src,
+				    unsigned int src_cnt,
+				    const unsigned char *scf)
+{
+	int i;
+
+	pr_debug("\n%s(%d):\nsrc(coef): ", __func__, id);
+	if (scf) {
+		for (i = 0; i < src_cnt; i++)
+			pr_debug("\t0x%016llx(0x%02x) ", src[i], scf[i]);
+	} else {
+		for (i = 0; i < src_cnt; i++)
+			pr_debug("\t0x%016llx(no) ", src[i]);
+	}
+
+	pr_debug("dst: ");
+	for (i = 0; i < 2; i++)
+		pr_debug("\t0x%016llx ", src[src_cnt + i]);
+}
+
+/******************************************************************************
+ * Command (Descriptor) Blocks low-level routines
+ ******************************************************************************/
+/**
+ * ppc440spe_desc_init_interrupt - initialize the descriptor for INTERRUPT
+ * pseudo operation
+ */
+static void ppc440spe_desc_init_interrupt(struct ppc440spe_adma_desc_slot *desc,
+					  struct ppc440spe_adma_chan *chan)
+{
+	struct xor_cb *p;
+
+	switch (chan->device->id) {
+	case PPC440SPE_XOR_ID:
+		p = desc->hw_desc;
+		memset(desc->hw_desc, 0, sizeof(struct xor_cb));
+		/* NOP with Command Block Complete Enable */
+		p->cbc = XOR_CBCR_CBCE_BIT;
+		break;
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
+		/* NOP with interrupt */
+		set_bit(PPC440SPE_DESC_INT, &desc->flags);
+		break;
+	default:
+		printk(KERN_ERR "Unsupported id %d in %s\n", chan->device->id,
+				__func__);
+		break;
+	}
+}
+
+/**
+ * ppc440spe_desc_init_null_xor - initialize the descriptor for NULL XOR
+ * pseudo operation
+ */
+static void ppc440spe_desc_init_null_xor(struct ppc440spe_adma_desc_slot *desc)
+{
+	memset(desc->hw_desc, 0, sizeof(struct xor_cb));
+	desc->hw_next = NULL;
+	desc->src_cnt = 0;
+	desc->dst_cnt = 1;
+}
+
+/**
+ * ppc440spe_desc_init_xor - initialize the descriptor for XOR operation
+ */
+static void ppc440spe_desc_init_xor(struct ppc440spe_adma_desc_slot *desc,
+					 int src_cnt, unsigned long flags)
+{
+	struct xor_cb *hw_desc = desc->hw_desc;
+
+	memset(desc->hw_desc, 0, sizeof(struct xor_cb));
+	desc->hw_next = NULL;
+	desc->src_cnt = src_cnt;
+	desc->dst_cnt = 1;
+
+	hw_desc->cbc = XOR_CBCR_TGT_BIT | src_cnt;
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Enable interrupt on completion */
+		hw_desc->cbc |= XOR_CBCR_CBCE_BIT;
+}
+
+/**
+ * ppc440spe_desc_init_dma2pq - initialize the descriptor for PQ
+ * operation in DMA2 controller
+ */
+static void ppc440spe_desc_init_dma2pq(struct ppc440spe_adma_desc_slot *desc,
+		int dst_cnt, int src_cnt, unsigned long flags)
+{
+	struct xor_cb *hw_desc = desc->hw_desc;
+
+	memset(desc->hw_desc, 0, sizeof(struct xor_cb));
+	desc->hw_next = NULL;
+	desc->src_cnt = src_cnt;
+	desc->dst_cnt = dst_cnt;
+	memset(desc->reverse_flags, 0, sizeof(desc->reverse_flags));
+	desc->descs_per_op = 0;
+
+	hw_desc->cbc = XOR_CBCR_TGT_BIT;
+	if (flags & DMA_PREP_INTERRUPT)
+		/* Enable interrupt on completion */
+		hw_desc->cbc |= XOR_CBCR_CBCE_BIT;
+}
+
+#define DMA_CTRL_FLAGS_LAST	DMA_PREP_FENCE
+#define DMA_PREP_ZERO_P		(DMA_CTRL_FLAGS_LAST << 1)
+#define DMA_PREP_ZERO_Q		(DMA_PREP_ZERO_P << 1)
+
+/**
+ * ppc440spe_desc_init_dma01pq - initialize the descriptors for PQ operation
+ * with DMA0/1
+ */
+static void ppc440spe_desc_init_dma01pq(struct ppc440spe_adma_desc_slot *desc,
+				int dst_cnt, int src_cnt, unsigned long flags,
+				unsigned long op)
+{
+	struct dma_cdb *hw_desc;
+	struct ppc440spe_adma_desc_slot *iter;
+	u8 dopc;
+
+	/* Common initialization of a PQ descriptors chain */
+	set_bits(op, &desc->flags);
+	desc->src_cnt = src_cnt;
+	desc->dst_cnt = dst_cnt;
+
+	/* WXOR MULTICAST if both P and Q are being computed
+	 * MV_SG1_SG2 if Q only
+	 */
+	dopc = (desc->dst_cnt == DMA_DEST_MAX_NUM) ?
+		DMA_CDB_OPC_MULTICAST : DMA_CDB_OPC_MV_SG1_SG2;
+
+	list_for_each_entry(iter, &desc->group_list, chain_node) {
+		hw_desc = iter->hw_desc;
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+
+		if (likely(!list_is_last(&iter->chain_node,
+				&desc->group_list))) {
+			/* set 'next' pointer */
+			iter->hw_next = list_entry(iter->chain_node.next,
+				struct ppc440spe_adma_desc_slot, chain_node);
+			clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+		} else {
+			/* this is the last descriptor.
+			 * this slot will be pasted from ADMA level
+			 * each time it wants to configure parameters
+			 * of the transaction (src, dst, ...)
+			 */
+			iter->hw_next = NULL;
+			if (flags & DMA_PREP_INTERRUPT)
+				set_bit(PPC440SPE_DESC_INT, &iter->flags);
+			else
+				clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+		}
+	}
+
+	/* Set OPS depending on WXOR/RXOR type of operation */
+	if (!test_bit(PPC440SPE_DESC_RXOR, &desc->flags)) {
+		/* This is a WXOR only chain:
+		 * - first descriptors are for zeroing destinations
+		 *   if PPC440SPE_ZERO_P/Q set;
+		 * - descriptors remained are for GF-XOR operations.
+		 */
+		iter = list_first_entry(&desc->group_list,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+
+		if (test_bit(PPC440SPE_ZERO_P, &desc->flags)) {
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+			iter = list_first_entry(&iter->chain_node,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		}
+
+		if (test_bit(PPC440SPE_ZERO_Q, &desc->flags)) {
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+			iter = list_first_entry(&iter->chain_node,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		}
+
+		list_for_each_entry_from(iter, &desc->group_list, chain_node) {
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = dopc;
+		}
+	} else {
+		/* This is either RXOR-only or mixed RXOR/WXOR */
+
+		/* The first 1 or 2 slots in chain are always RXOR,
+		 * if need to calculate P & Q, then there are two
+		 * RXOR slots; if only P or only Q, then there is one
+		 */
+		iter = list_first_entry(&desc->group_list,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+
+		if (desc->dst_cnt == DMA_DEST_MAX_NUM) {
+			iter = list_first_entry(&iter->chain_node,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+		}
+
+		/* The remaining descs (if any) are WXORs */
+		if (test_bit(PPC440SPE_DESC_WXOR, &desc->flags)) {
+			iter = list_first_entry(&iter->chain_node,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			list_for_each_entry_from(iter, &desc->group_list,
+						chain_node) {
+				hw_desc = iter->hw_desc;
+				hw_desc->opc = dopc;
+			}
+		}
+	}
+}
+
+/**
+ * ppc440spe_desc_init_dma01pqzero_sum - initialize the descriptor
+ * for PQ_ZERO_SUM operation
+ */
+static void ppc440spe_desc_init_dma01pqzero_sum(
+				struct ppc440spe_adma_desc_slot *desc,
+				int dst_cnt, int src_cnt)
+{
+	struct dma_cdb *hw_desc;
+	struct ppc440spe_adma_desc_slot *iter;
+	int i = 0;
+	u8 dopc = (dst_cnt == 2) ? DMA_CDB_OPC_MULTICAST :
+				   DMA_CDB_OPC_MV_SG1_SG2;
+	/*
+	 * Initialize starting from 2nd or 3rd descriptor dependent
+	 * on dst_cnt. First one or two slots are for cloning P
+	 * and/or Q to chan->pdest and/or chan->qdest as we have
+	 * to preserve original P/Q.
+	 */
+	iter = list_first_entry(&desc->group_list,
+				struct ppc440spe_adma_desc_slot, chain_node);
+	iter = list_entry(iter->chain_node.next,
+			  struct ppc440spe_adma_desc_slot, chain_node);
+
+	if (dst_cnt > 1) {
+		iter = list_entry(iter->chain_node.next,
+				  struct ppc440spe_adma_desc_slot, chain_node);
+	}
+	/* initialize each source descriptor in chain */
+	list_for_each_entry_from(iter, &desc->group_list, chain_node) {
+		hw_desc = iter->hw_desc;
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		iter->src_cnt = 0;
+		iter->dst_cnt = 0;
+
+		/* This is a ZERO_SUM operation:
+		 * - <src_cnt> descriptors starting from 2nd or 3rd
+		 *   descriptor are for GF-XOR operations;
+		 * - remaining <dst_cnt> descriptors are for checking the result
+		 */
+		if (i++ < src_cnt)
+			/* MV_SG1_SG2 if only Q is being verified
+			 * MULTICAST if both P and Q are being verified
+			 */
+			hw_desc->opc = dopc;
+		else
+			/* DMA_CDB_OPC_DCHECK128 operation */
+			hw_desc->opc = DMA_CDB_OPC_DCHECK128;
+
+		if (likely(!list_is_last(&iter->chain_node,
+					 &desc->group_list))) {
+			/* set 'next' pointer */
+			iter->hw_next = list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+		} else {
+			/* this is the last descriptor.
+			 * this slot will be pasted from ADMA level
+			 * each time it wants to configure parameters
+			 * of the transaction (src, dst, ...)
+			 */
+			iter->hw_next = NULL;
+			/* always enable interrupt generation since we get
+			 * the status of pqzero from the handler
+			 */
+			set_bit(PPC440SPE_DESC_INT, &iter->flags);
+		}
+	}
+	desc->src_cnt = src_cnt;
+	desc->dst_cnt = dst_cnt;
+}
+
+/**
+ * ppc440spe_desc_init_memcpy - initialize the descriptor for MEMCPY operation
+ */
+static void ppc440spe_desc_init_memcpy(struct ppc440spe_adma_desc_slot *desc,
+					unsigned long flags)
+{
+	struct dma_cdb *hw_desc = desc->hw_desc;
+
+	memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
+	desc->hw_next = NULL;
+	desc->src_cnt = 1;
+	desc->dst_cnt = 1;
+
+	if (flags & DMA_PREP_INTERRUPT)
+		set_bit(PPC440SPE_DESC_INT, &desc->flags);
+	else
+		clear_bit(PPC440SPE_DESC_INT, &desc->flags);
+
+	hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+}
+
+/**
+ * ppc440spe_desc_init_memset - initialize the descriptor for MEMSET operation
+ */
+static void ppc440spe_desc_init_memset(struct ppc440spe_adma_desc_slot *desc,
+					int value, unsigned long flags)
+{
+	struct dma_cdb *hw_desc = desc->hw_desc;
+
+	memset(desc->hw_desc, 0, sizeof(struct dma_cdb));
+	desc->hw_next = NULL;
+	desc->src_cnt = 1;
+	desc->dst_cnt = 1;
+
+	if (flags & DMA_PREP_INTERRUPT)
+		set_bit(PPC440SPE_DESC_INT, &desc->flags);
+	else
+		clear_bit(PPC440SPE_DESC_INT, &desc->flags);
+
+	hw_desc->sg1u = hw_desc->sg1l = cpu_to_le32((u32)value);
+	hw_desc->sg3u = hw_desc->sg3l = cpu_to_le32((u32)value);
+	hw_desc->opc = DMA_CDB_OPC_DFILL128;
+}
+
+/**
+ * ppc440spe_desc_set_src_addr - set source address into the descriptor
+ */
+static void ppc440spe_desc_set_src_addr(struct ppc440spe_adma_desc_slot *desc,
+					struct ppc440spe_adma_chan *chan,
+					int src_idx, dma_addr_t addrh,
+					dma_addr_t addrl)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+	phys_addr_t addr64, tmplow, tmphi;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		if (!addrh) {
+			addr64 = addrl;
+			tmphi = (addr64 >> 32);
+			tmplow = (addr64 & 0xFFFFFFFF);
+		} else {
+			tmphi = addrh;
+			tmplow = addrl;
+		}
+		dma_hw_desc = desc->hw_desc;
+		dma_hw_desc->sg1l = cpu_to_le32((u32)tmplow);
+		dma_hw_desc->sg1u |= cpu_to_le32((u32)tmphi);
+		break;
+	case PPC440SPE_XOR_ID:
+		xor_hw_desc = desc->hw_desc;
+		xor_hw_desc->ops[src_idx].l = addrl;
+		xor_hw_desc->ops[src_idx].h |= addrh;
+		break;
+	}
+}
+
+/**
+ * ppc440spe_desc_set_src_mult - set source address mult into the descriptor
+ */
+static void ppc440spe_desc_set_src_mult(struct ppc440spe_adma_desc_slot *desc,
+			struct ppc440spe_adma_chan *chan, u32 mult_index,
+			int sg_index, unsigned char mult_value)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+	u32 *psgu;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+
+		switch (sg_index) {
+		/* for RXOR operations set multiplier
+		 * into source cued address
+		 */
+		case DMA_CDB_SG_SRC:
+			psgu = &dma_hw_desc->sg1u;
+			break;
+		/* for WXOR operations set multiplier
+		 * into destination cued address(es)
+		 */
+		case DMA_CDB_SG_DST1:
+			psgu = &dma_hw_desc->sg2u;
+			break;
+		case DMA_CDB_SG_DST2:
+			psgu = &dma_hw_desc->sg3u;
+			break;
+		default:
+			BUG();
+		}
+
+		*psgu |= cpu_to_le32(mult_value << mult_index);
+		break;
+	case PPC440SPE_XOR_ID:
+		xor_hw_desc = desc->hw_desc;
+		break;
+	default:
+		BUG();
+	}
+}
+
+/**
+ * ppc440spe_desc_set_dest_addr - set destination address into the descriptor
+ */
+static void ppc440spe_desc_set_dest_addr(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan,
+				dma_addr_t addrh, dma_addr_t addrl,
+				u32 dst_idx)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+	phys_addr_t addr64, tmphi, tmplow;
+	u32 *psgu, *psgl;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		if (!addrh) {
+			addr64 = addrl;
+			tmphi = (addr64 >> 32);
+			tmplow = (addr64 & 0xFFFFFFFF);
+		} else {
+			tmphi = addrh;
+			tmplow = addrl;
+		}
+		dma_hw_desc = desc->hw_desc;
+
+		psgu = dst_idx ? &dma_hw_desc->sg3u : &dma_hw_desc->sg2u;
+		psgl = dst_idx ? &dma_hw_desc->sg3l : &dma_hw_desc->sg2l;
+
+		*psgl = cpu_to_le32((u32)tmplow);
+		*psgu |= cpu_to_le32((u32)tmphi);
+		break;
+	case PPC440SPE_XOR_ID:
+		xor_hw_desc = desc->hw_desc;
+		xor_hw_desc->cbtal = addrl;
+		xor_hw_desc->cbtah |= addrh;
+		break;
+	}
+}
+
+/**
+ * ppc440spe_desc_set_byte_count - set number of data bytes involved
+ * into the operation
+ */
+static void ppc440spe_desc_set_byte_count(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan,
+				u32 byte_count)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+		dma_hw_desc->cnt = cpu_to_le32(byte_count);
+		break;
+	case PPC440SPE_XOR_ID:
+		xor_hw_desc = desc->hw_desc;
+		xor_hw_desc->cbbc = byte_count;
+		break;
+	}
+}
+
+/**
+ * ppc440spe_desc_set_rxor_block_size - set RXOR block size
+ */
+static inline void ppc440spe_desc_set_rxor_block_size(u32 byte_count)
+{
+	/* assume that byte_count is aligned on the 512-boundary;
+	 * thus write it directly to the register (bits 23:31 are
+	 * reserved there).
+	 */
+	dcr_write(ppc440spe_mq_dcr_host, DCRN_MQ0_CF2H, byte_count);
+}
+
+/**
+ * ppc440spe_desc_set_dcheck - set CHECK pattern
+ */
+static void ppc440spe_desc_set_dcheck(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan, u8 *qword)
+{
+	struct dma_cdb *dma_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+		iowrite32(qword[0], &dma_hw_desc->sg3l);
+		iowrite32(qword[4], &dma_hw_desc->sg3u);
+		iowrite32(qword[8], &dma_hw_desc->sg2l);
+		iowrite32(qword[12], &dma_hw_desc->sg2u);
+		break;
+	default:
+		BUG();
+	}
+}
+
+/**
+ * ppc440spe_xor_set_link - set link address in xor CB
+ */
+static void ppc440spe_xor_set_link(struct ppc440spe_adma_desc_slot *prev_desc,
+				struct ppc440spe_adma_desc_slot *next_desc)
+{
+	struct xor_cb *xor_hw_desc = prev_desc->hw_desc;
+
+	if (unlikely(!next_desc || !(next_desc->phys))) {
+		printk(KERN_ERR "%s: next_desc=0x%p; next_desc->phys=0x%llx\n",
+			__func__, next_desc,
+			next_desc ? next_desc->phys : 0);
+		BUG();
+	}
+
+	xor_hw_desc->cbs = 0;
+	xor_hw_desc->cblal = next_desc->phys;
+	xor_hw_desc->cblah = 0;
+	xor_hw_desc->cbc |= XOR_CBCR_LNK_BIT;
+}
+
+/**
+ * ppc440spe_desc_set_link - set the address of descriptor following this
+ * descriptor in chain
+ */
+static void ppc440spe_desc_set_link(struct ppc440spe_adma_chan *chan,
+				struct ppc440spe_adma_desc_slot *prev_desc,
+				struct ppc440spe_adma_desc_slot *next_desc)
+{
+	unsigned long flags;
+	struct ppc440spe_adma_desc_slot *tail = next_desc;
+
+	if (unlikely(!prev_desc || !next_desc ||
+		(prev_desc->hw_next && prev_desc->hw_next != next_desc))) {
+		/* If previous next is overwritten something is wrong.
+		 * though we may refetch from append to initiate list
+		 * processing; in this case - it's ok.
+		 */
+		printk(KERN_ERR "%s: prev_desc=0x%p; next_desc=0x%p; "
+			"prev->hw_next=0x%p\n", __func__, prev_desc,
+			next_desc, prev_desc ? prev_desc->hw_next : 0);
+		BUG();
+	}
+
+	local_irq_save(flags);
+
+	/* do s/w chaining both for DMA and XOR descriptors */
+	prev_desc->hw_next = next_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		break;
+	case PPC440SPE_XOR_ID:
+		/* bind descriptor to the chain */
+		while (tail->hw_next)
+			tail = tail->hw_next;
+		xor_last_linked = tail;
+
+		if (prev_desc == xor_last_submit)
+			/* do not link to the last submitted CB */
+			break;
+		ppc440spe_xor_set_link(prev_desc, next_desc);
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+/**
+ * ppc440spe_desc_get_src_addr - extract the source address from the descriptor
+ */
+static u32 ppc440spe_desc_get_src_addr(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan, int src_idx)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+		/* May have 0, 1, 2, or 3 sources */
+		switch (dma_hw_desc->opc) {
+		case DMA_CDB_OPC_NO_OP:
+		case DMA_CDB_OPC_DFILL128:
+			return 0;
+		case DMA_CDB_OPC_DCHECK128:
+			if (unlikely(src_idx)) {
+				printk(KERN_ERR "%s: try to get %d source for"
+				    " DCHECK128\n", __func__, src_idx);
+				BUG();
+			}
+			return le32_to_cpu(dma_hw_desc->sg1l);
+		case DMA_CDB_OPC_MULTICAST:
+		case DMA_CDB_OPC_MV_SG1_SG2:
+			if (unlikely(src_idx > 2)) {
+				printk(KERN_ERR "%s: try to get %d source from"
+				    " DMA descr\n", __func__, src_idx);
+				BUG();
+			}
+			if (src_idx) {
+				if (le32_to_cpu(dma_hw_desc->sg1u) &
+				    DMA_CUED_XOR_WIN_MSK) {
+					u8 region;
+
+					if (src_idx == 1)
+						return le32_to_cpu(
+						    dma_hw_desc->sg1l) +
+							desc->unmap_len;
+
+					region = (le32_to_cpu(
+					    dma_hw_desc->sg1u)) >>
+						DMA_CUED_REGION_OFF;
+
+					region &= DMA_CUED_REGION_MSK;
+					switch (region) {
+					case DMA_RXOR123:
+						return le32_to_cpu(
+						    dma_hw_desc->sg1l) +
+							(desc->unmap_len << 1);
+					case DMA_RXOR124:
+						return le32_to_cpu(
+						    dma_hw_desc->sg1l) +
+							(desc->unmap_len * 3);
+					case DMA_RXOR125:
+						return le32_to_cpu(
+						    dma_hw_desc->sg1l) +
+							(desc->unmap_len << 2);
+					default:
+						printk(KERN_ERR
+						    "%s: try to"
+						    " get src3 for region %02x"
+						    "PPC440SPE_DESC_RXOR12?\n",
+						    __func__, region);
+						BUG();
+					}
+				} else {
+					printk(KERN_ERR
+						"%s: try to get %d"
+						" source for non-cued descr\n",
+						__func__, src_idx);
+					BUG();
+				}
+			}
+			return le32_to_cpu(dma_hw_desc->sg1l);
+		default:
+			printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
+				__func__, dma_hw_desc->opc);
+			BUG();
+		}
+		return le32_to_cpu(dma_hw_desc->sg1l);
+	case PPC440SPE_XOR_ID:
+		/* May have up to 16 sources */
+		xor_hw_desc = desc->hw_desc;
+		return xor_hw_desc->ops[src_idx].l;
+	}
+	return 0;
+}
+
+/**
+ * ppc440spe_desc_get_dest_addr - extract the destination address from the
+ * descriptor
+ */
+static u32 ppc440spe_desc_get_dest_addr(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan, int idx)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+
+		if (likely(!idx))
+			return le32_to_cpu(dma_hw_desc->sg2l);
+		return le32_to_cpu(dma_hw_desc->sg3l);
+	case PPC440SPE_XOR_ID:
+		xor_hw_desc = desc->hw_desc;
+		return xor_hw_desc->cbtal;
+	}
+	return 0;
+}
+
+/**
+ * ppc440spe_desc_get_src_num - extract the number of source addresses from
+ * the descriptor
+ */
+static u32 ppc440spe_desc_get_src_num(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan)
+{
+	struct dma_cdb *dma_hw_desc;
+	struct xor_cb *xor_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_hw_desc = desc->hw_desc;
+
+		switch (dma_hw_desc->opc) {
+		case DMA_CDB_OPC_NO_OP:
+		case DMA_CDB_OPC_DFILL128:
+			return 0;
+		case DMA_CDB_OPC_DCHECK128:
+			return 1;
+		case DMA_CDB_OPC_MV_SG1_SG2:
+		case DMA_CDB_OPC_MULTICAST:
+			/*
+			 * Only for RXOR operations we have more than
+			 * one source
+			 */
+			if (le32_to_cpu(dma_hw_desc->sg1u) &
+			    DMA_CUED_XOR_WIN_MSK) {
+				/* RXOR op, there are 2 or 3 sources */
+				if (((le32_to_cpu(dma_hw_desc->sg1u) >>
+				    DMA_CUED_REGION_OFF) &
+				      DMA_CUED_REGION_MSK) == DMA_RXOR12) {
+					/* RXOR 1-2 */
+					return 2;
+				} else {
+					/* RXOR 1-2-3/1-2-4/1-2-5 */
+					return 3;
+				}
+			}
+			return 1;
+		default:
+			printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
+				__func__, dma_hw_desc->opc);
+			BUG();
+		}
+	case PPC440SPE_XOR_ID:
+		/* up to 16 sources */
+		xor_hw_desc = desc->hw_desc;
+		return xor_hw_desc->cbc & XOR_CDCR_OAC_MSK;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+/**
+ * ppc440spe_desc_get_dst_num - get the number of destination addresses in
+ * this descriptor
+ */
+static u32 ppc440spe_desc_get_dst_num(struct ppc440spe_adma_desc_slot *desc,
+				struct ppc440spe_adma_chan *chan)
+{
+	struct dma_cdb *dma_hw_desc;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* May be 1 or 2 destinations */
+		dma_hw_desc = desc->hw_desc;
+		switch (dma_hw_desc->opc) {
+		case DMA_CDB_OPC_NO_OP:
+		case DMA_CDB_OPC_DCHECK128:
+			return 0;
+		case DMA_CDB_OPC_MV_SG1_SG2:
+		case DMA_CDB_OPC_DFILL128:
+			return 1;
+		case DMA_CDB_OPC_MULTICAST:
+			if (desc->dst_cnt == 2)
+				return 2;
+			else
+				return 1;
+		default:
+			printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
+				__func__, dma_hw_desc->opc);
+			BUG();
+		}
+	case PPC440SPE_XOR_ID:
+		/* Always only 1 destination */
+		return 1;
+	default:
+		BUG();
+	}
+	return 0;
+}
+
+/**
+ * ppc440spe_desc_get_link - get the address of the descriptor that
+ * follows this one
+ */
+static inline u32 ppc440spe_desc_get_link(struct ppc440spe_adma_desc_slot *desc,
+					struct ppc440spe_adma_chan *chan)
+{
+	if (!desc->hw_next)
+		return 0;
+
+	return desc->hw_next->phys;
+}
+
+/**
+ * ppc440spe_desc_is_aligned - check alignment
+ */
+static inline int ppc440spe_desc_is_aligned(
+	struct ppc440spe_adma_desc_slot *desc, int num_slots)
+{
+	return (desc->idx & (num_slots - 1)) ? 0 : 1;
+}
+
+/**
+ * ppc440spe_chan_xor_slot_count - get the number of slots necessary for
+ * XOR operation
+ */
+static int ppc440spe_chan_xor_slot_count(size_t len, int src_cnt,
+			int *slots_per_op)
+{
+	int slot_cnt;
+
+	/* each XOR descriptor provides up to 16 source operands */
+	slot_cnt = *slots_per_op = (src_cnt + XOR_MAX_OPS - 1)/XOR_MAX_OPS;
+
+	if (likely(len <= PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT))
+		return slot_cnt;
+
+	printk(KERN_ERR "%s: len %d > max %d !!\n",
+		__func__, len, PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT);
+	BUG();
+	return slot_cnt;
+}
+
+/**
+ * ppc440spe_dma2_pq_slot_count - get the number of slots necessary for
+ * DMA2 PQ operation
+ */
+static int ppc440spe_dma2_pq_slot_count(dma_addr_t *srcs,
+		int src_cnt, size_t len)
+{
+	signed long long order = 0;
+	int state = 0;
+	int addr_count = 0;
+	int i;
+	for (i = 1; i < src_cnt; i++) {
+		dma_addr_t cur_addr = srcs[i];
+		dma_addr_t old_addr = srcs[i-1];
+		switch (state) {
+		case 0:
+			if (cur_addr == old_addr + len) {
+				/* direct RXOR */
+				order = 1;
+				state = 1;
+				if (i == src_cnt-1)
+					addr_count++;
+			} else if (old_addr == cur_addr + len) {
+				/* reverse RXOR */
+				order = -1;
+				state = 1;
+				if (i == src_cnt-1)
+					addr_count++;
+			} else {
+				state = 3;
+			}
+			break;
+		case 1:
+			if (i == src_cnt-2 || (order == -1
+				&& cur_addr != old_addr - len)) {
+				order = 0;
+				state = 0;
+				addr_count++;
+			} else if (cur_addr == old_addr + len*order) {
+				state = 2;
+				if (i == src_cnt-1)
+					addr_count++;
+			} else if (cur_addr == old_addr + 2*len) {
+				state = 2;
+				if (i == src_cnt-1)
+					addr_count++;
+			} else if (cur_addr == old_addr + 3*len) {
+				state = 2;
+				if (i == src_cnt-1)
+					addr_count++;
+			} else {
+				order = 0;
+				state = 0;
+				addr_count++;
+			}
+			break;
+		case 2:
+			order = 0;
+			state = 0;
+			addr_count++;
+				break;
+		}
+		if (state == 3)
+			break;
+	}
+	if (src_cnt <= 1 || (state != 1 && state != 2)) {
+		pr_err("%s: src_cnt=%d, state=%d, addr_count=%d, order=%lld\n",
+			__func__, src_cnt, state, addr_count, order);
+		for (i = 0; i < src_cnt; i++)
+			pr_err("\t[%d] 0x%llx \n", i, srcs[i]);
+		BUG();
+	}
+
+	return (addr_count + XOR_MAX_OPS - 1) / XOR_MAX_OPS;
+}
+
+
+/******************************************************************************
+ * ADMA channel low-level routines
+ ******************************************************************************/
+
+static u32
+ppc440spe_chan_get_current_descriptor(struct ppc440spe_adma_chan *chan);
+static void ppc440spe_chan_append(struct ppc440spe_adma_chan *chan);
+
+/**
+ * ppc440spe_adma_device_clear_eot_status - interrupt ack to XOR or DMA engine
+ */
+static void ppc440spe_adma_device_clear_eot_status(
+					struct ppc440spe_adma_chan *chan)
+{
+	struct dma_regs *dma_reg;
+	struct xor_regs *xor_reg;
+	u8 *p = chan->device->dma_desc_pool_virt;
+	struct dma_cdb *cdb;
+	u32 rv, i;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* read FIFO to ack */
+		dma_reg = chan->device->dma_reg;
+		while ((rv = ioread32(&dma_reg->csfpl))) {
+			i = rv & DMA_CDB_ADDR_MSK;
+			cdb = (struct dma_cdb *)&p[i -
+			    (u32)chan->device->dma_desc_pool];
+
+			/* Clear opcode to ack. This is necessary for
+			 * ZeroSum operations only
+			 */
+			cdb->opc = 0;
+
+			if (test_bit(PPC440SPE_RXOR_RUN,
+			    &ppc440spe_rxor_state)) {
+				/* probably this is a completed RXOR op,
+				 * get pointer to CDB using the fact that
+				 * physical and virtual addresses of CDB
+				 * in pools have the same offsets
+				 */
+				if (le32_to_cpu(cdb->sg1u) &
+				    DMA_CUED_XOR_BASE) {
+					/* this is a RXOR */
+					clear_bit(PPC440SPE_RXOR_RUN,
+						  &ppc440spe_rxor_state);
+				}
+			}
+
+			if (rv & DMA_CDB_STATUS_MSK) {
+				/* ZeroSum check failed
+				 */
+				struct ppc440spe_adma_desc_slot *iter;
+				dma_addr_t phys = rv & ~DMA_CDB_MSK;
+
+				/*
+				 * Update the status of corresponding
+				 * descriptor.
+				 */
+				list_for_each_entry(iter, &chan->chain,
+				    chain_node) {
+					if (iter->phys == phys)
+						break;
+				}
+				/*
+				 * if cannot find the corresponding
+				 * slot it's a bug
+				 */
+				BUG_ON(&iter->chain_node == &chan->chain);
+
+				if (iter->xor_check_result) {
+					if (test_bit(PPC440SPE_DESC_PCHECK,
+						     &iter->flags)) {
+						*iter->xor_check_result |=
+							SUM_CHECK_P_RESULT;
+					} else
+					if (test_bit(PPC440SPE_DESC_QCHECK,
+						     &iter->flags)) {
+						*iter->xor_check_result |=
+							SUM_CHECK_Q_RESULT;
+					} else
+						BUG();
+				}
+			}
+		}
+
+		rv = ioread32(&dma_reg->dsts);
+		if (rv) {
+			pr_err("DMA%d err status: 0x%x\n",
+			       chan->device->id, rv);
+			/* write back to clear */
+			iowrite32(rv, &dma_reg->dsts);
+		}
+		break;
+	case PPC440SPE_XOR_ID:
+		/* reset status bits to ack */
+		xor_reg = chan->device->xor_reg;
+		rv = ioread32be(&xor_reg->sr);
+		iowrite32be(rv, &xor_reg->sr);
+
+		if (rv & (XOR_IE_ICBIE_BIT|XOR_IE_ICIE_BIT|XOR_IE_RPTIE_BIT)) {
+			if (rv & XOR_IE_RPTIE_BIT) {
+				/* Read PLB Timeout Error.
+				 * Try to resubmit the CB
+				 */
+				u32 val = ioread32be(&xor_reg->ccbalr);
+
+				iowrite32be(val, &xor_reg->cblalr);
+
+				val = ioread32be(&xor_reg->crsr);
+				iowrite32be(val | XOR_CRSR_XAE_BIT,
+					    &xor_reg->crsr);
+			} else
+				pr_err("XOR ERR 0x%x status\n", rv);
+			break;
+		}
+
+		/*  if the XORcore is idle, but there are unprocessed CBs
+		 * then refetch the s/w chain here
+		 */
+		if (!(ioread32be(&xor_reg->sr) & XOR_SR_XCP_BIT) &&
+		    do_xor_refetch)
+			ppc440spe_chan_append(chan);
+		break;
+	}
+}
+
+/**
+ * ppc440spe_chan_is_busy - get the channel status
+ */
+static int ppc440spe_chan_is_busy(struct ppc440spe_adma_chan *chan)
+{
+	struct dma_regs *dma_reg;
+	struct xor_regs *xor_reg;
+	int busy = 0;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_reg = chan->device->dma_reg;
+		/*  if command FIFO's head and tail pointers are equal and
+		 * status tail is the same as command, then channel is free
+		 */
+		if (ioread16(&dma_reg->cpfhp) != ioread16(&dma_reg->cpftp) ||
+		    ioread16(&dma_reg->cpftp) != ioread16(&dma_reg->csftp))
+			busy = 1;
+		break;
+	case PPC440SPE_XOR_ID:
+		/* use the special status bit for the XORcore
+		 */
+		xor_reg = chan->device->xor_reg;
+		busy = (ioread32be(&xor_reg->sr) & XOR_SR_XCP_BIT) ? 1 : 0;
+		break;
+	}
+
+	return busy;
+}
+
+/**
+ * ppc440spe_chan_set_first_xor_descriptor -  init XORcore chain
+ */
+static void ppc440spe_chan_set_first_xor_descriptor(
+				struct ppc440spe_adma_chan *chan,
+				struct ppc440spe_adma_desc_slot *next_desc)
+{
+	struct xor_regs *xor_reg = chan->device->xor_reg;
+
+	if (ioread32be(&xor_reg->sr) & XOR_SR_XCP_BIT)
+		printk(KERN_INFO "%s: Warn: XORcore is running "
+			"when try to set the first CDB!\n",
+			__func__);
+
+	xor_last_submit = xor_last_linked = next_desc;
+
+	iowrite32be(XOR_CRSR_64BA_BIT, &xor_reg->crsr);
+
+	iowrite32be(next_desc->phys, &xor_reg->cblalr);
+	iowrite32be(0, &xor_reg->cblahr);
+	iowrite32be(ioread32be(&xor_reg->cbcr) | XOR_CBCR_LNK_BIT,
+		    &xor_reg->cbcr);
+
+	chan->hw_chain_inited = 1;
+}
+
+/**
+ * ppc440spe_dma_put_desc - put DMA0,1 descriptor to FIFO.
+ * called with irqs disabled
+ */
+static void ppc440spe_dma_put_desc(struct ppc440spe_adma_chan *chan,
+		struct ppc440spe_adma_desc_slot *desc)
+{
+	u32 pcdb;
+	struct dma_regs *dma_reg = chan->device->dma_reg;
+
+	pcdb = desc->phys;
+	if (!test_bit(PPC440SPE_DESC_INT, &desc->flags))
+		pcdb |= DMA_CDB_NO_INT;
+
+	chan_last_sub[chan->device->id] = desc;
+
+	ADMA_LL_DBG(print_cb(chan, desc->hw_desc));
+
+	iowrite32(pcdb, &dma_reg->cpfpl);
+}
+
+/**
+ * ppc440spe_chan_append - update the h/w chain in the channel
+ */
+static void ppc440spe_chan_append(struct ppc440spe_adma_chan *chan)
+{
+	struct xor_regs *xor_reg;
+	struct ppc440spe_adma_desc_slot *iter;
+	struct xor_cb *xcb;
+	u32 cur_desc;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		cur_desc = ppc440spe_chan_get_current_descriptor(chan);
+
+		if (likely(cur_desc)) {
+			iter = chan_last_sub[chan->device->id];
+			BUG_ON(!iter);
+		} else {
+			/* first peer */
+			iter = chan_first_cdb[chan->device->id];
+			BUG_ON(!iter);
+			ppc440spe_dma_put_desc(chan, iter);
+			chan->hw_chain_inited = 1;
+		}
+
+		/* is there something new to append */
+		if (!iter->hw_next)
+			break;
+
+		/* flush descriptors from the s/w queue to fifo */
+		list_for_each_entry_continue(iter, &chan->chain, chain_node) {
+			ppc440spe_dma_put_desc(chan, iter);
+			if (!iter->hw_next)
+				break;
+		}
+		break;
+	case PPC440SPE_XOR_ID:
+		/* update h/w links and refetch */
+		if (!xor_last_submit->hw_next)
+			break;
+
+		xor_reg = chan->device->xor_reg;
+		/* the last linked CDB has to generate an interrupt
+		 * that we'd be able to append the next lists to h/w
+		 * regardless of the XOR engine state at the moment of
+		 * appending of these next lists
+		 */
+		xcb = xor_last_linked->hw_desc;
+		xcb->cbc |= XOR_CBCR_CBCE_BIT;
+
+		if (!(ioread32be(&xor_reg->sr) & XOR_SR_XCP_BIT)) {
+			/* XORcore is idle. Refetch now */
+			do_xor_refetch = 0;
+			ppc440spe_xor_set_link(xor_last_submit,
+				xor_last_submit->hw_next);
+
+			ADMA_LL_DBG(print_cb_list(chan,
+				xor_last_submit->hw_next));
+
+			xor_last_submit = xor_last_linked;
+			iowrite32be(ioread32be(&xor_reg->crsr) |
+				    XOR_CRSR_RCBE_BIT | XOR_CRSR_64BA_BIT,
+				    &xor_reg->crsr);
+		} else {
+			/* XORcore is running. Refetch later in the handler */
+			do_xor_refetch = 1;
+		}
+
+		break;
+	}
+
+	local_irq_restore(flags);
+}
+
+/**
+ * ppc440spe_chan_get_current_descriptor - get the currently executed descriptor
+ */
+static u32
+ppc440spe_chan_get_current_descriptor(struct ppc440spe_adma_chan *chan)
+{
+	struct dma_regs *dma_reg;
+	struct xor_regs *xor_reg;
+
+	if (unlikely(!chan->hw_chain_inited))
+		/* h/w descriptor chain is not initialized yet */
+		return 0;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_reg = chan->device->dma_reg;
+		return ioread32(&dma_reg->acpl) & (~DMA_CDB_MSK);
+	case PPC440SPE_XOR_ID:
+		xor_reg = chan->device->xor_reg;
+		return ioread32be(&xor_reg->ccbalr);
+	}
+	return 0;
+}
+
+/**
+ * ppc440spe_chan_run - enable the channel
+ */
+static void ppc440spe_chan_run(struct ppc440spe_adma_chan *chan)
+{
+	struct xor_regs *xor_reg;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* DMAs are always enabled, do nothing */
+		break;
+	case PPC440SPE_XOR_ID:
+		/* drain write buffer */
+		xor_reg = chan->device->xor_reg;
+
+		/* fetch descriptor pointed to in <link> */
+		iowrite32be(XOR_CRSR_64BA_BIT | XOR_CRSR_XAE_BIT,
+			    &xor_reg->crsr);
+		break;
+	}
+}
+
+/******************************************************************************
+ * ADMA device level
+ ******************************************************************************/
+
+static void ppc440spe_chan_start_null_xor(struct ppc440spe_adma_chan *chan);
+static int ppc440spe_adma_alloc_chan_resources(struct dma_chan *chan);
+
+static dma_cookie_t
+ppc440spe_adma_tx_submit(struct dma_async_tx_descriptor *tx);
+
+static void ppc440spe_adma_set_dest(struct ppc440spe_adma_desc_slot *tx,
+				    dma_addr_t addr, int index);
+static void
+ppc440spe_adma_memcpy_xor_set_src(struct ppc440spe_adma_desc_slot *tx,
+				  dma_addr_t addr, int index);
+
+static void
+ppc440spe_adma_pq_set_dest(struct ppc440spe_adma_desc_slot *tx,
+			   dma_addr_t *paddr, unsigned long flags);
+static void
+ppc440spe_adma_pq_set_src(struct ppc440spe_adma_desc_slot *tx,
+			  dma_addr_t addr, int index);
+static void
+ppc440spe_adma_pq_set_src_mult(struct ppc440spe_adma_desc_slot *tx,
+			       unsigned char mult, int index, int dst_pos);
+static void
+ppc440spe_adma_pqzero_sum_set_dest(struct ppc440spe_adma_desc_slot *tx,
+				   dma_addr_t paddr, dma_addr_t qaddr);
+
+static struct page *ppc440spe_rxor_srcs[32];
+
+/**
+ * ppc440spe_can_rxor - check if the operands may be processed with RXOR
+ */
+static int ppc440spe_can_rxor(struct page **srcs, int src_cnt, size_t len)
+{
+	int i, order = 0, state = 0;
+	int idx = 0;
+
+	if (unlikely(!(src_cnt > 1)))
+		return 0;
+
+	BUG_ON(src_cnt > ARRAY_SIZE(ppc440spe_rxor_srcs));
+
+	/* Skip holes in the source list before checking */
+	for (i = 0; i < src_cnt; i++) {
+		if (!srcs[i])
+			continue;
+		ppc440spe_rxor_srcs[idx++] = srcs[i];
+	}
+	src_cnt = idx;
+
+	for (i = 1; i < src_cnt; i++) {
+		char *cur_addr = page_address(ppc440spe_rxor_srcs[i]);
+		char *old_addr = page_address(ppc440spe_rxor_srcs[i - 1]);
+
+		switch (state) {
+		case 0:
+			if (cur_addr == old_addr + len) {
+				/* direct RXOR */
+				order = 1;
+				state = 1;
+			} else if (old_addr == cur_addr + len) {
+				/* reverse RXOR */
+				order = -1;
+				state = 1;
+			} else
+				goto out;
+			break;
+		case 1:
+			if ((i == src_cnt - 2) ||
+			    (order == -1 && cur_addr != old_addr - len)) {
+				order = 0;
+				state = 0;
+			} else if ((cur_addr == old_addr + len * order) ||
+				   (cur_addr == old_addr + 2 * len) ||
+				   (cur_addr == old_addr + 3 * len)) {
+				state = 2;
+			} else {
+				order = 0;
+				state = 0;
+			}
+			break;
+		case 2:
+			order = 0;
+			state = 0;
+			break;
+		}
+	}
+
+out:
+	if (state == 1 || state == 2)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * ppc440spe_adma_device_estimate - estimate the efficiency of processing
+ *	the operation given on this channel. It's assumed that 'chan' is
+ *	capable to process 'cap' type of operation.
+ * @chan: channel to use
+ * @cap: type of transaction
+ * @dst_lst: array of destination pointers
+ * @dst_cnt: number of destination operands
+ * @src_lst: array of source pointers
+ * @src_cnt: number of source operands
+ * @src_sz: size of each source operand
+ */
+static int ppc440spe_adma_estimate(struct dma_chan *chan,
+	enum dma_transaction_type cap, struct page **dst_lst, int dst_cnt,
+	struct page **src_lst, int src_cnt, size_t src_sz)
+{
+	int ef = 1;
+
+	if (cap == DMA_PQ || cap == DMA_PQ_VAL) {
+		/* If RAID-6 capabilities were not activated don't try
+		 * to use them
+		 */
+		if (unlikely(!ppc440spe_r6_enabled))
+			return -1;
+	}
+	/*  In the current implementation of ppc440spe ADMA driver it
+	 * makes sense to pick out only pq case, because it may be
+	 * processed:
+	 * (1) either using Biskup method on DMA2;
+	 * (2) or on DMA0/1.
+	 *  Thus we give a favour to (1) if the sources are suitable;
+	 * else let it be processed on one of the DMA0/1 engines.
+	 *  In the sum_product case where destination is also the
+	 * source process it on DMA0/1 only.
+	 */
+	if (cap == DMA_PQ && chan->chan_id == PPC440SPE_XOR_ID) {
+
+		if (dst_cnt == 1 && src_cnt == 2 && dst_lst[0] == src_lst[1])
+			ef = 0; /* sum_product case, process on DMA0/1 */
+		else if (ppc440spe_can_rxor(src_lst, src_cnt, src_sz))
+			ef = 3; /* override (DMA0/1 + idle) */
+		else
+			ef = 0; /* can't process on DMA2 if !rxor */
+	}
+
+	/* channel idleness increases the priority */
+	if (likely(ef) &&
+	    !ppc440spe_chan_is_busy(to_ppc440spe_adma_chan(chan)))
+		ef++;
+
+	return ef;
+}
+
+struct dma_chan *
+ppc440spe_async_tx_find_best_channel(enum dma_transaction_type cap,
+	struct page **dst_lst, int dst_cnt, struct page **src_lst,
+	int src_cnt, size_t src_sz)
+{
+	struct dma_chan *best_chan = NULL;
+	struct ppc_dma_chan_ref *ref;
+	int best_rank = -1;
+
+	if (unlikely(!src_sz))
+		return NULL;
+	if (src_sz > PAGE_SIZE) {
+		/*
+		 * should a user of the api ever pass > PAGE_SIZE requests
+		 * we sort out cases where temporary page-sized buffers
+		 * are used.
+		 */
+		switch (cap) {
+		case DMA_PQ:
+			if (src_cnt == 1 && dst_lst[1] == src_lst[0])
+				return NULL;
+			if (src_cnt == 2 && dst_lst[1] == src_lst[1])
+				return NULL;
+			break;
+		case DMA_PQ_VAL:
+		case DMA_XOR_VAL:
+			return NULL;
+		default:
+			break;
+		}
+	}
+
+	list_for_each_entry(ref, &ppc440spe_adma_chan_list, node) {
+		if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
+			int rank;
+
+			rank = ppc440spe_adma_estimate(ref->chan, cap, dst_lst,
+					dst_cnt, src_lst, src_cnt, src_sz);
+			if (rank > best_rank) {
+				best_rank = rank;
+				best_chan = ref->chan;
+			}
+		}
+	}
+
+	return best_chan;
+}
+EXPORT_SYMBOL_GPL(ppc440spe_async_tx_find_best_channel);
+
+/**
+ * ppc440spe_get_group_entry - get group entry with index idx
+ * @tdesc: is the last allocated slot in the group.
+ */
+static struct ppc440spe_adma_desc_slot *
+ppc440spe_get_group_entry(struct ppc440spe_adma_desc_slot *tdesc, u32 entry_idx)
+{
+	struct ppc440spe_adma_desc_slot *iter = tdesc->group_head;
+	int i = 0;
+
+	if (entry_idx < 0 || entry_idx >= (tdesc->src_cnt + tdesc->dst_cnt)) {
+		printk("%s: entry_idx %d, src_cnt %d, dst_cnt %d\n",
+			__func__, entry_idx, tdesc->src_cnt, tdesc->dst_cnt);
+		BUG();
+	}
+
+	list_for_each_entry(iter, &tdesc->group_list, chain_node) {
+		if (i++ == entry_idx)
+			break;
+	}
+	return iter;
+}
+
+/**
+ * ppc440spe_adma_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &ppc440spe_chan->lock while calling this function
+ */
+static void ppc440spe_adma_free_slots(struct ppc440spe_adma_desc_slot *slot,
+				      struct ppc440spe_adma_chan *chan)
+{
+	int stride = slot->slots_per_op;
+
+	while (stride--) {
+		slot->slots_per_op = 0;
+		slot = list_entry(slot->slot_node.next,
+				struct ppc440spe_adma_desc_slot,
+				slot_node);
+	}
+}
+
+static void ppc440spe_adma_unmap(struct ppc440spe_adma_chan *chan,
+				 struct ppc440spe_adma_desc_slot *desc)
+{
+	u32 src_cnt, dst_cnt;
+	dma_addr_t addr;
+
+	/*
+	 * get the number of sources & destination
+	 * included in this descriptor and unmap
+	 * them all
+	 */
+	src_cnt = ppc440spe_desc_get_src_num(desc, chan);
+	dst_cnt = ppc440spe_desc_get_dst_num(desc, chan);
+
+	/* unmap destinations */
+	if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		while (dst_cnt--) {
+			addr = ppc440spe_desc_get_dest_addr(
+				desc, chan, dst_cnt);
+			dma_unmap_page(chan->device->dev,
+					addr, desc->unmap_len,
+					DMA_FROM_DEVICE);
+		}
+	}
+
+	/* unmap sources */
+	if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		while (src_cnt--) {
+			addr = ppc440spe_desc_get_src_addr(
+				desc, chan, src_cnt);
+			dma_unmap_page(chan->device->dev,
+					addr, desc->unmap_len,
+					DMA_TO_DEVICE);
+		}
+	}
+}
+
+/**
+ * ppc440spe_adma_run_tx_complete_actions - call functions to be called
+ * upon completion
+ */
+static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
+		struct ppc440spe_adma_desc_slot *desc,
+		struct ppc440spe_adma_chan *chan,
+		dma_cookie_t cookie)
+{
+	int i;
+
+	BUG_ON(desc->async_tx.cookie < 0);
+	if (desc->async_tx.cookie > 0) {
+		cookie = desc->async_tx.cookie;
+		desc->async_tx.cookie = 0;
+
+		/* call the callback (must not sleep or submit new
+		 * operations to this channel)
+		 */
+		if (desc->async_tx.callback)
+			desc->async_tx.callback(
+				desc->async_tx.callback_param);
+
+		/* unmap dma addresses
+		 * (unmap_single vs unmap_page?)
+		 *
+		 * actually, ppc's dma_unmap_page() functions are empty, so
+		 * the following code is just for the sake of completeness
+		 */
+		if (chan && chan->needs_unmap && desc->group_head &&
+		     desc->unmap_len) {
+			struct ppc440spe_adma_desc_slot *unmap =
+							desc->group_head;
+			/* assume 1 slot per op always */
+			u32 slot_count = unmap->slot_cnt;
+
+			/* Run through the group list and unmap addresses */
+			for (i = 0; i < slot_count; i++) {
+				BUG_ON(!unmap);
+				ppc440spe_adma_unmap(chan, unmap);
+				unmap = unmap->hw_next;
+			}
+		}
+	}
+
+	/* run dependent operations */
+	dma_run_dependencies(&desc->async_tx);
+
+	return cookie;
+}
+
+/**
+ * ppc440spe_adma_clean_slot - clean up CDB slot (if ack is set)
+ */
+static int ppc440spe_adma_clean_slot(struct ppc440spe_adma_desc_slot *desc,
+		struct ppc440spe_adma_chan *chan)
+{
+	/* the client is allowed to attach dependent operations
+	 * until 'ack' is set
+	 */
+	if (!async_tx_test_ack(&desc->async_tx))
+		return 0;
+
+	/* leave the last descriptor in the chain
+	 * so we can append to it
+	 */
+	if (list_is_last(&desc->chain_node, &chan->chain) ||
+	    desc->phys == ppc440spe_chan_get_current_descriptor(chan))
+		return 1;
+
+	if (chan->device->id != PPC440SPE_XOR_ID) {
+		/* our DMA interrupt handler clears opc field of
+		 * each processed descriptor. For all types of
+		 * operations except for ZeroSum we do not actually
+		 * need ack from the interrupt handler. ZeroSum is a
+		 * special case since the result of this operation
+		 * is available from the handler only, so if we see
+		 * such type of descriptor (which is unprocessed yet)
+		 * then leave it in chain.
+		 */
+		struct dma_cdb *cdb = desc->hw_desc;
+		if (cdb->opc == DMA_CDB_OPC_DCHECK128)
+			return 1;
+	}
+
+	dev_dbg(chan->device->common.dev, "\tfree slot %llx: %d stride: %d\n",
+		desc->phys, desc->idx, desc->slots_per_op);
+
+	list_del(&desc->chain_node);
+	ppc440spe_adma_free_slots(desc, chan);
+	return 0;
+}
+
+/**
+ * __ppc440spe_adma_slot_cleanup - this is the common clean-up routine
+ *	which runs through the channel CDBs list until reach the descriptor
+ *	currently processed. When routine determines that all CDBs of group
+ *	are completed then corresponding callbacks (if any) are called and slots
+ *	are freed.
+ */
+static void __ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
+{
+	struct ppc440spe_adma_desc_slot *iter, *_iter, *group_start = NULL;
+	dma_cookie_t cookie = 0;
+	u32 current_desc = ppc440spe_chan_get_current_descriptor(chan);
+	int busy = ppc440spe_chan_is_busy(chan);
+	int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+
+	dev_dbg(chan->device->common.dev, "ppc440spe adma%d: %s\n",
+		chan->device->id, __func__);
+
+	if (!current_desc) {
+		/*  There were no transactions yet, so
+		 * nothing to clean
+		 */
+		return;
+	}
+
+	/* free completed slots from the chain starting with
+	 * the oldest descriptor
+	 */
+	list_for_each_entry_safe(iter, _iter, &chan->chain,
+					chain_node) {
+		dev_dbg(chan->device->common.dev, "\tcookie: %d slot: %d "
+		    "busy: %d this_desc: %#llx next_desc: %#x "
+		    "cur: %#x ack: %d\n",
+		    iter->async_tx.cookie, iter->idx, busy, iter->phys,
+		    ppc440spe_desc_get_link(iter, chan), current_desc,
+		    async_tx_test_ack(&iter->async_tx));
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+
+		/* do not advance past the current descriptor loaded into the
+		 * hardware channel,subsequent descriptors are either in process
+		 * or have not been submitted
+		 */
+		if (seen_current)
+			break;
+
+		/* stop the search if we reach the current descriptor and the
+		 * channel is busy, or if it appears that the current descriptor
+		 * needs to be re-read (i.e. has been appended to)
+		 */
+		if (iter->phys == current_desc) {
+			BUG_ON(seen_current++);
+			if (busy || ppc440spe_desc_get_link(iter, chan)) {
+				/* not all descriptors of the group have
+				 * been completed; exit.
+				 */
+				break;
+			}
+		}
+
+		/* detect the start of a group transaction */
+		if (!slot_cnt && !slots_per_op) {
+			slot_cnt = iter->slot_cnt;
+			slots_per_op = iter->slots_per_op;
+			if (slot_cnt <= slots_per_op) {
+				slot_cnt = 0;
+				slots_per_op = 0;
+			}
+		}
+
+		if (slot_cnt) {
+			if (!group_start)
+				group_start = iter;
+			slot_cnt -= slots_per_op;
+		}
+
+		/* all the members of a group are complete */
+		if (slots_per_op != 0 && slot_cnt == 0) {
+			struct ppc440spe_adma_desc_slot *grp_iter, *_grp_iter;
+			int end_of_chain = 0;
+
+			/* clean up the group */
+			slot_cnt = group_start->slot_cnt;
+			grp_iter = group_start;
+			list_for_each_entry_safe_from(grp_iter, _grp_iter,
+				&chan->chain, chain_node) {
+
+				cookie = ppc440spe_adma_run_tx_complete_actions(
+					grp_iter, chan, cookie);
+
+				slot_cnt -= slots_per_op;
+				end_of_chain = ppc440spe_adma_clean_slot(
+				    grp_iter, chan);
+				if (end_of_chain && slot_cnt) {
+					/* Should wait for ZeroSum completion */
+					if (cookie > 0)
+						chan->completed_cookie = cookie;
+					return;
+				}
+
+				if (slot_cnt == 0 || end_of_chain)
+					break;
+			}
+
+			/* the group should be complete at this point */
+			BUG_ON(slot_cnt);
+
+			slots_per_op = 0;
+			group_start = NULL;
+			if (end_of_chain)
+				break;
+			else
+				continue;
+		} else if (slots_per_op) /* wait for group completion */
+			continue;
+
+		cookie = ppc440spe_adma_run_tx_complete_actions(iter, chan,
+		    cookie);
+
+		if (ppc440spe_adma_clean_slot(iter, chan))
+			break;
+	}
+
+	BUG_ON(!seen_current);
+
+	if (cookie > 0) {
+		chan->completed_cookie = cookie;
+		pr_debug("\tcompleted cookie %d\n", cookie);
+	}
+
+}
+
+/**
+ * ppc440spe_adma_tasklet - clean up watch-dog initiator
+ */
+static void ppc440spe_adma_tasklet(unsigned long data)
+{
+	struct ppc440spe_adma_chan *chan = (struct ppc440spe_adma_chan *) data;
+
+	spin_lock_nested(&chan->lock, SINGLE_DEPTH_NESTING);
+	__ppc440spe_adma_slot_cleanup(chan);
+	spin_unlock(&chan->lock);
+}
+
+/**
+ * ppc440spe_adma_slot_cleanup - clean up scheduled initiator
+ */
+static void ppc440spe_adma_slot_cleanup(struct ppc440spe_adma_chan *chan)
+{
+	spin_lock_bh(&chan->lock);
+	__ppc440spe_adma_slot_cleanup(chan);
+	spin_unlock_bh(&chan->lock);
+}
+
+/**
+ * ppc440spe_adma_alloc_slots - allocate free slots (if any)
+ */
+static struct ppc440spe_adma_desc_slot *ppc440spe_adma_alloc_slots(
+		struct ppc440spe_adma_chan *chan, int num_slots,
+		int slots_per_op)
+{
+	struct ppc440spe_adma_desc_slot *iter = NULL, *_iter;
+	struct ppc440spe_adma_desc_slot *alloc_start = NULL;
+	struct list_head chain = LIST_HEAD_INIT(chain);
+	int slots_found, retry = 0;
+
+
+	BUG_ON(!num_slots || !slots_per_op);
+	/* start search from the last allocated descrtiptor
+	 * if a contiguous allocation can not be found start searching
+	 * from the beginning of the list
+	 */
+retry:
+	slots_found = 0;
+	if (retry == 0)
+		iter = chan->last_used;
+	else
+		iter = list_entry(&chan->all_slots,
+				  struct ppc440spe_adma_desc_slot,
+				  slot_node);
+	list_for_each_entry_safe_continue(iter, _iter, &chan->all_slots,
+	    slot_node) {
+		prefetch(_iter);
+		prefetch(&_iter->async_tx);
+		if (iter->slots_per_op) {
+			slots_found = 0;
+			continue;
+		}
+
+		/* start the allocation if the slot is correctly aligned */
+		if (!slots_found++)
+			alloc_start = iter;
+
+		if (slots_found == num_slots) {
+			struct ppc440spe_adma_desc_slot *alloc_tail = NULL;
+			struct ppc440spe_adma_desc_slot *last_used = NULL;
+
+			iter = alloc_start;
+			while (num_slots) {
+				int i;
+				/* pre-ack all but the last descriptor */
+				if (num_slots != slots_per_op)
+					async_tx_ack(&iter->async_tx);
+
+				list_add_tail(&iter->chain_node, &chain);
+				alloc_tail = iter;
+				iter->async_tx.cookie = 0;
+				iter->hw_next = NULL;
+				iter->flags = 0;
+				iter->slot_cnt = num_slots;
+				iter->xor_check_result = NULL;
+				for (i = 0; i < slots_per_op; i++) {
+					iter->slots_per_op = slots_per_op - i;
+					last_used = iter;
+					iter = list_entry(iter->slot_node.next,
+						struct ppc440spe_adma_desc_slot,
+						slot_node);
+				}
+				num_slots -= slots_per_op;
+			}
+			alloc_tail->group_head = alloc_start;
+			alloc_tail->async_tx.cookie = -EBUSY;
+			list_splice(&chain, &alloc_tail->group_list);
+			chan->last_used = last_used;
+			return alloc_tail;
+		}
+	}
+	if (!retry++)
+		goto retry;
+
+	/* try to free some slots if the allocation fails */
+	tasklet_schedule(&chan->irq_tasklet);
+	return NULL;
+}
+
+/**
+ * ppc440spe_adma_alloc_chan_resources -  allocate pools for CDB slots
+ */
+static int ppc440spe_adma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *slot = NULL;
+	char *hw_desc;
+	int i, db_sz;
+	int init;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+	init = ppc440spe_chan->slots_allocated ? 0 : 1;
+	chan->chan_id = ppc440spe_chan->device->id;
+
+	/* Allocate descriptor slots */
+	i = ppc440spe_chan->slots_allocated;
+	if (ppc440spe_chan->device->id != PPC440SPE_XOR_ID)
+		db_sz = sizeof(struct dma_cdb);
+	else
+		db_sz = sizeof(struct xor_cb);
+
+	for (; i < (ppc440spe_chan->device->pool_size / db_sz); i++) {
+		slot = kzalloc(sizeof(struct ppc440spe_adma_desc_slot),
+			       GFP_KERNEL);
+		if (!slot) {
+			printk(KERN_INFO "SPE ADMA Channel only initialized"
+				" %d descriptor slots", i--);
+			break;
+		}
+
+		hw_desc = (char *) ppc440spe_chan->device->dma_desc_pool_virt;
+		slot->hw_desc = (void *) &hw_desc[i * db_sz];
+		dma_async_tx_descriptor_init(&slot->async_tx, chan);
+		slot->async_tx.tx_submit = ppc440spe_adma_tx_submit;
+		INIT_LIST_HEAD(&slot->chain_node);
+		INIT_LIST_HEAD(&slot->slot_node);
+		INIT_LIST_HEAD(&slot->group_list);
+		slot->phys = ppc440spe_chan->device->dma_desc_pool + i * db_sz;
+		slot->idx = i;
+
+		spin_lock_bh(&ppc440spe_chan->lock);
+		ppc440spe_chan->slots_allocated++;
+		list_add_tail(&slot->slot_node, &ppc440spe_chan->all_slots);
+		spin_unlock_bh(&ppc440spe_chan->lock);
+	}
+
+	if (i && !ppc440spe_chan->last_used) {
+		ppc440spe_chan->last_used =
+			list_entry(ppc440spe_chan->all_slots.next,
+				struct ppc440spe_adma_desc_slot,
+				slot_node);
+	}
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: allocated %d descriptor slots\n",
+		ppc440spe_chan->device->id, i);
+
+	/* initialize the channel and the chain with a null operation */
+	if (init) {
+		switch (ppc440spe_chan->device->id) {
+		case PPC440SPE_DMA0_ID:
+		case PPC440SPE_DMA1_ID:
+			ppc440spe_chan->hw_chain_inited = 0;
+			/* Use WXOR for self-testing */
+			if (!ppc440spe_r6_tchan)
+				ppc440spe_r6_tchan = ppc440spe_chan;
+			break;
+		case PPC440SPE_XOR_ID:
+			ppc440spe_chan_start_null_xor(ppc440spe_chan);
+			break;
+		default:
+			BUG();
+		}
+		ppc440spe_chan->needs_unmap = 1;
+	}
+
+	return (i > 0) ? i : -ENOMEM;
+}
+
+/**
+ * ppc440spe_desc_assign_cookie - assign a cookie
+ */
+static dma_cookie_t ppc440spe_desc_assign_cookie(
+		struct ppc440spe_adma_chan *chan,
+		struct ppc440spe_adma_desc_slot *desc)
+{
+	dma_cookie_t cookie = chan->common.cookie;
+
+	cookie++;
+	if (cookie < 0)
+		cookie = 1;
+	chan->common.cookie = desc->async_tx.cookie = cookie;
+	return cookie;
+}
+
+/**
+ * ppc440spe_rxor_set_region_data -
+ */
+static void ppc440spe_rxor_set_region(struct ppc440spe_adma_desc_slot *desc,
+	u8 xor_arg_no, u32 mask)
+{
+	struct xor_cb *xcb = desc->hw_desc;
+
+	xcb->ops[xor_arg_no].h |= mask;
+}
+
+/**
+ * ppc440spe_rxor_set_src -
+ */
+static void ppc440spe_rxor_set_src(struct ppc440spe_adma_desc_slot *desc,
+	u8 xor_arg_no, dma_addr_t addr)
+{
+	struct xor_cb *xcb = desc->hw_desc;
+
+	xcb->ops[xor_arg_no].h |= DMA_CUED_XOR_BASE;
+	xcb->ops[xor_arg_no].l = addr;
+}
+
+/**
+ * ppc440spe_rxor_set_mult -
+ */
+static void ppc440spe_rxor_set_mult(struct ppc440spe_adma_desc_slot *desc,
+	u8 xor_arg_no, u8 idx, u8 mult)
+{
+	struct xor_cb *xcb = desc->hw_desc;
+
+	xcb->ops[xor_arg_no].h |= mult << (DMA_CUED_MULT1_OFF + idx * 8);
+}
+
+/**
+ * ppc440spe_adma_check_threshold - append CDBs to h/w chain if threshold
+ *	has been achieved
+ */
+static void ppc440spe_adma_check_threshold(struct ppc440spe_adma_chan *chan)
+{
+	dev_dbg(chan->device->common.dev, "ppc440spe adma%d: pending: %d\n",
+		chan->device->id, chan->pending);
+
+	if (chan->pending >= PPC440SPE_ADMA_THRESHOLD) {
+		chan->pending = 0;
+		ppc440spe_chan_append(chan);
+	}
+}
+
+/**
+ * ppc440spe_adma_tx_submit - submit new descriptor group to the channel
+ *	(it's not necessary that descriptors will be submitted to the h/w
+ *	chains too right now)
+ */
+static dma_cookie_t ppc440spe_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ppc440spe_adma_desc_slot *sw_desc;
+	struct ppc440spe_adma_chan *chan = to_ppc440spe_adma_chan(tx->chan);
+	struct ppc440spe_adma_desc_slot *group_start, *old_chain_tail;
+	int slot_cnt;
+	int slots_per_op;
+	dma_cookie_t cookie;
+
+	sw_desc = tx_to_ppc440spe_adma_slot(tx);
+
+	group_start = sw_desc->group_head;
+	slot_cnt = group_start->slot_cnt;
+	slots_per_op = group_start->slots_per_op;
+
+	spin_lock_bh(&chan->lock);
+
+	cookie = ppc440spe_desc_assign_cookie(chan, sw_desc);
+
+	if (unlikely(list_empty(&chan->chain))) {
+		/* first peer */
+		list_splice_init(&sw_desc->group_list, &chan->chain);
+		chan_first_cdb[chan->device->id] = group_start;
+	} else {
+		/* isn't first peer, bind CDBs to chain */
+		old_chain_tail = list_entry(chan->chain.prev,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		list_splice_init(&sw_desc->group_list,
+		    &old_chain_tail->chain_node);
+		/* fix up the hardware chain */
+		ppc440spe_desc_set_link(chan, old_chain_tail, group_start);
+	}
+
+	/* increment the pending count by the number of operations */
+	chan->pending += slot_cnt / slots_per_op;
+	ppc440spe_adma_check_threshold(chan);
+	spin_unlock_bh(&chan->lock);
+
+	dev_dbg(chan->device->common.dev,
+		"ppc440spe adma%d: %s cookie: %d slot: %d tx %p\n",
+		chan->device->id, __func__,
+		sw_desc->async_tx.cookie, sw_desc->idx, sw_desc);
+
+	return cookie;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_interrupt - prepare CDB for a pseudo DMA operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_interrupt(
+		struct dma_chan *chan, unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc, *group_start;
+	int slot_cnt, slots_per_op;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s\n", ppc440spe_chan->device->id,
+		__func__);
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	slot_cnt = slots_per_op = 1;
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt,
+			slots_per_op);
+	if (sw_desc) {
+		group_start = sw_desc->group_head;
+		ppc440spe_desc_init_interrupt(group_start, ppc440spe_chan);
+		group_start->unmap_len = 0;
+		sw_desc->async_tx.flags = flags;
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_memcpy - prepare CDB for a MEMCPY operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_memcpy(
+		struct dma_chan *chan, dma_addr_t dma_dest,
+		dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc, *group_start;
+	int slot_cnt, slots_per_op;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	if (unlikely(!len))
+		return NULL;
+
+	BUG_ON(unlikely(len > PPC440SPE_ADMA_DMA_MAX_BYTE_COUNT));
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s len: %u int_en %d\n",
+		ppc440spe_chan->device->id, __func__, len,
+		flags & DMA_PREP_INTERRUPT ? 1 : 0);
+	slot_cnt = slots_per_op = 1;
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt,
+		slots_per_op);
+	if (sw_desc) {
+		group_start = sw_desc->group_head;
+		ppc440spe_desc_init_memcpy(group_start, flags);
+		ppc440spe_adma_set_dest(group_start, dma_dest, 0);
+		ppc440spe_adma_memcpy_xor_set_src(group_start, dma_src, 0);
+		ppc440spe_desc_set_byte_count(group_start, ppc440spe_chan, len);
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.flags = flags;
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_memset - prepare CDB for a MEMSET operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_memset(
+		struct dma_chan *chan, dma_addr_t dma_dest, int value,
+		size_t len, unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc, *group_start;
+	int slot_cnt, slots_per_op;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	if (unlikely(!len))
+		return NULL;
+
+	BUG_ON(unlikely(len > PPC440SPE_ADMA_DMA_MAX_BYTE_COUNT));
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s cal: %u len: %u int_en %d\n",
+		ppc440spe_chan->device->id, __func__, value, len,
+		flags & DMA_PREP_INTERRUPT ? 1 : 0);
+
+	slot_cnt = slots_per_op = 1;
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt,
+		slots_per_op);
+	if (sw_desc) {
+		group_start = sw_desc->group_head;
+		ppc440spe_desc_init_memset(group_start, value, flags);
+		ppc440spe_adma_set_dest(group_start, dma_dest, 0);
+		ppc440spe_desc_set_byte_count(group_start, ppc440spe_chan, len);
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.flags = flags;
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_xor - prepare CDB for a XOR operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_xor(
+		struct dma_chan *chan, dma_addr_t dma_dest,
+		dma_addr_t *dma_src, u32 src_cnt, size_t len,
+		unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc, *group_start;
+	int slot_cnt, slots_per_op;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	ADMA_LL_DBG(prep_dma_xor_dbg(ppc440spe_chan->device->id,
+				     dma_dest, dma_src, src_cnt));
+	if (unlikely(!len))
+		return NULL;
+	BUG_ON(unlikely(len > PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT));
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s src_cnt: %d len: %u int_en: %d\n",
+		ppc440spe_chan->device->id, __func__, src_cnt, len,
+		flags & DMA_PREP_INTERRUPT ? 1 : 0);
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	slot_cnt = ppc440spe_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt,
+			slots_per_op);
+	if (sw_desc) {
+		group_start = sw_desc->group_head;
+		ppc440spe_desc_init_xor(group_start, src_cnt, flags);
+		ppc440spe_adma_set_dest(group_start, dma_dest, 0);
+		while (src_cnt--)
+			ppc440spe_adma_memcpy_xor_set_src(group_start,
+				dma_src[src_cnt], src_cnt);
+		ppc440spe_desc_set_byte_count(group_start, ppc440spe_chan, len);
+		sw_desc->unmap_len = len;
+		sw_desc->async_tx.flags = flags;
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static inline void
+ppc440spe_desc_set_xor_src_cnt(struct ppc440spe_adma_desc_slot *desc,
+				int src_cnt);
+static void ppc440spe_init_rxor_cursor(struct ppc440spe_rxor *cursor);
+
+/**
+ * ppc440spe_adma_init_dma2rxor_slot -
+ */
+static void ppc440spe_adma_init_dma2rxor_slot(
+		struct ppc440spe_adma_desc_slot *desc,
+		dma_addr_t *src, int src_cnt)
+{
+	int i;
+
+	/* initialize CDB */
+	for (i = 0; i < src_cnt; i++) {
+		ppc440spe_adma_dma2rxor_prep_src(desc, &desc->rxor_cursor, i,
+						 desc->src_cnt, (u32)src[i]);
+	}
+}
+
+/**
+ * ppc440spe_dma01_prep_mult -
+ * for Q operation where destination is also the source
+ */
+static struct ppc440spe_adma_desc_slot *ppc440spe_dma01_prep_mult(
+		struct ppc440spe_adma_chan *ppc440spe_chan,
+		dma_addr_t *dst, int dst_cnt, dma_addr_t *src, int src_cnt,
+		const unsigned char *scf, size_t len, unsigned long flags)
+{
+	struct ppc440spe_adma_desc_slot *sw_desc = NULL;
+	unsigned long op = 0;
+	int slot_cnt;
+
+	set_bit(PPC440SPE_DESC_WXOR, &op);
+	slot_cnt = 2;
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+
+	/* use WXOR, each descriptor occupies one slot */
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt, 1);
+	if (sw_desc) {
+		struct ppc440spe_adma_chan *chan;
+		struct ppc440spe_adma_desc_slot *iter;
+		struct dma_cdb *hw_desc;
+
+		chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+		set_bits(op, &sw_desc->flags);
+		sw_desc->src_cnt = src_cnt;
+		sw_desc->dst_cnt = dst_cnt;
+		/* First descriptor, zero data in the destination and copy it
+		 * to q page using MULTICAST transfer.
+		 */
+		iter = list_first_entry(&sw_desc->group_list,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		/* set 'next' pointer */
+		iter->hw_next = list_entry(iter->chain_node.next,
+					   struct ppc440spe_adma_desc_slot,
+					   chain_node);
+		clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MULTICAST;
+
+		ppc440spe_desc_set_dest_addr(iter, chan,
+					     DMA_CUED_XOR_BASE, dst[0], 0);
+		ppc440spe_desc_set_dest_addr(iter, chan, 0, dst[1], 1);
+		ppc440spe_desc_set_src_addr(iter, chan, 0, DMA_CUED_XOR_HB,
+					    src[0]);
+		ppc440spe_desc_set_byte_count(iter, ppc440spe_chan, len);
+		iter->unmap_len = len;
+
+		/*
+		 * Second descriptor, multiply data from the q page
+		 * and store the result in real destination.
+		 */
+		iter = list_first_entry(&iter->chain_node,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		iter->hw_next = NULL;
+		if (flags & DMA_PREP_INTERRUPT)
+			set_bit(PPC440SPE_DESC_INT, &iter->flags);
+		else
+			clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+		ppc440spe_desc_set_src_addr(iter, chan, 0,
+					    DMA_CUED_XOR_HB, dst[1]);
+		ppc440spe_desc_set_dest_addr(iter, chan,
+					     DMA_CUED_XOR_BASE, dst[0], 0);
+
+		ppc440spe_desc_set_src_mult(iter, chan, DMA_CUED_MULT1_OFF,
+					    DMA_CDB_SG_DST1, scf[0]);
+		ppc440spe_desc_set_byte_count(iter, ppc440spe_chan, len);
+		iter->unmap_len = len;
+		sw_desc->async_tx.flags = flags;
+	}
+
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc;
+}
+
+/**
+ * ppc440spe_dma01_prep_sum_product -
+ * Dx = A*(P+Pxy) + B*(Q+Qxy) operation where destination is also
+ * the source.
+ */
+static struct ppc440spe_adma_desc_slot *ppc440spe_dma01_prep_sum_product(
+		struct ppc440spe_adma_chan *ppc440spe_chan,
+		dma_addr_t *dst, dma_addr_t *src, int src_cnt,
+		const unsigned char *scf, size_t len, unsigned long flags)
+{
+	struct ppc440spe_adma_desc_slot *sw_desc = NULL;
+	unsigned long op = 0;
+	int slot_cnt;
+
+	set_bit(PPC440SPE_DESC_WXOR, &op);
+	slot_cnt = 3;
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+
+	/* WXOR, each descriptor occupies one slot */
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt, 1);
+	if (sw_desc) {
+		struct ppc440spe_adma_chan *chan;
+		struct ppc440spe_adma_desc_slot *iter;
+		struct dma_cdb *hw_desc;
+
+		chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+		set_bits(op, &sw_desc->flags);
+		sw_desc->src_cnt = src_cnt;
+		sw_desc->dst_cnt = 1;
+		/* 1st descriptor, src[1] data to q page and zero destination */
+		iter = list_first_entry(&sw_desc->group_list,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		iter->hw_next = list_entry(iter->chain_node.next,
+					   struct ppc440spe_adma_desc_slot,
+					   chain_node);
+		clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MULTICAST;
+
+		ppc440spe_desc_set_dest_addr(iter, chan, DMA_CUED_XOR_BASE,
+					     *dst, 0);
+		ppc440spe_desc_set_dest_addr(iter, chan, 0,
+					     ppc440spe_chan->qdest, 1);
+		ppc440spe_desc_set_src_addr(iter, chan, 0, DMA_CUED_XOR_HB,
+					    src[1]);
+		ppc440spe_desc_set_byte_count(iter, ppc440spe_chan, len);
+		iter->unmap_len = len;
+
+		/* 2nd descriptor, multiply src[1] data and store the
+		 * result in destination */
+		iter = list_first_entry(&iter->chain_node,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		/* set 'next' pointer */
+		iter->hw_next = list_entry(iter->chain_node.next,
+					   struct ppc440spe_adma_desc_slot,
+					   chain_node);
+		if (flags & DMA_PREP_INTERRUPT)
+			set_bit(PPC440SPE_DESC_INT, &iter->flags);
+		else
+			clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+		ppc440spe_desc_set_src_addr(iter, chan, 0, DMA_CUED_XOR_HB,
+					    ppc440spe_chan->qdest);
+		ppc440spe_desc_set_dest_addr(iter, chan, DMA_CUED_XOR_BASE,
+					     *dst, 0);
+		ppc440spe_desc_set_src_mult(iter, chan,	DMA_CUED_MULT1_OFF,
+					    DMA_CDB_SG_DST1, scf[1]);
+		ppc440spe_desc_set_byte_count(iter, ppc440spe_chan, len);
+		iter->unmap_len = len;
+
+		/*
+		 * 3rd descriptor, multiply src[0] data and xor it
+		 * with destination
+		 */
+		iter = list_first_entry(&iter->chain_node,
+					struct ppc440spe_adma_desc_slot,
+					chain_node);
+		memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+		iter->hw_next = NULL;
+		if (flags & DMA_PREP_INTERRUPT)
+			set_bit(PPC440SPE_DESC_INT, &iter->flags);
+		else
+			clear_bit(PPC440SPE_DESC_INT, &iter->flags);
+
+		hw_desc = iter->hw_desc;
+		hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+		ppc440spe_desc_set_src_addr(iter, chan, 0, DMA_CUED_XOR_HB,
+					    src[0]);
+		ppc440spe_desc_set_dest_addr(iter, chan, DMA_CUED_XOR_BASE,
+					     *dst, 0);
+		ppc440spe_desc_set_src_mult(iter, chan, DMA_CUED_MULT1_OFF,
+					    DMA_CDB_SG_DST1, scf[0]);
+		ppc440spe_desc_set_byte_count(iter, ppc440spe_chan, len);
+		iter->unmap_len = len;
+		sw_desc->async_tx.flags = flags;
+	}
+
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc;
+}
+
+static struct ppc440spe_adma_desc_slot *ppc440spe_dma01_prep_pq(
+		struct ppc440spe_adma_chan *ppc440spe_chan,
+		dma_addr_t *dst, int dst_cnt, dma_addr_t *src, int src_cnt,
+		const unsigned char *scf, size_t len, unsigned long flags)
+{
+	int slot_cnt;
+	struct ppc440spe_adma_desc_slot *sw_desc = NULL, *iter;
+	unsigned long op = 0;
+	unsigned char mult = 1;
+
+	pr_debug("%s: dst_cnt %d, src_cnt %d, len %d\n",
+		 __func__, dst_cnt, src_cnt, len);
+	/*  select operations WXOR/RXOR depending on the
+	 * source addresses of operators and the number
+	 * of destinations (RXOR support only Q-parity calculations)
+	 */
+	set_bit(PPC440SPE_DESC_WXOR, &op);
+	if (!test_and_set_bit(PPC440SPE_RXOR_RUN, &ppc440spe_rxor_state)) {
+		/* no active RXOR;
+		 * do RXOR if:
+		 * - there are more than 1 source,
+		 * - len is aligned on 512-byte boundary,
+		 * - source addresses fit to one of 4 possible regions.
+		 */
+		if (src_cnt > 1 &&
+		    !(len & MQ0_CF2H_RXOR_BS_MASK) &&
+		    (src[0] + len) == src[1]) {
+			/* may do RXOR R1 R2 */
+			set_bit(PPC440SPE_DESC_RXOR, &op);
+			if (src_cnt != 2) {
+				/* may try to enhance region of RXOR */
+				if ((src[1] + len) == src[2]) {
+					/* do RXOR R1 R2 R3 */
+					set_bit(PPC440SPE_DESC_RXOR123,
+						&op);
+				} else if ((src[1] + len * 2) == src[2]) {
+					/* do RXOR R1 R2 R4 */
+					set_bit(PPC440SPE_DESC_RXOR124, &op);
+				} else if ((src[1] + len * 3) == src[2]) {
+					/* do RXOR R1 R2 R5 */
+					set_bit(PPC440SPE_DESC_RXOR125,
+						&op);
+				} else {
+					/* do RXOR R1 R2 */
+					set_bit(PPC440SPE_DESC_RXOR12,
+						&op);
+				}
+			} else {
+				/* do RXOR R1 R2 */
+				set_bit(PPC440SPE_DESC_RXOR12, &op);
+			}
+		}
+
+		if (!test_bit(PPC440SPE_DESC_RXOR, &op)) {
+			/* can not do this operation with RXOR */
+			clear_bit(PPC440SPE_RXOR_RUN,
+				&ppc440spe_rxor_state);
+		} else {
+			/* can do; set block size right now */
+			ppc440spe_desc_set_rxor_block_size(len);
+		}
+	}
+
+	/* Number of necessary slots depends on operation type selected */
+	if (!test_bit(PPC440SPE_DESC_RXOR, &op)) {
+		/*  This is a WXOR only chain. Need descriptors for each
+		 * source to GF-XOR them with WXOR, and need descriptors
+		 * for each destination to zero them with WXOR
+		 */
+		slot_cnt = src_cnt;
+
+		if (flags & DMA_PREP_ZERO_P) {
+			slot_cnt++;
+			set_bit(PPC440SPE_ZERO_P, &op);
+		}
+		if (flags & DMA_PREP_ZERO_Q) {
+			slot_cnt++;
+			set_bit(PPC440SPE_ZERO_Q, &op);
+		}
+	} else {
+		/*  Need 1/2 descriptor for RXOR operation, and
+		 * need (src_cnt - (2 or 3)) for WXOR of sources
+		 * remained (if any)
+		 */
+		slot_cnt = dst_cnt;
+
+		if (flags & DMA_PREP_ZERO_P)
+			set_bit(PPC440SPE_ZERO_P, &op);
+		if (flags & DMA_PREP_ZERO_Q)
+			set_bit(PPC440SPE_ZERO_Q, &op);
+
+		if (test_bit(PPC440SPE_DESC_RXOR12, &op))
+			slot_cnt += src_cnt - 2;
+		else
+			slot_cnt += src_cnt - 3;
+
+		/*  Thus we have either RXOR only chain or
+		 * mixed RXOR/WXOR
+		 */
+		if (slot_cnt == dst_cnt)
+			/* RXOR only chain */
+			clear_bit(PPC440SPE_DESC_WXOR, &op);
+	}
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	/* for both RXOR/WXOR each descriptor occupies one slot */
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt, 1);
+	if (sw_desc) {
+		ppc440spe_desc_init_dma01pq(sw_desc, dst_cnt, src_cnt,
+				flags, op);
+
+		/* setup dst/src/mult */
+		pr_debug("%s: set dst descriptor 0, 1: 0x%016llx, 0x%016llx\n",
+			 __func__, dst[0], dst[1]);
+		ppc440spe_adma_pq_set_dest(sw_desc, dst, flags);
+		while (src_cnt--) {
+			ppc440spe_adma_pq_set_src(sw_desc, src[src_cnt],
+						  src_cnt);
+
+			/* NOTE: "Multi = 0 is equivalent to = 1" as it
+			 * stated in 440SPSPe_RAID6_Addendum_UM_1_17.pdf
+			 * doesn't work for RXOR with DMA0/1! Instead, multi=0
+			 * leads to zeroing source data after RXOR.
+			 * So, for P case set-up mult=1 explicitly.
+			 */
+			if (!(flags & DMA_PREP_PQ_DISABLE_Q))
+				mult = scf[src_cnt];
+			ppc440spe_adma_pq_set_src_mult(sw_desc,
+				mult, src_cnt,  dst_cnt - 1);
+		}
+
+		/* Setup byte count foreach slot just allocated */
+		sw_desc->async_tx.flags = flags;
+		list_for_each_entry(iter, &sw_desc->group_list,
+				chain_node) {
+			ppc440spe_desc_set_byte_count(iter,
+				ppc440spe_chan, len);
+			iter->unmap_len = len;
+		}
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	return sw_desc;
+}
+
+static struct ppc440spe_adma_desc_slot *ppc440spe_dma2_prep_pq(
+		struct ppc440spe_adma_chan *ppc440spe_chan,
+		dma_addr_t *dst, int dst_cnt, dma_addr_t *src, int src_cnt,
+		const unsigned char *scf, size_t len, unsigned long flags)
+{
+	int slot_cnt, descs_per_op;
+	struct ppc440spe_adma_desc_slot *sw_desc = NULL, *iter;
+	unsigned long op = 0;
+	unsigned char mult = 1;
+
+	BUG_ON(!dst_cnt);
+	/*pr_debug("%s: dst_cnt %d, src_cnt %d, len %d\n",
+		 __func__, dst_cnt, src_cnt, len);*/
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	descs_per_op = ppc440spe_dma2_pq_slot_count(src, src_cnt, len);
+	if (descs_per_op < 0) {
+		spin_unlock_bh(&ppc440spe_chan->lock);
+		return NULL;
+	}
+
+	/* depending on number of sources we have 1 or 2 RXOR chains */
+	slot_cnt = descs_per_op * dst_cnt;
+
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt, 1);
+	if (sw_desc) {
+		op = slot_cnt;
+		sw_desc->async_tx.flags = flags;
+		list_for_each_entry(iter, &sw_desc->group_list, chain_node) {
+			ppc440spe_desc_init_dma2pq(iter, dst_cnt, src_cnt,
+				--op ? 0 : flags);
+			ppc440spe_desc_set_byte_count(iter, ppc440spe_chan,
+				len);
+			iter->unmap_len = len;
+
+			ppc440spe_init_rxor_cursor(&(iter->rxor_cursor));
+			iter->rxor_cursor.len = len;
+			iter->descs_per_op = descs_per_op;
+		}
+		op = 0;
+		list_for_each_entry(iter, &sw_desc->group_list, chain_node) {
+			op++;
+			if (op % descs_per_op == 0)
+				ppc440spe_adma_init_dma2rxor_slot(iter, src,
+								  src_cnt);
+			if (likely(!list_is_last(&iter->chain_node,
+						 &sw_desc->group_list))) {
+				/* set 'next' pointer */
+				iter->hw_next =
+					list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+				ppc440spe_xor_set_link(iter, iter->hw_next);
+			} else {
+				/* this is the last descriptor. */
+				iter->hw_next = NULL;
+			}
+		}
+
+		/* fixup head descriptor */
+		sw_desc->dst_cnt = dst_cnt;
+		if (flags & DMA_PREP_ZERO_P)
+			set_bit(PPC440SPE_ZERO_P, &sw_desc->flags);
+		if (flags & DMA_PREP_ZERO_Q)
+			set_bit(PPC440SPE_ZERO_Q, &sw_desc->flags);
+
+		/* setup dst/src/mult */
+		ppc440spe_adma_pq_set_dest(sw_desc, dst, flags);
+
+		while (src_cnt--) {
+			/* handle descriptors (if dst_cnt == 2) inside
+			 * the ppc440spe_adma_pq_set_srcxxx() functions
+			 */
+			ppc440spe_adma_pq_set_src(sw_desc, src[src_cnt],
+						  src_cnt);
+			if (!(flags & DMA_PREP_PQ_DISABLE_Q))
+				mult = scf[src_cnt];
+			ppc440spe_adma_pq_set_src_mult(sw_desc,
+					mult, src_cnt, dst_cnt - 1);
+		}
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+	ppc440spe_desc_set_rxor_block_size(len);
+	return sw_desc;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_pq - prepare CDB (group) for a GF-XOR operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_pq(
+		struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
+		unsigned int src_cnt, const unsigned char *scf,
+		size_t len, unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc = NULL;
+	int dst_cnt = 0;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	ADMA_LL_DBG(prep_dma_pq_dbg(ppc440spe_chan->device->id,
+				    dst, src, src_cnt));
+	BUG_ON(!len);
+	BUG_ON(unlikely(len > PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT));
+	BUG_ON(!src_cnt);
+
+	if (src_cnt == 1 && dst[1] == src[0]) {
+		dma_addr_t dest[2];
+
+		/* dst[1] is real destination (Q) */
+		dest[0] = dst[1];
+		/* this is the page to multicast source data to */
+		dest[1] = ppc440spe_chan->qdest;
+		sw_desc = ppc440spe_dma01_prep_mult(ppc440spe_chan,
+				dest, 2, src, src_cnt, scf, len, flags);
+		return sw_desc ? &sw_desc->async_tx : NULL;
+	}
+
+	if (src_cnt == 2 && dst[1] == src[1]) {
+		sw_desc = ppc440spe_dma01_prep_sum_product(ppc440spe_chan,
+					&dst[1], src, 2, scf, len, flags);
+		return sw_desc ? &sw_desc->async_tx : NULL;
+	}
+
+	if (!(flags & DMA_PREP_PQ_DISABLE_P)) {
+		BUG_ON(!dst[0]);
+		dst_cnt++;
+		flags |= DMA_PREP_ZERO_P;
+	}
+
+	if (!(flags & DMA_PREP_PQ_DISABLE_Q)) {
+		BUG_ON(!dst[1]);
+		dst_cnt++;
+		flags |= DMA_PREP_ZERO_Q;
+	}
+
+	BUG_ON(!dst_cnt);
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s src_cnt: %d len: %u int_en: %d\n",
+		ppc440spe_chan->device->id, __func__, src_cnt, len,
+		flags & DMA_PREP_INTERRUPT ? 1 : 0);
+
+	switch (ppc440spe_chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		sw_desc = ppc440spe_dma01_prep_pq(ppc440spe_chan,
+				dst, dst_cnt, src, src_cnt, scf,
+				len, flags);
+		break;
+
+	case PPC440SPE_XOR_ID:
+		sw_desc = ppc440spe_dma2_prep_pq(ppc440spe_chan,
+				dst, dst_cnt, src, src_cnt, scf,
+				len, flags);
+		break;
+	}
+
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_pqzero_sum - prepare CDB group for
+ * a PQ_ZERO_SUM operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_pqzero_sum(
+		struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
+		unsigned int src_cnt, const unsigned char *scf, size_t len,
+		enum sum_check_flags *pqres, unsigned long flags)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *sw_desc, *iter;
+	dma_addr_t pdest, qdest;
+	int slot_cnt, slots_per_op, idst, dst_cnt;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+
+	if (flags & DMA_PREP_PQ_DISABLE_P)
+		pdest = 0;
+	else
+		pdest = pq[0];
+
+	if (flags & DMA_PREP_PQ_DISABLE_Q)
+		qdest = 0;
+	else
+		qdest = pq[1];
+
+	ADMA_LL_DBG(prep_dma_pqzero_sum_dbg(ppc440spe_chan->device->id,
+					    src, src_cnt, scf));
+
+	/* Always use WXOR for P/Q calculations (two destinations).
+	 * Need 1 or 2 extra slots to verify results are zero.
+	 */
+	idst = dst_cnt = (pdest && qdest) ? 2 : 1;
+
+	/* One additional slot per destination to clone P/Q
+	 * before calculation (we have to preserve destinations).
+	 */
+	slot_cnt = src_cnt + dst_cnt * 2;
+	slots_per_op = 1;
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	sw_desc = ppc440spe_adma_alloc_slots(ppc440spe_chan, slot_cnt,
+					     slots_per_op);
+	if (sw_desc) {
+		ppc440spe_desc_init_dma01pqzero_sum(sw_desc, dst_cnt, src_cnt);
+
+		/* Setup byte count for each slot just allocated */
+		sw_desc->async_tx.flags = flags;
+		list_for_each_entry(iter, &sw_desc->group_list, chain_node) {
+			ppc440spe_desc_set_byte_count(iter, ppc440spe_chan,
+						      len);
+			iter->unmap_len = len;
+		}
+
+		if (pdest) {
+			struct dma_cdb *hw_desc;
+			struct ppc440spe_adma_chan *chan;
+
+			iter = sw_desc->group_head;
+			chan = to_ppc440spe_adma_chan(iter->async_tx.chan);
+			memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+			iter->hw_next = list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+			iter->src_cnt = 0;
+			iter->dst_cnt = 0;
+			ppc440spe_desc_set_dest_addr(iter, chan, 0,
+						     ppc440spe_chan->pdest, 0);
+			ppc440spe_desc_set_src_addr(iter, chan, 0, 0, pdest);
+			ppc440spe_desc_set_byte_count(iter, ppc440spe_chan,
+						      len);
+			iter->unmap_len = 0;
+			/* override pdest to preserve original P */
+			pdest = ppc440spe_chan->pdest;
+		}
+		if (qdest) {
+			struct dma_cdb *hw_desc;
+			struct ppc440spe_adma_chan *chan;
+
+			iter = list_first_entry(&sw_desc->group_list,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			chan = to_ppc440spe_adma_chan(iter->async_tx.chan);
+
+			if (pdest) {
+				iter = list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			}
+
+			memset(iter->hw_desc, 0, sizeof(struct dma_cdb));
+			iter->hw_next = list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			hw_desc = iter->hw_desc;
+			hw_desc->opc = DMA_CDB_OPC_MV_SG1_SG2;
+			iter->src_cnt = 0;
+			iter->dst_cnt = 0;
+			ppc440spe_desc_set_dest_addr(iter, chan, 0,
+						     ppc440spe_chan->qdest, 0);
+			ppc440spe_desc_set_src_addr(iter, chan, 0, 0, qdest);
+			ppc440spe_desc_set_byte_count(iter, ppc440spe_chan,
+						      len);
+			iter->unmap_len = 0;
+			/* override qdest to preserve original Q */
+			qdest = ppc440spe_chan->qdest;
+		}
+
+		/* Setup destinations for P/Q ops */
+		ppc440spe_adma_pqzero_sum_set_dest(sw_desc, pdest, qdest);
+
+		/* Setup zero QWORDs into DCHECK CDBs */
+		idst = dst_cnt;
+		list_for_each_entry_reverse(iter, &sw_desc->group_list,
+					    chain_node) {
+			/*
+			 * The last CDB corresponds to Q-parity check,
+			 * the one before last CDB corresponds
+			 * P-parity check
+			 */
+			if (idst == DMA_DEST_MAX_NUM) {
+				if (idst == dst_cnt) {
+					set_bit(PPC440SPE_DESC_QCHECK,
+						&iter->flags);
+				} else {
+					set_bit(PPC440SPE_DESC_PCHECK,
+						&iter->flags);
+				}
+			} else {
+				if (qdest) {
+					set_bit(PPC440SPE_DESC_QCHECK,
+						&iter->flags);
+				} else {
+					set_bit(PPC440SPE_DESC_PCHECK,
+						&iter->flags);
+				}
+			}
+			iter->xor_check_result = pqres;
+
+			/*
+			 * set it to zero, if check fail then result will
+			 * be updated
+			 */
+			*iter->xor_check_result = 0;
+			ppc440spe_desc_set_dcheck(iter, ppc440spe_chan,
+				ppc440spe_qword);
+
+			if (!(--dst_cnt))
+				break;
+		}
+
+		/* Setup sources and mults for P/Q ops */
+		list_for_each_entry_continue_reverse(iter, &sw_desc->group_list,
+						     chain_node) {
+			struct ppc440spe_adma_chan *chan;
+			u32 mult_dst;
+
+			chan = to_ppc440spe_adma_chan(iter->async_tx.chan);
+			ppc440spe_desc_set_src_addr(iter, chan, 0,
+						    DMA_CUED_XOR_HB,
+						    src[src_cnt - 1]);
+			if (qdest) {
+				mult_dst = (dst_cnt - 1) ? DMA_CDB_SG_DST2 :
+							   DMA_CDB_SG_DST1;
+				ppc440spe_desc_set_src_mult(iter, chan,
+							    DMA_CUED_MULT1_OFF,
+							    mult_dst,
+							    scf[src_cnt - 1]);
+			}
+			if (!(--src_cnt))
+				break;
+		}
+	}
+	spin_unlock_bh(&ppc440spe_chan->lock);
+	return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+/**
+ * ppc440spe_adma_prep_dma_xor_zero_sum - prepare CDB group for
+ * XOR ZERO_SUM operation
+ */
+static struct dma_async_tx_descriptor *ppc440spe_adma_prep_dma_xor_zero_sum(
+		struct dma_chan *chan, dma_addr_t *src, unsigned int src_cnt,
+		size_t len, enum sum_check_flags *result, unsigned long flags)
+{
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t pq[2];
+
+	/* validate P, disable Q */
+	pq[0] = src[0];
+	pq[1] = 0;
+	flags |= DMA_PREP_PQ_DISABLE_Q;
+
+	tx = ppc440spe_adma_prep_dma_pqzero_sum(chan, pq, &src[1],
+						src_cnt - 1, 0, len,
+						result, flags);
+	return tx;
+}
+
+/**
+ * ppc440spe_adma_set_dest - set destination address into descriptor
+ */
+static void ppc440spe_adma_set_dest(struct ppc440spe_adma_desc_slot *sw_desc,
+		dma_addr_t addr, int index)
+{
+	struct ppc440spe_adma_chan *chan;
+
+	BUG_ON(index >= sw_desc->dst_cnt);
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* to do: support transfers lengths >
+		 * PPC440SPE_ADMA_DMA/XOR_MAX_BYTE_COUNT
+		 */
+		ppc440spe_desc_set_dest_addr(sw_desc->group_head,
+			chan, 0, addr, index);
+		break;
+	case PPC440SPE_XOR_ID:
+		sw_desc = ppc440spe_get_group_entry(sw_desc, index);
+		ppc440spe_desc_set_dest_addr(sw_desc,
+			chan, 0, addr, index);
+		break;
+	}
+}
+
+static void ppc440spe_adma_pq_zero_op(struct ppc440spe_adma_desc_slot *iter,
+		struct ppc440spe_adma_chan *chan, dma_addr_t addr)
+{
+	/*  To clear destinations update the descriptor
+	 * (P or Q depending on index) as follows:
+	 * addr is destination (0 corresponds to SG2):
+	 */
+	ppc440spe_desc_set_dest_addr(iter, chan, DMA_CUED_XOR_BASE, addr, 0);
+
+	/* ... and the addr is source: */
+	ppc440spe_desc_set_src_addr(iter, chan, 0, DMA_CUED_XOR_HB, addr);
+
+	/* addr is always SG2 then the mult is always DST1 */
+	ppc440spe_desc_set_src_mult(iter, chan, DMA_CUED_MULT1_OFF,
+				    DMA_CDB_SG_DST1, 1);
+}
+
+/**
+ * ppc440spe_adma_pq_set_dest - set destination address into descriptor
+ * for the PQXOR operation
+ */
+static void ppc440spe_adma_pq_set_dest(struct ppc440spe_adma_desc_slot *sw_desc,
+		dma_addr_t *addrs, unsigned long flags)
+{
+	struct ppc440spe_adma_desc_slot *iter;
+	struct ppc440spe_adma_chan *chan;
+	dma_addr_t paddr, qaddr;
+	dma_addr_t addr = 0, ppath, qpath;
+	int index = 0, i;
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+
+	if (flags & DMA_PREP_PQ_DISABLE_P)
+		paddr = 0;
+	else
+		paddr = addrs[0];
+
+	if (flags & DMA_PREP_PQ_DISABLE_Q)
+		qaddr = 0;
+	else
+		qaddr = addrs[1];
+
+	if (!paddr || !qaddr)
+		addr = paddr ? paddr : qaddr;
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* walk through the WXOR source list and set P/Q-destinations
+		 * for each slot:
+		 */
+		if (!test_bit(PPC440SPE_DESC_RXOR, &sw_desc->flags)) {
+			/* This is WXOR-only chain; may have 1/2 zero descs */
+			if (test_bit(PPC440SPE_ZERO_P, &sw_desc->flags))
+				index++;
+			if (test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags))
+				index++;
+
+			iter = ppc440spe_get_group_entry(sw_desc, index);
+			if (addr) {
+				/* one destination */
+				list_for_each_entry_from(iter,
+					&sw_desc->group_list, chain_node)
+					ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, addr, 0);
+			} else {
+				/* two destinations */
+				list_for_each_entry_from(iter,
+					&sw_desc->group_list, chain_node) {
+					ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, paddr, 0);
+					ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, qaddr, 1);
+				}
+			}
+
+			if (index) {
+				/*  To clear destinations update the descriptor
+				 * (1st,2nd, or both depending on flags)
+				 */
+				index = 0;
+				if (test_bit(PPC440SPE_ZERO_P,
+						&sw_desc->flags)) {
+					iter = ppc440spe_get_group_entry(
+							sw_desc, index++);
+					ppc440spe_adma_pq_zero_op(iter, chan,
+							paddr);
+				}
+
+				if (test_bit(PPC440SPE_ZERO_Q,
+						&sw_desc->flags)) {
+					iter = ppc440spe_get_group_entry(
+							sw_desc, index++);
+					ppc440spe_adma_pq_zero_op(iter, chan,
+							qaddr);
+				}
+
+				return;
+			}
+		} else {
+			/* This is RXOR-only or RXOR/WXOR mixed chain */
+
+			/* If we want to include destination into calculations,
+			 * then make dest addresses cued with mult=1 (XOR).
+			 */
+			ppath = test_bit(PPC440SPE_ZERO_P, &sw_desc->flags) ?
+					DMA_CUED_XOR_HB :
+					DMA_CUED_XOR_BASE |
+						(1 << DMA_CUED_MULT1_OFF);
+			qpath = test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags) ?
+					DMA_CUED_XOR_HB :
+					DMA_CUED_XOR_BASE |
+						(1 << DMA_CUED_MULT1_OFF);
+
+			/* Setup destination(s) in RXOR slot(s) */
+			iter = ppc440spe_get_group_entry(sw_desc, index++);
+			ppc440spe_desc_set_dest_addr(iter, chan,
+						paddr ? ppath : qpath,
+						paddr ? paddr : qaddr, 0);
+			if (!addr) {
+				/* two destinations */
+				iter = ppc440spe_get_group_entry(sw_desc,
+								 index++);
+				ppc440spe_desc_set_dest_addr(iter, chan,
+						qpath, qaddr, 0);
+			}
+
+			if (test_bit(PPC440SPE_DESC_WXOR, &sw_desc->flags)) {
+				/* Setup destination(s) in remaining WXOR
+				 * slots
+				 */
+				iter = ppc440spe_get_group_entry(sw_desc,
+								 index);
+				if (addr) {
+					/* one destination */
+					list_for_each_entry_from(iter,
+					    &sw_desc->group_list,
+					    chain_node)
+						ppc440spe_desc_set_dest_addr(
+							iter, chan,
+							DMA_CUED_XOR_BASE,
+							addr, 0);
+
+				} else {
+					/* two destinations */
+					list_for_each_entry_from(iter,
+					    &sw_desc->group_list,
+					    chain_node) {
+						ppc440spe_desc_set_dest_addr(
+							iter, chan,
+							DMA_CUED_XOR_BASE,
+							paddr, 0);
+						ppc440spe_desc_set_dest_addr(
+							iter, chan,
+							DMA_CUED_XOR_BASE,
+							qaddr, 1);
+					}
+				}
+			}
+
+		}
+		break;
+
+	case PPC440SPE_XOR_ID:
+		/* DMA2 descriptors have only 1 destination, so there are
+		 * two chains - one for each dest.
+		 * If we want to include destination into calculations,
+		 * then make dest addresses cued with mult=1 (XOR).
+		 */
+		ppath = test_bit(PPC440SPE_ZERO_P, &sw_desc->flags) ?
+				DMA_CUED_XOR_HB :
+				DMA_CUED_XOR_BASE |
+					(1 << DMA_CUED_MULT1_OFF);
+
+		qpath = test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags) ?
+				DMA_CUED_XOR_HB :
+				DMA_CUED_XOR_BASE |
+					(1 << DMA_CUED_MULT1_OFF);
+
+		iter = ppc440spe_get_group_entry(sw_desc, 0);
+		for (i = 0; i < sw_desc->descs_per_op; i++) {
+			ppc440spe_desc_set_dest_addr(iter, chan,
+				paddr ? ppath : qpath,
+				paddr ? paddr : qaddr, 0);
+			iter = list_entry(iter->chain_node.next,
+					  struct ppc440spe_adma_desc_slot,
+					  chain_node);
+		}
+
+		if (!addr) {
+			/* Two destinations; setup Q here */
+			iter = ppc440spe_get_group_entry(sw_desc,
+				sw_desc->descs_per_op);
+			for (i = 0; i < sw_desc->descs_per_op; i++) {
+				ppc440spe_desc_set_dest_addr(iter,
+					chan, qpath, qaddr, 0);
+				iter = list_entry(iter->chain_node.next,
+						struct ppc440spe_adma_desc_slot,
+						chain_node);
+			}
+		}
+
+		break;
+	}
+}
+
+/**
+ * ppc440spe_adma_pq_zero_sum_set_dest - set destination address into descriptor
+ * for the PQ_ZERO_SUM operation
+ */
+static void ppc440spe_adma_pqzero_sum_set_dest(
+		struct ppc440spe_adma_desc_slot *sw_desc,
+		dma_addr_t paddr, dma_addr_t qaddr)
+{
+	struct ppc440spe_adma_desc_slot *iter, *end;
+	struct ppc440spe_adma_chan *chan;
+	dma_addr_t addr = 0;
+	int idx;
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+
+	/* walk through the WXOR source list and set P/Q-destinations
+	 * for each slot
+	 */
+	idx = (paddr && qaddr) ? 2 : 1;
+	/* set end */
+	list_for_each_entry_reverse(end, &sw_desc->group_list,
+				    chain_node) {
+		if (!(--idx))
+			break;
+	}
+	/* set start */
+	idx = (paddr && qaddr) ? 2 : 1;
+	iter = ppc440spe_get_group_entry(sw_desc, idx);
+
+	if (paddr && qaddr) {
+		/* two destinations */
+		list_for_each_entry_from(iter, &sw_desc->group_list,
+					 chain_node) {
+			if (unlikely(iter == end))
+				break;
+			ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, paddr, 0);
+			ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, qaddr, 1);
+		}
+	} else {
+		/* one destination */
+		addr = paddr ? paddr : qaddr;
+		list_for_each_entry_from(iter, &sw_desc->group_list,
+					 chain_node) {
+			if (unlikely(iter == end))
+				break;
+			ppc440spe_desc_set_dest_addr(iter, chan,
+						DMA_CUED_XOR_BASE, addr, 0);
+		}
+	}
+
+	/*  The remaining descriptors are DATACHECK. These have no need in
+	 * destination. Actually, these destinations are used there
+	 * as sources for check operation. So, set addr as source.
+	 */
+	ppc440spe_desc_set_src_addr(end, chan, 0, 0, addr ? addr : paddr);
+
+	if (!addr) {
+		end = list_entry(end->chain_node.next,
+				 struct ppc440spe_adma_desc_slot, chain_node);
+		ppc440spe_desc_set_src_addr(end, chan, 0, 0, qaddr);
+	}
+}
+
+/**
+ * ppc440spe_desc_set_xor_src_cnt - set source count into descriptor
+ */
+static inline void ppc440spe_desc_set_xor_src_cnt(
+			struct ppc440spe_adma_desc_slot *desc,
+			int src_cnt)
+{
+	struct xor_cb *hw_desc = desc->hw_desc;
+
+	hw_desc->cbc &= ~XOR_CDCR_OAC_MSK;
+	hw_desc->cbc |= src_cnt;
+}
+
+/**
+ * ppc440spe_adma_pq_set_src - set source address into descriptor
+ */
+static void ppc440spe_adma_pq_set_src(struct ppc440spe_adma_desc_slot *sw_desc,
+		dma_addr_t addr, int index)
+{
+	struct ppc440spe_adma_chan *chan;
+	dma_addr_t haddr = 0;
+	struct ppc440spe_adma_desc_slot *iter = NULL;
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		/* DMA0,1 may do: WXOR, RXOR, RXOR+WXORs chain
+		 */
+		if (test_bit(PPC440SPE_DESC_RXOR, &sw_desc->flags)) {
+			/* RXOR-only or RXOR/WXOR operation */
+			int iskip = test_bit(PPC440SPE_DESC_RXOR12,
+				&sw_desc->flags) ?  2 : 3;
+
+			if (index == 0) {
+				/* 1st slot (RXOR) */
+				/* setup sources region (R1-2-3, R1-2-4,
+				 * or R1-2-5)
+				 */
+				if (test_bit(PPC440SPE_DESC_RXOR12,
+						&sw_desc->flags))
+					haddr = DMA_RXOR12 <<
+						DMA_CUED_REGION_OFF;
+				else if (test_bit(PPC440SPE_DESC_RXOR123,
+				    &sw_desc->flags))
+					haddr = DMA_RXOR123 <<
+						DMA_CUED_REGION_OFF;
+				else if (test_bit(PPC440SPE_DESC_RXOR124,
+				    &sw_desc->flags))
+					haddr = DMA_RXOR124 <<
+						DMA_CUED_REGION_OFF;
+				else if (test_bit(PPC440SPE_DESC_RXOR125,
+				    &sw_desc->flags))
+					haddr = DMA_RXOR125 <<
+						DMA_CUED_REGION_OFF;
+				else
+					BUG();
+				haddr |= DMA_CUED_XOR_BASE;
+				iter = ppc440spe_get_group_entry(sw_desc, 0);
+			} else if (index < iskip) {
+				/* 1st slot (RXOR)
+				 * shall actually set source address only once
+				 * instead of first <iskip>
+				 */
+				iter = NULL;
+			} else {
+				/* 2nd/3d and next slots (WXOR);
+				 * skip first slot with RXOR
+				 */
+				haddr = DMA_CUED_XOR_HB;
+				iter = ppc440spe_get_group_entry(sw_desc,
+				    index - iskip + sw_desc->dst_cnt);
+			}
+		} else {
+			int znum = 0;
+
+			/* WXOR-only operation; skip first slots with
+			 * zeroing destinations
+			 */
+			if (test_bit(PPC440SPE_ZERO_P, &sw_desc->flags))
+				znum++;
+			if (test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags))
+				znum++;
+
+			haddr = DMA_CUED_XOR_HB;
+			iter = ppc440spe_get_group_entry(sw_desc,
+					index + znum);
+		}
+
+		if (likely(iter)) {
+			ppc440spe_desc_set_src_addr(iter, chan, 0, haddr, addr);
+
+			if (!index &&
+			    test_bit(PPC440SPE_DESC_RXOR, &sw_desc->flags) &&
+			    sw_desc->dst_cnt == 2) {
+				/* if we have two destinations for RXOR, then
+				 * setup source in the second descr too
+				 */
+				iter = ppc440spe_get_group_entry(sw_desc, 1);
+				ppc440spe_desc_set_src_addr(iter, chan, 0,
+					haddr, addr);
+			}
+		}
+		break;
+
+	case PPC440SPE_XOR_ID:
+		/* DMA2 may do Biskup */
+		iter = sw_desc->group_head;
+		if (iter->dst_cnt == 2) {
+			/* both P & Q calculations required; set P src here */
+			ppc440spe_adma_dma2rxor_set_src(iter, index, addr);
+
+			/* this is for Q */
+			iter = ppc440spe_get_group_entry(sw_desc,
+				sw_desc->descs_per_op);
+		}
+		ppc440spe_adma_dma2rxor_set_src(iter, index, addr);
+		break;
+	}
+}
+
+/**
+ * ppc440spe_adma_memcpy_xor_set_src - set source address into descriptor
+ */
+static void ppc440spe_adma_memcpy_xor_set_src(
+		struct ppc440spe_adma_desc_slot *sw_desc,
+		dma_addr_t addr, int index)
+{
+	struct ppc440spe_adma_chan *chan;
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+	sw_desc = sw_desc->group_head;
+
+	if (likely(sw_desc))
+		ppc440spe_desc_set_src_addr(sw_desc, chan, index, 0, addr);
+}
+
+/**
+ * ppc440spe_adma_dma2rxor_inc_addr  -
+ */
+static void ppc440spe_adma_dma2rxor_inc_addr(
+		struct ppc440spe_adma_desc_slot *desc,
+		struct ppc440spe_rxor *cursor, int index, int src_cnt)
+{
+	cursor->addr_count++;
+	if (index == src_cnt - 1) {
+		ppc440spe_desc_set_xor_src_cnt(desc, cursor->addr_count);
+	} else if (cursor->addr_count == XOR_MAX_OPS) {
+		ppc440spe_desc_set_xor_src_cnt(desc, cursor->addr_count);
+		cursor->addr_count = 0;
+		cursor->desc_count++;
+	}
+}
+
+/**
+ * ppc440spe_adma_dma2rxor_prep_src - setup RXOR types in DMA2 CDB
+ */
+static int ppc440spe_adma_dma2rxor_prep_src(
+		struct ppc440spe_adma_desc_slot *hdesc,
+		struct ppc440spe_rxor *cursor, int index,
+		int src_cnt, u32 addr)
+{
+	int rval = 0;
+	u32 sign;
+	struct ppc440spe_adma_desc_slot *desc = hdesc;
+	int i;
+
+	for (i = 0; i < cursor->desc_count; i++) {
+		desc = list_entry(hdesc->chain_node.next,
+				  struct ppc440spe_adma_desc_slot,
+				  chain_node);
+	}
+
+	switch (cursor->state) {
+	case 0:
+		if (addr == cursor->addrl + cursor->len) {
+			/* direct RXOR */
+			cursor->state = 1;
+			cursor->xor_count++;
+			if (index == src_cnt-1) {
+				ppc440spe_rxor_set_region(desc,
+					cursor->addr_count,
+					DMA_RXOR12 << DMA_CUED_REGION_OFF);
+				ppc440spe_adma_dma2rxor_inc_addr(
+					desc, cursor, index, src_cnt);
+			}
+		} else if (cursor->addrl == addr + cursor->len) {
+			/* reverse RXOR */
+			cursor->state = 1;
+			cursor->xor_count++;
+			set_bit(cursor->addr_count, &desc->reverse_flags[0]);
+			if (index == src_cnt-1) {
+				ppc440spe_rxor_set_region(desc,
+					cursor->addr_count,
+					DMA_RXOR12 << DMA_CUED_REGION_OFF);
+				ppc440spe_adma_dma2rxor_inc_addr(
+					desc, cursor, index, src_cnt);
+			}
+		} else {
+			printk(KERN_ERR "Cannot build "
+				"DMA2 RXOR command block.\n");
+			BUG();
+		}
+		break;
+	case 1:
+		sign = test_bit(cursor->addr_count,
+				desc->reverse_flags)
+			? -1 : 1;
+		if (index == src_cnt-2 || (sign == -1
+			&& addr != cursor->addrl - 2*cursor->len)) {
+			cursor->state = 0;
+			cursor->xor_count = 1;
+			cursor->addrl = addr;
+			ppc440spe_rxor_set_region(desc,
+				cursor->addr_count,
+				DMA_RXOR12 << DMA_CUED_REGION_OFF);
+			ppc440spe_adma_dma2rxor_inc_addr(
+				desc, cursor, index, src_cnt);
+		} else if (addr == cursor->addrl + 2*sign*cursor->len) {
+			cursor->state = 2;
+			cursor->xor_count = 0;
+			ppc440spe_rxor_set_region(desc,
+				cursor->addr_count,
+				DMA_RXOR123 << DMA_CUED_REGION_OFF);
+			if (index == src_cnt-1) {
+				ppc440spe_adma_dma2rxor_inc_addr(
+					desc, cursor, index, src_cnt);
+			}
+		} else if (addr == cursor->addrl + 3*cursor->len) {
+			cursor->state = 2;
+			cursor->xor_count = 0;
+			ppc440spe_rxor_set_region(desc,
+				cursor->addr_count,
+				DMA_RXOR124 << DMA_CUED_REGION_OFF);
+			if (index == src_cnt-1) {
+				ppc440spe_adma_dma2rxor_inc_addr(
+					desc, cursor, index, src_cnt);
+			}
+		} else if (addr == cursor->addrl + 4*cursor->len) {
+			cursor->state = 2;
+			cursor->xor_count = 0;
+			ppc440spe_rxor_set_region(desc,
+				cursor->addr_count,
+				DMA_RXOR125 << DMA_CUED_REGION_OFF);
+			if (index == src_cnt-1) {
+				ppc440spe_adma_dma2rxor_inc_addr(
+					desc, cursor, index, src_cnt);
+			}
+		} else {
+			cursor->state = 0;
+			cursor->xor_count = 1;
+			cursor->addrl = addr;
+			ppc440spe_rxor_set_region(desc,
+				cursor->addr_count,
+				DMA_RXOR12 << DMA_CUED_REGION_OFF);
+			ppc440spe_adma_dma2rxor_inc_addr(
+				desc, cursor, index, src_cnt);
+		}
+		break;
+	case 2:
+		cursor->state = 0;
+		cursor->addrl = addr;
+		cursor->xor_count++;
+		if (index) {
+			ppc440spe_adma_dma2rxor_inc_addr(
+				desc, cursor, index, src_cnt);
+		}
+		break;
+	}
+
+	return rval;
+}
+
+/**
+ * ppc440spe_adma_dma2rxor_set_src - set RXOR source address; it's assumed that
+ *	ppc440spe_adma_dma2rxor_prep_src() has already done prior this call
+ */
+static void ppc440spe_adma_dma2rxor_set_src(
+		struct ppc440spe_adma_desc_slot *desc,
+		int index, dma_addr_t addr)
+{
+	struct xor_cb *xcb = desc->hw_desc;
+	int k = 0, op = 0, lop = 0;
+
+	/* get the RXOR operand which corresponds to index addr */
+	while (op <= index) {
+		lop = op;
+		if (k == XOR_MAX_OPS) {
+			k = 0;
+			desc = list_entry(desc->chain_node.next,
+				struct ppc440spe_adma_desc_slot, chain_node);
+			xcb = desc->hw_desc;
+
+		}
+		if ((xcb->ops[k++].h & (DMA_RXOR12 << DMA_CUED_REGION_OFF)) ==
+		    (DMA_RXOR12 << DMA_CUED_REGION_OFF))
+			op += 2;
+		else
+			op += 3;
+	}
+
+	BUG_ON(k < 1);
+
+	if (test_bit(k-1, desc->reverse_flags)) {
+		/* reverse operand order; put last op in RXOR group */
+		if (index == op - 1)
+			ppc440spe_rxor_set_src(desc, k - 1, addr);
+	} else {
+		/* direct operand order; put first op in RXOR group */
+		if (index == lop)
+			ppc440spe_rxor_set_src(desc, k - 1, addr);
+	}
+}
+
+/**
+ * ppc440spe_adma_dma2rxor_set_mult - set RXOR multipliers; it's assumed that
+ *	ppc440spe_adma_dma2rxor_prep_src() has already done prior this call
+ */
+static void ppc440spe_adma_dma2rxor_set_mult(
+		struct ppc440spe_adma_desc_slot *desc,
+		int index, u8 mult)
+{
+	struct xor_cb *xcb = desc->hw_desc;
+	int k = 0, op = 0, lop = 0;
+
+	/* get the RXOR operand which corresponds to index mult */
+	while (op <= index) {
+		lop = op;
+		if (k == XOR_MAX_OPS) {
+			k = 0;
+			desc = list_entry(desc->chain_node.next,
+					  struct ppc440spe_adma_desc_slot,
+					  chain_node);
+			xcb = desc->hw_desc;
+
+		}
+		if ((xcb->ops[k++].h & (DMA_RXOR12 << DMA_CUED_REGION_OFF)) ==
+		    (DMA_RXOR12 << DMA_CUED_REGION_OFF))
+			op += 2;
+		else
+			op += 3;
+	}
+
+	BUG_ON(k < 1);
+	if (test_bit(k-1, desc->reverse_flags)) {
+		/* reverse order */
+		ppc440spe_rxor_set_mult(desc, k - 1, op - index - 1, mult);
+	} else {
+		/* direct order */
+		ppc440spe_rxor_set_mult(desc, k - 1, index - lop, mult);
+	}
+}
+
+/**
+ * ppc440spe_init_rxor_cursor -
+ */
+static void ppc440spe_init_rxor_cursor(struct ppc440spe_rxor *cursor)
+{
+	memset(cursor, 0, sizeof(struct ppc440spe_rxor));
+	cursor->state = 2;
+}
+
+/**
+ * ppc440spe_adma_pq_set_src_mult - set multiplication coefficient into
+ * descriptor for the PQXOR operation
+ */
+static void ppc440spe_adma_pq_set_src_mult(
+		struct ppc440spe_adma_desc_slot *sw_desc,
+		unsigned char mult, int index, int dst_pos)
+{
+	struct ppc440spe_adma_chan *chan;
+	u32 mult_idx, mult_dst;
+	struct ppc440spe_adma_desc_slot *iter = NULL, *iter1 = NULL;
+
+	chan = to_ppc440spe_adma_chan(sw_desc->async_tx.chan);
+
+	switch (chan->device->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		if (test_bit(PPC440SPE_DESC_RXOR, &sw_desc->flags)) {
+			int region = test_bit(PPC440SPE_DESC_RXOR12,
+					&sw_desc->flags) ? 2 : 3;
+
+			if (index < region) {
+				/* RXOR multipliers */
+				iter = ppc440spe_get_group_entry(sw_desc,
+					sw_desc->dst_cnt - 1);
+				if (sw_desc->dst_cnt == 2)
+					iter1 = ppc440spe_get_group_entry(
+							sw_desc, 0);
+
+				mult_idx = DMA_CUED_MULT1_OFF + (index << 3);
+				mult_dst = DMA_CDB_SG_SRC;
+			} else {
+				/* WXOR multiplier */
+				iter = ppc440spe_get_group_entry(sw_desc,
+							index - region +
+							sw_desc->dst_cnt);
+				mult_idx = DMA_CUED_MULT1_OFF;
+				mult_dst = dst_pos ? DMA_CDB_SG_DST2 :
+						     DMA_CDB_SG_DST1;
+			}
+		} else {
+			int znum = 0;
+
+			/* WXOR-only;
+			 * skip first slots with destinations (if ZERO_DST has
+			 * place)
+			 */
+			if (test_bit(PPC440SPE_ZERO_P, &sw_desc->flags))
+				znum++;
+			if (test_bit(PPC440SPE_ZERO_Q, &sw_desc->flags))
+				znum++;
+
+			iter = ppc440spe_get_group_entry(sw_desc, index + znum);
+			mult_idx = DMA_CUED_MULT1_OFF;
+			mult_dst = dst_pos ? DMA_CDB_SG_DST2 : DMA_CDB_SG_DST1;
+		}
+
+		if (likely(iter)) {
+			ppc440spe_desc_set_src_mult(iter, chan,
+				mult_idx, mult_dst, mult);
+
+			if (unlikely(iter1)) {
+				/* if we have two destinations for RXOR, then
+				 * we've just set Q mult. Set-up P now.
+				 */
+				ppc440spe_desc_set_src_mult(iter1, chan,
+					mult_idx, mult_dst, 1);
+			}
+
+		}
+		break;
+
+	case PPC440SPE_XOR_ID:
+		iter = sw_desc->group_head;
+		if (sw_desc->dst_cnt == 2) {
+			/* both P & Q calculations required; set P mult here */
+			ppc440spe_adma_dma2rxor_set_mult(iter, index, 1);
+
+			/* and then set Q mult */
+			iter = ppc440spe_get_group_entry(sw_desc,
+			       sw_desc->descs_per_op);
+		}
+		ppc440spe_adma_dma2rxor_set_mult(iter, index, mult);
+		break;
+	}
+}
+
+/**
+ * ppc440spe_adma_free_chan_resources - free the resources allocated
+ */
+static void ppc440spe_adma_free_chan_resources(struct dma_chan *chan)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	struct ppc440spe_adma_desc_slot *iter, *_iter;
+	int in_use_descs = 0;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+	ppc440spe_adma_slot_cleanup(ppc440spe_chan);
+
+	spin_lock_bh(&ppc440spe_chan->lock);
+	list_for_each_entry_safe(iter, _iter, &ppc440spe_chan->chain,
+					chain_node) {
+		in_use_descs++;
+		list_del(&iter->chain_node);
+	}
+	list_for_each_entry_safe_reverse(iter, _iter,
+			&ppc440spe_chan->all_slots, slot_node) {
+		list_del(&iter->slot_node);
+		kfree(iter);
+		ppc440spe_chan->slots_allocated--;
+	}
+	ppc440spe_chan->last_used = NULL;
+
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d %s slots_allocated %d\n",
+		ppc440spe_chan->device->id,
+		__func__, ppc440spe_chan->slots_allocated);
+	spin_unlock_bh(&ppc440spe_chan->lock);
+
+	/* one is ok since we left it on there on purpose */
+	if (in_use_descs > 1)
+		printk(KERN_ERR "SPE: Freeing %d in use descriptors!\n",
+			in_use_descs - 1);
+}
+
+/**
+ * ppc440spe_adma_is_complete - poll the status of an ADMA transaction
+ * @chan: ADMA channel handle
+ * @cookie: ADMA transaction identifier
+ */
+static enum dma_status ppc440spe_adma_is_complete(struct dma_chan *chan,
+	dma_cookie_t cookie, dma_cookie_t *done, dma_cookie_t *used)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	enum dma_status ret;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+	last_used = chan->cookie;
+	last_complete = ppc440spe_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret == DMA_SUCCESS)
+		return ret;
+
+	ppc440spe_adma_slot_cleanup(ppc440spe_chan);
+
+	last_used = chan->cookie;
+	last_complete = ppc440spe_chan->completed_cookie;
+
+	if (done)
+		*done = last_complete;
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/**
+ * ppc440spe_adma_eot_handler - end of transfer interrupt handler
+ */
+static irqreturn_t ppc440spe_adma_eot_handler(int irq, void *data)
+{
+	struct ppc440spe_adma_chan *chan = data;
+
+	dev_dbg(chan->device->common.dev,
+		"ppc440spe adma%d: %s\n", chan->device->id, __func__);
+
+	tasklet_schedule(&chan->irq_tasklet);
+	ppc440spe_adma_device_clear_eot_status(chan);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ppc440spe_adma_err_handler - DMA error interrupt handler;
+ *	do the same things as a eot handler
+ */
+static irqreturn_t ppc440spe_adma_err_handler(int irq, void *data)
+{
+	struct ppc440spe_adma_chan *chan = data;
+
+	dev_dbg(chan->device->common.dev,
+		"ppc440spe adma%d: %s\n", chan->device->id, __func__);
+
+	tasklet_schedule(&chan->irq_tasklet);
+	ppc440spe_adma_device_clear_eot_status(chan);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ppc440spe_test_callback - called when test operation has been done
+ */
+static void ppc440spe_test_callback(void *unused)
+{
+	complete(&ppc440spe_r6_test_comp);
+}
+
+/**
+ * ppc440spe_adma_issue_pending - flush all pending descriptors to h/w
+ */
+static void ppc440spe_adma_issue_pending(struct dma_chan *chan)
+{
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+
+	ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+	dev_dbg(ppc440spe_chan->device->common.dev,
+		"ppc440spe adma%d: %s %d \n", ppc440spe_chan->device->id,
+		__func__, ppc440spe_chan->pending);
+
+	if (ppc440spe_chan->pending) {
+		ppc440spe_chan->pending = 0;
+		ppc440spe_chan_append(ppc440spe_chan);
+	}
+}
+
+/**
+ * ppc440spe_chan_start_null_xor - initiate the first XOR operation (DMA engines
+ *	use FIFOs (as opposite to chains used in XOR) so this is a XOR
+ *	specific operation)
+ */
+static void ppc440spe_chan_start_null_xor(struct ppc440spe_adma_chan *chan)
+{
+	struct ppc440spe_adma_desc_slot *sw_desc, *group_start;
+	dma_cookie_t cookie;
+	int slot_cnt, slots_per_op;
+
+	dev_dbg(chan->device->common.dev,
+		"ppc440spe adma%d: %s\n", chan->device->id, __func__);
+
+	spin_lock_bh(&chan->lock);
+	slot_cnt = ppc440spe_chan_xor_slot_count(0, 2, &slots_per_op);
+	sw_desc = ppc440spe_adma_alloc_slots(chan, slot_cnt, slots_per_op);
+	if (sw_desc) {
+		group_start = sw_desc->group_head;
+		list_splice_init(&sw_desc->group_list, &chan->chain);
+		async_tx_ack(&sw_desc->async_tx);
+		ppc440spe_desc_init_null_xor(group_start);
+
+		cookie = chan->common.cookie;
+		cookie++;
+		if (cookie <= 1)
+			cookie = 2;
+
+		/* initialize the completed cookie to be less than
+		 * the most recently used cookie
+		 */
+		chan->completed_cookie = cookie - 1;
+		chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+		/* channel should not be busy */
+		BUG_ON(ppc440spe_chan_is_busy(chan));
+
+		/* set the descriptor address */
+		ppc440spe_chan_set_first_xor_descriptor(chan, sw_desc);
+
+		/* run the descriptor */
+		ppc440spe_chan_run(chan);
+	} else
+		printk(KERN_ERR "ppc440spe adma%d"
+			" failed to allocate null descriptor\n",
+			chan->device->id);
+	spin_unlock_bh(&chan->lock);
+}
+
+/**
+ * ppc440spe_test_raid6 - test are RAID-6 capabilities enabled successfully.
+ *	For this we just perform one WXOR operation with the same source
+ *	and destination addresses, the GF-multiplier is 1; so if RAID-6
+ *	capabilities are enabled then we'll get src/dst filled with zero.
+ */
+static int ppc440spe_test_raid6(struct ppc440spe_adma_chan *chan)
+{
+	struct ppc440spe_adma_desc_slot *sw_desc, *iter;
+	struct page *pg;
+	char *a;
+	dma_addr_t dma_addr, addrs[2];
+	unsigned long op = 0;
+	int rval = 0;
+
+	set_bit(PPC440SPE_DESC_WXOR, &op);
+
+	pg = alloc_page(GFP_KERNEL);
+	if (!pg)
+		return -ENOMEM;
+
+	spin_lock_bh(&chan->lock);
+	sw_desc = ppc440spe_adma_alloc_slots(chan, 1, 1);
+	if (sw_desc) {
+		/* 1 src, 1 dsr, int_ena, WXOR */
+		ppc440spe_desc_init_dma01pq(sw_desc, 1, 1, 1, op);
+		list_for_each_entry(iter, &sw_desc->group_list, chain_node) {
+			ppc440spe_desc_set_byte_count(iter, chan, PAGE_SIZE);
+			iter->unmap_len = PAGE_SIZE;
+		}
+	} else {
+		rval = -EFAULT;
+		spin_unlock_bh(&chan->lock);
+		goto exit;
+	}
+	spin_unlock_bh(&chan->lock);
+
+	/* Fill the test page with ones */
+	memset(page_address(pg), 0xFF, PAGE_SIZE);
+	dma_addr = dma_map_page(chan->device->dev, pg, 0,
+				PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+	/* Setup addresses */
+	ppc440spe_adma_pq_set_src(sw_desc, dma_addr, 0);
+	ppc440spe_adma_pq_set_src_mult(sw_desc, 1, 0, 0);
+	addrs[0] = dma_addr;
+	addrs[1] = 0;
+	ppc440spe_adma_pq_set_dest(sw_desc, addrs, DMA_PREP_PQ_DISABLE_Q);
+
+	async_tx_ack(&sw_desc->async_tx);
+	sw_desc->async_tx.callback = ppc440spe_test_callback;
+	sw_desc->async_tx.callback_param = NULL;
+
+	init_completion(&ppc440spe_r6_test_comp);
+
+	ppc440spe_adma_tx_submit(&sw_desc->async_tx);
+	ppc440spe_adma_issue_pending(&chan->common);
+
+	wait_for_completion(&ppc440spe_r6_test_comp);
+
+	/* Now check if the test page is zeroed */
+	a = page_address(pg);
+	if ((*(u32 *)a) == 0 && memcmp(a, a+4, PAGE_SIZE-4) == 0) {
+		/* page is zero - RAID-6 enabled */
+		rval = 0;
+	} else {
+		/* RAID-6 was not enabled */
+		rval = -EINVAL;
+	}
+exit:
+	__free_page(pg);
+	return rval;
+}
+
+static void ppc440spe_adma_init_capabilities(struct ppc440spe_adma_device *adev)
+{
+	switch (adev->id) {
+	case PPC440SPE_DMA0_ID:
+	case PPC440SPE_DMA1_ID:
+		dma_cap_set(DMA_MEMCPY, adev->common.cap_mask);
+		dma_cap_set(DMA_INTERRUPT, adev->common.cap_mask);
+		dma_cap_set(DMA_MEMSET, adev->common.cap_mask);
+		dma_cap_set(DMA_PQ, adev->common.cap_mask);
+		dma_cap_set(DMA_PQ_VAL, adev->common.cap_mask);
+		dma_cap_set(DMA_XOR_VAL, adev->common.cap_mask);
+		break;
+	case PPC440SPE_XOR_ID:
+		dma_cap_set(DMA_XOR, adev->common.cap_mask);
+		dma_cap_set(DMA_PQ, adev->common.cap_mask);
+		dma_cap_set(DMA_INTERRUPT, adev->common.cap_mask);
+		adev->common.cap_mask = adev->common.cap_mask;
+		break;
+	}
+
+	/* Set base routines */
+	adev->common.device_alloc_chan_resources =
+				ppc440spe_adma_alloc_chan_resources;
+	adev->common.device_free_chan_resources =
+				ppc440spe_adma_free_chan_resources;
+	adev->common.device_is_tx_complete = ppc440spe_adma_is_complete;
+	adev->common.device_issue_pending = ppc440spe_adma_issue_pending;
+
+	/* Set prep routines based on capability */
+	if (dma_has_cap(DMA_MEMCPY, adev->common.cap_mask)) {
+		adev->common.device_prep_dma_memcpy =
+			ppc440spe_adma_prep_dma_memcpy;
+	}
+	if (dma_has_cap(DMA_MEMSET, adev->common.cap_mask)) {
+		adev->common.device_prep_dma_memset =
+			ppc440spe_adma_prep_dma_memset;
+	}
+	if (dma_has_cap(DMA_XOR, adev->common.cap_mask)) {
+		adev->common.max_xor = XOR_MAX_OPS;
+		adev->common.device_prep_dma_xor =
+			ppc440spe_adma_prep_dma_xor;
+	}
+	if (dma_has_cap(DMA_PQ, adev->common.cap_mask)) {
+		switch (adev->id) {
+		case PPC440SPE_DMA0_ID:
+			dma_set_maxpq(&adev->common,
+				DMA0_FIFO_SIZE / sizeof(struct dma_cdb), 0);
+			break;
+		case PPC440SPE_DMA1_ID:
+			dma_set_maxpq(&adev->common,
+				DMA1_FIFO_SIZE / sizeof(struct dma_cdb), 0);
+			break;
+		case PPC440SPE_XOR_ID:
+			adev->common.max_pq = XOR_MAX_OPS * 3;
+			break;
+		}
+		adev->common.device_prep_dma_pq =
+			ppc440spe_adma_prep_dma_pq;
+	}
+	if (dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask)) {
+		switch (adev->id) {
+		case PPC440SPE_DMA0_ID:
+			adev->common.max_pq = DMA0_FIFO_SIZE /
+						sizeof(struct dma_cdb);
+			break;
+		case PPC440SPE_DMA1_ID:
+			adev->common.max_pq = DMA1_FIFO_SIZE /
+						sizeof(struct dma_cdb);
+			break;
+		}
+		adev->common.device_prep_dma_pq_val =
+			ppc440spe_adma_prep_dma_pqzero_sum;
+	}
+	if (dma_has_cap(DMA_XOR_VAL, adev->common.cap_mask)) {
+		switch (adev->id) {
+		case PPC440SPE_DMA0_ID:
+			adev->common.max_xor = DMA0_FIFO_SIZE /
+						sizeof(struct dma_cdb);
+			break;
+		case PPC440SPE_DMA1_ID:
+			adev->common.max_xor = DMA1_FIFO_SIZE /
+						sizeof(struct dma_cdb);
+			break;
+		}
+		adev->common.device_prep_dma_xor_val =
+			ppc440spe_adma_prep_dma_xor_zero_sum;
+	}
+	if (dma_has_cap(DMA_INTERRUPT, adev->common.cap_mask)) {
+		adev->common.device_prep_dma_interrupt =
+			ppc440spe_adma_prep_dma_interrupt;
+	}
+	pr_info("%s: AMCC(R) PPC440SP(E) ADMA Engine: "
+	  "( %s%s%s%s%s%s%s)\n",
+	  dev_name(adev->dev),
+	  dma_has_cap(DMA_PQ, adev->common.cap_mask) ? "pq " : "",
+	  dma_has_cap(DMA_PQ_VAL, adev->common.cap_mask) ? "pq_val " : "",
+	  dma_has_cap(DMA_XOR, adev->common.cap_mask) ? "xor " : "",
+	  dma_has_cap(DMA_XOR_VAL, adev->common.cap_mask) ? "xor_val " : "",
+	  dma_has_cap(DMA_MEMCPY, adev->common.cap_mask) ? "memcpy " : "",
+	  dma_has_cap(DMA_MEMSET, adev->common.cap_mask)  ? "memset " : "",
+	  dma_has_cap(DMA_INTERRUPT, adev->common.cap_mask) ? "intr " : "");
+}
+
+static int ppc440spe_adma_setup_irqs(struct ppc440spe_adma_device *adev,
+				     struct ppc440spe_adma_chan *chan,
+				     int *initcode)
+{
+	struct device_node *np;
+	int ret;
+
+	np = container_of(adev->dev, struct of_device, dev)->node;
+	if (adev->id != PPC440SPE_XOR_ID) {
+		adev->err_irq = irq_of_parse_and_map(np, 1);
+		if (adev->err_irq == NO_IRQ) {
+			dev_warn(adev->dev, "no err irq resource?\n");
+			*initcode = PPC_ADMA_INIT_IRQ2;
+			adev->err_irq = -ENXIO;
+		} else
+			atomic_inc(&ppc440spe_adma_err_irq_ref);
+	} else {
+		adev->err_irq = -ENXIO;
+	}
+
+	adev->irq = irq_of_parse_and_map(np, 0);
+	if (adev->irq == NO_IRQ) {
+		dev_err(adev->dev, "no irq resource\n");
+		*initcode = PPC_ADMA_INIT_IRQ1;
+		ret = -ENXIO;
+		goto err_irq_map;
+	}
+	dev_dbg(adev->dev, "irq %d, err irq %d\n",
+		adev->irq, adev->err_irq);
+
+	ret = request_irq(adev->irq, ppc440spe_adma_eot_handler,
+			  0, dev_driver_string(adev->dev), chan);
+	if (ret) {
+		dev_err(adev->dev, "can't request irq %d\n",
+			adev->irq);
+		*initcode = PPC_ADMA_INIT_IRQ1;
+		ret = -EIO;
+		goto err_req1;
+	}
+
+	/* only DMA engines have a separate error IRQ
+	 * so it's Ok if err_irq < 0 in XOR engine case.
+	 */
+	if (adev->err_irq > 0) {
+		/* both DMA engines share common error IRQ */
+		ret = request_irq(adev->err_irq,
+				  ppc440spe_adma_err_handler,
+				  IRQF_SHARED,
+				  dev_driver_string(adev->dev),
+				  chan);
+		if (ret) {
+			dev_err(adev->dev, "can't request irq %d\n",
+				adev->err_irq);
+			*initcode = PPC_ADMA_INIT_IRQ2;
+			ret = -EIO;
+			goto err_req2;
+		}
+	}
+
+	if (adev->id == PPC440SPE_XOR_ID) {
+		/* enable XOR engine interrupts */
+		iowrite32be(XOR_IE_CBCIE_BIT | XOR_IE_ICBIE_BIT |
+			    XOR_IE_ICIE_BIT | XOR_IE_RPTIE_BIT,
+			    &adev->xor_reg->ier);
+	} else {
+		u32 mask, enable;
+
+		np = of_find_compatible_node(NULL, NULL, "ibm,i2o-440spe");
+		if (!np) {
+			pr_err("%s: can't find I2O device tree node\n",
+				__func__);
+			ret = -ENODEV;
+			goto err_req2;
+		}
+		adev->i2o_reg = of_iomap(np, 0);
+		if (!adev->i2o_reg) {
+			pr_err("%s: failed to map I2O registers\n", __func__);
+			of_node_put(np);
+			ret = -EINVAL;
+			goto err_req2;
+		}
+		of_node_put(np);
+		/* Unmask 'CS FIFO Attention' interrupts and
+		 * enable generating interrupts on errors
+		 */
+		enable = (adev->id == PPC440SPE_DMA0_ID) ?
+			 ~(I2O_IOPIM_P0SNE | I2O_IOPIM_P0EM) :
+			 ~(I2O_IOPIM_P1SNE | I2O_IOPIM_P1EM);
+		mask = ioread32(&adev->i2o_reg->iopim) & enable;
+		iowrite32(mask, &adev->i2o_reg->iopim);
+	}
+	return 0;
+
+err_req2:
+	free_irq(adev->irq, chan);
+err_req1:
+	irq_dispose_mapping(adev->irq);
+err_irq_map:
+	if (adev->err_irq > 0) {
+		if (atomic_dec_and_test(&ppc440spe_adma_err_irq_ref))
+			irq_dispose_mapping(adev->err_irq);
+	}
+	return ret;
+}
+
+static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
+					struct ppc440spe_adma_chan *chan)
+{
+	u32 mask, disable;
+
+	if (adev->id == PPC440SPE_XOR_ID) {
+		/* disable XOR engine interrupts */
+		mask = ioread32be(&adev->xor_reg->ier);
+		mask &= ~(XOR_IE_CBCIE_BIT | XOR_IE_ICBIE_BIT |
+			  XOR_IE_ICIE_BIT | XOR_IE_RPTIE_BIT);
+		iowrite32be(mask, &adev->xor_reg->ier);
+	} else {
+		/* disable DMAx engine interrupts */
+		disable = (adev->id == PPC440SPE_DMA0_ID) ?
+			  (I2O_IOPIM_P0SNE | I2O_IOPIM_P0EM) :
+			  (I2O_IOPIM_P1SNE | I2O_IOPIM_P1EM);
+		mask = ioread32(&adev->i2o_reg->iopim) | disable;
+		iowrite32(mask, &adev->i2o_reg->iopim);
+	}
+	free_irq(adev->irq, chan);
+	irq_dispose_mapping(adev->irq);
+	if (adev->err_irq > 0) {
+		free_irq(adev->err_irq, chan);
+		if (atomic_dec_and_test(&ppc440spe_adma_err_irq_ref)) {
+			irq_dispose_mapping(adev->err_irq);
+			iounmap(adev->i2o_reg);
+		}
+	}
+}
+
+/**
+ * ppc440spe_adma_probe - probe the asynch device
+ */
+static int __devinit ppc440spe_adma_probe(struct of_device *ofdev,
+					  const struct of_device_id *match)
+{
+	struct device_node *np = ofdev->node;
+	struct resource res;
+	struct ppc440spe_adma_device *adev;
+	struct ppc440spe_adma_chan *chan;
+	struct ppc_dma_chan_ref *ref, *_ref;
+	int ret = 0, initcode = PPC_ADMA_INIT_OK;
+	const u32 *idx;
+	int len;
+	void *regs;
+	u32 id, pool_size;
+
+	if (of_device_is_compatible(np, "amcc,xor-accelerator")) {
+		id = PPC440SPE_XOR_ID;
+		/* As far as the XOR engine is concerned, it does not
+		 * use FIFOs but uses linked list. So there is no dependency
+		 * between pool size to allocate and the engine configuration.
+		 */
+		pool_size = PAGE_SIZE << 1;
+	} else {
+		/* it is DMA0 or DMA1 */
+		idx = of_get_property(np, "cell-index", &len);
+		if (!idx || (len != sizeof(u32))) {
+			dev_err(&ofdev->dev, "Device node %s has missing "
+				"or invalid cell-index property\n",
+				np->full_name);
+			return -EINVAL;
+		}
+		id = *idx;
+		/* DMA0,1 engines use FIFO to maintain CDBs, so we
+		 * should allocate the pool accordingly to size of this
+		 * FIFO. Thus, the pool size depends on the FIFO depth:
+		 * how much CDBs pointers the FIFO may contain then so
+		 * much CDBs we should provide in the pool.
+		 * That is
+		 *   CDB size = 32B;
+		 *   CDBs number = (DMA0_FIFO_SIZE >> 3);
+		 *   Pool size = CDBs number * CDB size =
+		 *      = (DMA0_FIFO_SIZE >> 3) << 5 = DMA0_FIFO_SIZE << 2.
+		 */
+		pool_size = (id == PPC440SPE_DMA0_ID) ?
+			    DMA0_FIFO_SIZE : DMA1_FIFO_SIZE;
+		pool_size <<= 2;
+	}
+
+	if (of_address_to_resource(np, 0, &res)) {
+		dev_err(&ofdev->dev, "failed to get memory resource\n");
+		initcode = PPC_ADMA_INIT_MEMRES;
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!request_mem_region(res.start, resource_size(&res),
+				dev_driver_string(&ofdev->dev))) {
+		dev_err(&ofdev->dev, "failed to request memory region "
+			"(0x%016llx-0x%016llx)\n",
+			(u64)res.start, (u64)res.end);
+		initcode = PPC_ADMA_INIT_MEMREG;
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* create a device */
+	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+	if (!adev) {
+		dev_err(&ofdev->dev, "failed to allocate device\n");
+		initcode = PPC_ADMA_INIT_ALLOC;
+		ret = -ENOMEM;
+		goto err_adev_alloc;
+	}
+
+	adev->id = id;
+	adev->pool_size = pool_size;
+	/* allocate coherent memory for hardware descriptors */
+	adev->dma_desc_pool_virt = dma_alloc_coherent(&ofdev->dev,
+					adev->pool_size, &adev->dma_desc_pool,
+					GFP_KERNEL);
+	if (adev->dma_desc_pool_virt == NULL) {
+		dev_err(&ofdev->dev, "failed to allocate %d bytes of coherent "
+			"memory for hardware descriptors\n",
+			adev->pool_size);
+		initcode = PPC_ADMA_INIT_COHERENT;
+		ret = -ENOMEM;
+		goto err_dma_alloc;
+	}
+	dev_dbg(&ofdev->dev, "allocted descriptor pool virt 0x%p phys 0x%llx\n",
+		adev->dma_desc_pool_virt, (u64)adev->dma_desc_pool);
+
+	regs = ioremap(res.start, resource_size(&res));
+	if (!regs) {
+		dev_err(&ofdev->dev, "failed to ioremap regs!\n");
+		goto err_regs_alloc;
+	}
+
+	if (adev->id == PPC440SPE_XOR_ID) {
+		adev->xor_reg = regs;
+		/* Reset XOR */
+		iowrite32be(XOR_CRSR_XASR_BIT, &adev->xor_reg->crsr);
+		iowrite32be(XOR_CRSR_64BA_BIT, &adev->xor_reg->crrr);
+	} else {
+		size_t fifo_size = (adev->id == PPC440SPE_DMA0_ID) ?
+				   DMA0_FIFO_SIZE : DMA1_FIFO_SIZE;
+		adev->dma_reg = regs;
+		/* DMAx_FIFO_SIZE is defined in bytes,
+		 * <fsiz> - is defined in number of CDB pointers (8byte).
+		 * DMA FIFO Length = CSlength + CPlength, where
+		 * CSlength = CPlength = (fsiz + 1) * 8.
+		 */
+		iowrite32(DMA_FIFO_ENABLE | ((fifo_size >> 3) - 2),
+			  &adev->dma_reg->fsiz);
+		/* Configure DMA engine */
+		iowrite32(DMA_CFG_DXEPR_HP | DMA_CFG_DFMPP_HP | DMA_CFG_FALGN,
+			  &adev->dma_reg->cfg);
+		/* Clear Status */
+		iowrite32(~0, &adev->dma_reg->dsts);
+	}
+
+	adev->dev = &ofdev->dev;
+	adev->common.dev = &ofdev->dev;
+	INIT_LIST_HEAD(&adev->common.channels);
+	dev_set_drvdata(&ofdev->dev, adev);
+
+	/* create a channel */
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan) {
+		dev_err(&ofdev->dev, "can't allocate channel structure\n");
+		initcode = PPC_ADMA_INIT_CHANNEL;
+		ret = -ENOMEM;
+		goto err_chan_alloc;
+	}
+
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->chain);
+	INIT_LIST_HEAD(&chan->all_slots);
+	chan->device = adev;
+	chan->common.device = &adev->common;
+	list_add_tail(&chan->common.device_node, &adev->common.channels);
+	tasklet_init(&chan->irq_tasklet, ppc440spe_adma_tasklet,
+		     (unsigned long)chan);
+
+	/* allocate and map helper pages for async validation or
+	 * async_mult/async_sum_product operations on DMA0/1.
+	 */
+	if (adev->id != PPC440SPE_XOR_ID) {
+		chan->pdest_page = alloc_page(GFP_KERNEL);
+		chan->qdest_page = alloc_page(GFP_KERNEL);
+		if (!chan->pdest_page ||
+		    !chan->qdest_page) {
+			if (chan->pdest_page)
+				__free_page(chan->pdest_page);
+			if (chan->qdest_page)
+				__free_page(chan->qdest_page);
+			ret = -ENOMEM;
+			goto err_page_alloc;
+		}
+		chan->pdest = dma_map_page(&ofdev->dev, chan->pdest_page, 0,
+					   PAGE_SIZE, DMA_BIDIRECTIONAL);
+		chan->qdest = dma_map_page(&ofdev->dev, chan->qdest_page, 0,
+					   PAGE_SIZE, DMA_BIDIRECTIONAL);
+	}
+
+	ref = kmalloc(sizeof(*ref), GFP_KERNEL);
+	if (ref) {
+		ref->chan = &chan->common;
+		INIT_LIST_HEAD(&ref->node);
+		list_add_tail(&ref->node, &ppc440spe_adma_chan_list);
+	} else {
+		dev_err(&ofdev->dev, "failed to allocate channel reference!\n");
+		ret = -ENOMEM;
+		goto err_ref_alloc;
+	}
+
+	ret = ppc440spe_adma_setup_irqs(adev, chan, &initcode);
+	if (ret)
+		goto err_irq;
+
+	ppc440spe_adma_init_capabilities(adev);
+
+	ret = dma_async_device_register(&adev->common);
+	if (ret) {
+		initcode = PPC_ADMA_INIT_REGISTER;
+		dev_err(&ofdev->dev, "failed to register dma device\n");
+		goto err_dev_reg;
+	}
+
+	goto out;
+
+err_dev_reg:
+	ppc440spe_adma_release_irqs(adev, chan);
+err_irq:
+	list_for_each_entry_safe(ref, _ref, &ppc440spe_adma_chan_list, node) {
+		if (chan == to_ppc440spe_adma_chan(ref->chan)) {
+			list_del(&ref->node);
+			kfree(ref);
+		}
+	}
+err_ref_alloc:
+	if (adev->id != PPC440SPE_XOR_ID) {
+		dma_unmap_page(&ofdev->dev, chan->pdest,
+			       PAGE_SIZE, DMA_BIDIRECTIONAL);
+		dma_unmap_page(&ofdev->dev, chan->qdest,
+			       PAGE_SIZE, DMA_BIDIRECTIONAL);
+		__free_page(chan->pdest_page);
+		__free_page(chan->qdest_page);
+	}
+err_page_alloc:
+	kfree(chan);
+err_chan_alloc:
+	if (adev->id == PPC440SPE_XOR_ID)
+		iounmap(adev->xor_reg);
+	else
+		iounmap(adev->dma_reg);
+err_regs_alloc:
+	dma_free_coherent(adev->dev, adev->pool_size,
+			  adev->dma_desc_pool_virt,
+			  adev->dma_desc_pool);
+err_dma_alloc:
+	kfree(adev);
+err_adev_alloc:
+	release_mem_region(res.start, resource_size(&res));
+out:
+	if (id < PPC440SPE_ADMA_ENGINES_NUM)
+		ppc440spe_adma_devices[id] = initcode;
+
+	return ret;
+}
+
+/**
+ * ppc440spe_adma_remove - remove the asynch device
+ */
+static int __devexit ppc440spe_adma_remove(struct of_device *ofdev)
+{
+	struct ppc440spe_adma_device *adev = dev_get_drvdata(&ofdev->dev);
+	struct device_node *np = ofdev->node;
+	struct resource res;
+	struct dma_chan *chan, *_chan;
+	struct ppc_dma_chan_ref *ref, *_ref;
+	struct ppc440spe_adma_chan *ppc440spe_chan;
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+	if (adev->id < PPC440SPE_ADMA_ENGINES_NUM)
+		ppc440spe_adma_devices[adev->id] = -1;
+
+	dma_async_device_unregister(&adev->common);
+
+	list_for_each_entry_safe(chan, _chan, &adev->common.channels,
+				 device_node) {
+		ppc440spe_chan = to_ppc440spe_adma_chan(chan);
+		ppc440spe_adma_release_irqs(adev, ppc440spe_chan);
+		tasklet_kill(&ppc440spe_chan->irq_tasklet);
+		if (adev->id != PPC440SPE_XOR_ID) {
+			dma_unmap_page(&ofdev->dev, ppc440spe_chan->pdest,
+					PAGE_SIZE, DMA_BIDIRECTIONAL);
+			dma_unmap_page(&ofdev->dev, ppc440spe_chan->qdest,
+					PAGE_SIZE, DMA_BIDIRECTIONAL);
+			__free_page(ppc440spe_chan->pdest_page);
+			__free_page(ppc440spe_chan->qdest_page);
+		}
+		list_for_each_entry_safe(ref, _ref, &ppc440spe_adma_chan_list,
+					 node) {
+			if (ppc440spe_chan ==
+			    to_ppc440spe_adma_chan(ref->chan)) {
+				list_del(&ref->node);
+				kfree(ref);
+			}
+		}
+		list_del(&chan->device_node);
+		kfree(ppc440spe_chan);
+	}
+
+	dma_free_coherent(adev->dev, adev->pool_size,
+			  adev->dma_desc_pool_virt, adev->dma_desc_pool);
+	if (adev->id == PPC440SPE_XOR_ID)
+		iounmap(adev->xor_reg);
+	else
+		iounmap(adev->dma_reg);
+	of_address_to_resource(np, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+	kfree(adev);
+	return 0;
+}
+
+/*
+ * /sys driver interface to enable h/w RAID-6 capabilities
+ * Files created in e.g. /sys/devices/plb.0/400100100.dma0/driver/
+ * directory are "devices", "enable" and "poly".
+ * "devices" shows available engines.
+ * "enable" is used to enable RAID-6 capabilities or to check
+ * whether these has been activated.
+ * "poly" allows setting/checking used polynomial (for PPC440SPe only).
+ */
+
+static ssize_t show_ppc440spe_devices(struct device_driver *dev, char *buf)
+{
+	ssize_t size = 0;
+	int i;
+
+	for (i = 0; i < PPC440SPE_ADMA_ENGINES_NUM; i++) {
+		if (ppc440spe_adma_devices[i] == -1)
+			continue;
+		size += snprintf(buf + size, PAGE_SIZE - size,
+				 "PPC440SP(E)-ADMA.%d: %s\n", i,
+				 ppc_adma_errors[ppc440spe_adma_devices[i]]);
+	}
+	return size;
+}
+
+static ssize_t show_ppc440spe_r6enable(struct device_driver *dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE,
+			"PPC440SP(e) RAID-6 capabilities are %sABLED.\n",
+			ppc440spe_r6_enabled ? "EN" : "DIS");
+}
+
+static ssize_t store_ppc440spe_r6enable(struct device_driver *dev,
+					const char *buf, size_t count)
+{
+	unsigned long val;
+
+	if (!count || count > 11)
+		return -EINVAL;
+
+	if (!ppc440spe_r6_tchan)
+		return -EFAULT;
+
+	/* Write a key */
+	sscanf(buf, "%lx", &val);
+	dcr_write(ppc440spe_mq_dcr_host, DCRN_MQ0_XORBA, val);
+	isync();
+
+	/* Verify whether it really works now */
+	if (ppc440spe_test_raid6(ppc440spe_r6_tchan) == 0) {
+		pr_info("PPC440SP(e) RAID-6 has been activated "
+			"successfully\n");
+		ppc440spe_r6_enabled = 1;
+	} else {
+		pr_info("PPC440SP(e) RAID-6 hasn't been activated!"
+			" Error key ?\n");
+		ppc440spe_r6_enabled = 0;
+	}
+	return count;
+}
+
+static ssize_t show_ppc440spe_r6poly(struct device_driver *dev, char *buf)
+{
+	ssize_t size = 0;
+	u32 reg;
+
+#ifdef CONFIG_440SP
+	/* 440SP has fixed polynomial */
+	reg = 0x4d;
+#else
+	reg = dcr_read(ppc440spe_mq_dcr_host, DCRN_MQ0_CFBHL);
+	reg >>= MQ0_CFBHL_POLY;
+	reg &= 0xFF;
+#endif
+
+	size = snprintf(buf, PAGE_SIZE, "PPC440SP(e) RAID-6 driver "
+			"uses 0x1%02x polynomial.\n", reg);
+	return size;
+}
+
+static ssize_t store_ppc440spe_r6poly(struct device_driver *dev,
+				      const char *buf, size_t count)
+{
+	unsigned long reg, val;
+
+#ifdef CONFIG_440SP
+	/* 440SP uses default 0x14D polynomial only */
+	return -EINVAL;
+#endif
+
+	if (!count || count > 6)
+		return -EINVAL;
+
+	/* e.g., 0x14D or 0x11D */
+	sscanf(buf, "%lx", &val);
+
+	if (val & ~0x1FF)
+		return -EINVAL;
+
+	val &= 0xFF;
+	reg = dcr_read(ppc440spe_mq_dcr_host, DCRN_MQ0_CFBHL);
+	reg &= ~(0xFF << MQ0_CFBHL_POLY);
+	reg |= val << MQ0_CFBHL_POLY;
+	dcr_write(ppc440spe_mq_dcr_host, DCRN_MQ0_CFBHL, reg);
+
+	return count;
+}
+
+static DRIVER_ATTR(devices, S_IRUGO, show_ppc440spe_devices, NULL);
+static DRIVER_ATTR(enable, S_IRUGO | S_IWUSR, show_ppc440spe_r6enable,
+		   store_ppc440spe_r6enable);
+static DRIVER_ATTR(poly, S_IRUGO | S_IWUSR, show_ppc440spe_r6poly,
+		   store_ppc440spe_r6poly);
+
+/*
+ * Common initialisation for RAID engines; allocate memory for
+ * DMAx FIFOs, perform configuration common for all DMA engines.
+ * Further DMA engine specific configuration is done at probe time.
+ */
+static int ppc440spe_configure_raid_devices(void)
+{
+	struct device_node *np;
+	struct resource i2o_res;
+	struct i2o_regs __iomem *i2o_reg;
+	dcr_host_t i2o_dcr_host;
+	unsigned int dcr_base, dcr_len;
+	int i, ret;
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,i2o-440spe");
+	if (!np) {
+		pr_err("%s: can't find I2O device tree node\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(np, 0, &i2o_res)) {
+		of_node_put(np);
+		return -EINVAL;
+	}
+
+	i2o_reg = of_iomap(np, 0);
+	if (!i2o_reg) {
+		pr_err("%s: failed to map I2O registers\n", __func__);
+		of_node_put(np);
+		return -EINVAL;
+	}
+
+	/* Get I2O DCRs base */
+	dcr_base = dcr_resource_start(np, 0);
+	dcr_len = dcr_resource_len(np, 0);
+	if (!dcr_base && !dcr_len) {
+		pr_err("%s: can't get DCR registers base/len!\n",
+			np->full_name);
+		of_node_put(np);
+		iounmap(i2o_reg);
+		return -ENODEV;
+	}
+
+	i2o_dcr_host = dcr_map(np, dcr_base, dcr_len);
+	if (!DCR_MAP_OK(i2o_dcr_host)) {
+		pr_err("%s: failed to map DCRs!\n", np->full_name);
+		of_node_put(np);
+		iounmap(i2o_reg);
+		return -ENODEV;
+	}
+	of_node_put(np);
+
+	/* Provide memory regions for DMA's FIFOs: I2O, DMA0 and DMA1 share
+	 * the base address of FIFO memory space.
+	 * Actually we need twice more physical memory than programmed in the
+	 * <fsiz> register (because there are two FIFOs for each DMA: CP and CS)
+	 */
+	ppc440spe_dma_fifo_buf = kmalloc((DMA0_FIFO_SIZE + DMA1_FIFO_SIZE) << 1,
+					 GFP_KERNEL);
+	if (!ppc440spe_dma_fifo_buf) {
+		pr_err("%s: DMA FIFO buffer allocation failed.\n", __func__);
+		iounmap(i2o_reg);
+		dcr_unmap(i2o_dcr_host, dcr_len);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Configure h/w
+	 */
+	/* Reset I2O/DMA */
+	mtdcri(SDR0, DCRN_SDR0_SRST, DCRN_SDR0_SRST_I2ODMA);
+	mtdcri(SDR0, DCRN_SDR0_SRST, 0);
+
+	/* Setup the base address of mmaped registers */
+	dcr_write(i2o_dcr_host, DCRN_I2O0_IBAH, (u32)(i2o_res.start >> 32));
+	dcr_write(i2o_dcr_host, DCRN_I2O0_IBAL, (u32)(i2o_res.start) |
+						I2O_REG_ENABLE);
+	dcr_unmap(i2o_dcr_host, dcr_len);
+
+	/* Setup FIFO memory space base address */
+	iowrite32(0, &i2o_reg->ifbah);
+	iowrite32(((u32)__pa(ppc440spe_dma_fifo_buf)), &i2o_reg->ifbal);
+
+	/* set zero FIFO size for I2O, so the whole
+	 * ppc440spe_dma_fifo_buf is used by DMAs.
+	 * DMAx_FIFOs will be configured while probe.
+	 */
+	iowrite32(0, &i2o_reg->ifsiz);
+	iounmap(i2o_reg);
+
+	/* To prepare WXOR/RXOR functionality we need access to
+	 * Memory Queue Module DCRs (finally it will be enabled
+	 * via /sys interface of the ppc440spe ADMA driver).
+	 */
+	np = of_find_compatible_node(NULL, NULL, "ibm,mq-440spe");
+	if (!np) {
+		pr_err("%s: can't find MQ device tree node\n",
+			__func__);
+		ret = -ENODEV;
+		goto out_free;
+	}
+
+	/* Get MQ DCRs base */
+	dcr_base = dcr_resource_start(np, 0);
+	dcr_len = dcr_resource_len(np, 0);
+	if (!dcr_base && !dcr_len) {
+		pr_err("%s: can't get DCR registers base/len!\n",
+			np->full_name);
+		ret = -ENODEV;
+		goto out_mq;
+	}
+
+	ppc440spe_mq_dcr_host = dcr_map(np, dcr_base, dcr_len);
+	if (!DCR_MAP_OK(ppc440spe_mq_dcr_host)) {
+		pr_err("%s: failed to map DCRs!\n", np->full_name);
+		ret = -ENODEV;
+		goto out_mq;
+	}
+	of_node_put(np);
+	ppc440spe_mq_dcr_len = dcr_len;
+
+	/* Set HB alias */
+	dcr_write(ppc440spe_mq_dcr_host, DCRN_MQ0_BAUH, DMA_CUED_XOR_HB);
+
+	/* Set:
+	 * - LL transaction passing limit to 1;
+	 * - Memory controller cycle limit to 1;
+	 * - Galois Polynomial to 0x14d (default)
+	 */
+	dcr_write(ppc440spe_mq_dcr_host, DCRN_MQ0_CFBHL,
+		  (1 << MQ0_CFBHL_TPLM) | (1 << MQ0_CFBHL_HBCL) |
+		  (PPC440SPE_DEFAULT_POLY << MQ0_CFBHL_POLY));
+
+	atomic_set(&ppc440spe_adma_err_irq_ref, 0);
+	for (i = 0; i < PPC440SPE_ADMA_ENGINES_NUM; i++)
+		ppc440spe_adma_devices[i] = -1;
+
+	return 0;
+
+out_mq:
+	of_node_put(np);
+out_free:
+	kfree(ppc440spe_dma_fifo_buf);
+	return ret;
+}
+
+static struct of_device_id __devinitdata ppc440spe_adma_of_match[] = {
+	{ .compatible	= "ibm,dma-440spe", },
+	{ .compatible	= "amcc,xor-accelerator", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
+
+static struct of_platform_driver ppc440spe_adma_driver = {
+	.match_table = ppc440spe_adma_of_match,
+	.probe = ppc440spe_adma_probe,
+	.remove = __devexit_p(ppc440spe_adma_remove),
+	.driver = {
+		.name = "PPC440SP(E)-ADMA",
+		.owner = THIS_MODULE,
+	},
+};
+
+static __init int ppc440spe_adma_init(void)
+{
+	int ret;
+
+	ret = ppc440spe_configure_raid_devices();
+	if (ret)
+		return ret;
+
+	ret = of_register_platform_driver(&ppc440spe_adma_driver);
+	if (ret) {
+		pr_err("%s: failed to register platform driver\n",
+			__func__);
+		goto out_reg;
+	}
+
+	/* Initialization status */
+	ret = driver_create_file(&ppc440spe_adma_driver.driver,
+				 &driver_attr_devices);
+	if (ret)
+		goto out_dev;
+
+	/* RAID-6 h/w enable entry */
+	ret = driver_create_file(&ppc440spe_adma_driver.driver,
+				 &driver_attr_enable);
+	if (ret)
+		goto out_en;
+
+	/* GF polynomial to use */
+	ret = driver_create_file(&ppc440spe_adma_driver.driver,
+				 &driver_attr_poly);
+	if (!ret)
+		return ret;
+
+	driver_remove_file(&ppc440spe_adma_driver.driver,
+			   &driver_attr_enable);
+out_en:
+	driver_remove_file(&ppc440spe_adma_driver.driver,
+			   &driver_attr_devices);
+out_dev:
+	/* User will not be able to enable h/w RAID-6 */
+	pr_err("%s: failed to create RAID-6 driver interface\n",
+		__func__);
+	of_unregister_platform_driver(&ppc440spe_adma_driver);
+out_reg:
+	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
+	kfree(ppc440spe_dma_fifo_buf);
+	return ret;
+}
+
+static void __exit ppc440spe_adma_exit(void)
+{
+	driver_remove_file(&ppc440spe_adma_driver.driver,
+			   &driver_attr_poly);
+	driver_remove_file(&ppc440spe_adma_driver.driver,
+			   &driver_attr_enable);
+	driver_remove_file(&ppc440spe_adma_driver.driver,
+			   &driver_attr_devices);
+	of_unregister_platform_driver(&ppc440spe_adma_driver);
+	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
+	kfree(ppc440spe_dma_fifo_buf);
+}
+
+arch_initcall(ppc440spe_adma_init);
+module_exit(ppc440spe_adma_exit);
+
+MODULE_AUTHOR("Yuri Tikhonov <yur@emcraft.com>");
+MODULE_DESCRIPTION("PPC440SPE ADMA Engine Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/dma/ppc4xx/adma.h b/drivers/dma/ppc4xx/adma.h
new file mode 100644
index 0000000..8ada5a81
--- /dev/null
+++ b/drivers/dma/ppc4xx/adma.h
@@ -0,0 +1,195 @@
+/*
+ * 2006-2009 (C) DENX Software Engineering.
+ *
+ * Author: Yuri Tikhonov <yur@emcraft.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#ifndef _PPC440SPE_ADMA_H
+#define _PPC440SPE_ADMA_H
+
+#include <linux/types.h>
+#include "dma.h"
+#include "xor.h"
+
+#define to_ppc440spe_adma_chan(chan) \
+		container_of(chan, struct ppc440spe_adma_chan, common)
+#define to_ppc440spe_adma_device(dev) \
+		container_of(dev, struct ppc440spe_adma_device, common)
+#define tx_to_ppc440spe_adma_slot(tx) \
+		container_of(tx, struct ppc440spe_adma_desc_slot, async_tx)
+
+/* Default polynomial (for 440SP is only available) */
+#define PPC440SPE_DEFAULT_POLY	0x4d
+
+#define PPC440SPE_ADMA_ENGINES_NUM	(XOR_ENGINES_NUM + DMA_ENGINES_NUM)
+
+#define PPC440SPE_ADMA_WATCHDOG_MSEC	3
+#define PPC440SPE_ADMA_THRESHOLD	1
+
+#define PPC440SPE_DMA0_ID	0
+#define PPC440SPE_DMA1_ID	1
+#define PPC440SPE_XOR_ID	2
+
+#define PPC440SPE_ADMA_DMA_MAX_BYTE_COUNT	0xFFFFFFUL
+/* this is the XOR_CBBCR width */
+#define PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT	(1 << 31)
+#define PPC440SPE_ADMA_ZERO_SUM_MAX_BYTE_COUNT PPC440SPE_ADMA_XOR_MAX_BYTE_COUNT
+
+#define PPC440SPE_RXOR_RUN	0
+
+#define MQ0_CF2H_RXOR_BS_MASK	0x1FF
+
+#undef ADMA_LL_DEBUG
+
+/**
+ * struct ppc440spe_adma_device - internal representation of an ADMA device
+ * @dev: device
+ * @dma_reg: base for DMAx register access
+ * @xor_reg: base for XOR register access
+ * @i2o_reg: base for I2O register access
+ * @id: HW ADMA Device selector
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @pool_size: size of the pool
+ * @irq: DMAx or XOR irq number
+ * @err_irq: DMAx error irq number
+ * @common: embedded struct dma_device
+ */
+struct ppc440spe_adma_device {
+	struct device *dev;
+	struct dma_regs __iomem *dma_reg;
+	struct xor_regs __iomem *xor_reg;
+	struct i2o_regs __iomem *i2o_reg;
+	int id;
+	void *dma_desc_pool_virt;
+	dma_addr_t dma_desc_pool;
+	size_t pool_size;
+	int irq;
+	int err_irq;
+	struct dma_device common;
+};
+
+/**
+ * struct ppc440spe_adma_chan - internal representation of an ADMA channel
+ * @lock: serializes enqueue/dequeue operations to the slot pool
+ * @device: parent device
+ * @chain: device chain view of the descriptors
+ * @common: common dmaengine channel object members
+ * @all_slots: complete domain of slots usable by the channel
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @hw_chain_inited: h/w descriptor chain initialization flag
+ * @irq_tasklet: bottom half where ppc440spe_adma_slot_cleanup runs
+ * @needs_unmap: if buffers should not be unmapped upon final processing
+ * @pdest_page: P destination page for async validate operation
+ * @qdest_page: Q destination page for async validate operation
+ * @pdest: P dma addr for async validate operation
+ * @qdest: Q dma addr for async validate operation
+ */
+struct ppc440spe_adma_chan {
+	spinlock_t lock;
+	struct ppc440spe_adma_device *device;
+	struct list_head chain;
+	struct dma_chan common;
+	struct list_head all_slots;
+	struct ppc440spe_adma_desc_slot *last_used;
+	int pending;
+	dma_cookie_t completed_cookie;
+	int slots_allocated;
+	int hw_chain_inited;
+	struct tasklet_struct irq_tasklet;
+	u8 needs_unmap;
+	struct page *pdest_page;
+	struct page *qdest_page;
+	dma_addr_t pdest;
+	dma_addr_t qdest;
+};
+
+struct ppc440spe_rxor {
+	u32 addrl;
+	u32 addrh;
+	int len;
+	int xor_count;
+	int addr_count;
+	int desc_count;
+	int state;
+};
+
+/**
+ * struct ppc440spe_adma_desc_slot - PPC440SPE-ADMA software descriptor
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @hw_next: pointer to the next descriptor in chain
+ * @async_tx: support for the async_tx api
+ * @slot_node: node on the iop_adma_chan.all_slots list
+ * @chain_node: node on the op_adma_chan.chain list
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ *              for example transfer lengths larger than the supported hw max
+ * @unmap_len: transaction bytecount
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @stride: currently chained or not
+ * @idx: pool index
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @src_cnt: number of sources set in this descriptor
+ * @dst_cnt: number of destinations set in the descriptor
+ * @slots_per_op: number of slots per operation
+ * @descs_per_op: number of slot per P/Q operation see comment
+ *                for ppc440spe_prep_dma_pqxor function
+ * @flags: desc state/type
+ * @reverse_flags: 1 if a corresponding rxor address uses reversed address order
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct ppc440spe_adma_desc_slot {
+	dma_addr_t phys;
+	struct ppc440spe_adma_desc_slot *group_head;
+	struct ppc440spe_adma_desc_slot *hw_next;
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head slot_node;
+	struct list_head chain_node; /* node in channel ops list */
+	struct list_head group_list; /* list */
+	unsigned int unmap_len;
+	void *hw_desc;
+	u16 stride;
+	u16 idx;
+	u16 slot_cnt;
+	u8 src_cnt;
+	u8 dst_cnt;
+	u8 slots_per_op;
+	u8 descs_per_op;
+	unsigned long flags;
+	unsigned long reverse_flags[8];
+
+#define PPC440SPE_DESC_INT	0	/* generate interrupt on complete */
+#define PPC440SPE_ZERO_P	1	/* clear P destionaion */
+#define PPC440SPE_ZERO_Q	2	/* clear Q destination */
+#define PPC440SPE_COHERENT	3	/* src/dst are coherent */
+
+#define PPC440SPE_DESC_WXOR	4	/* WXORs are in chain */
+#define PPC440SPE_DESC_RXOR	5	/* RXOR is in chain */
+
+#define PPC440SPE_DESC_RXOR123	8	/* CDB for RXOR123 operation */
+#define PPC440SPE_DESC_RXOR124	9	/* CDB for RXOR124 operation */
+#define PPC440SPE_DESC_RXOR125	10	/* CDB for RXOR125 operation */
+#define PPC440SPE_DESC_RXOR12	11	/* CDB for RXOR12 operation */
+#define PPC440SPE_DESC_RXOR_REV	12	/* CDB has srcs in reversed order */
+
+#define PPC440SPE_DESC_PCHECK	13
+#define PPC440SPE_DESC_QCHECK	14
+
+#define PPC440SPE_DESC_RXOR_MSK	0x3
+
+	struct ppc440spe_rxor rxor_cursor;
+
+	union {
+		u32 *xor_check_result;
+		u32 *crc32_result;
+	};
+};
+
+#endif /* _PPC440SPE_ADMA_H */
diff --git a/drivers/dma/ppc4xx/dma.h b/drivers/dma/ppc4xx/dma.h
new file mode 100644
index 0000000..bcde2df
--- /dev/null
+++ b/drivers/dma/ppc4xx/dma.h
@@ -0,0 +1,223 @@
+/*
+ * 440SPe's DMA engines support header file
+ *
+ * 2006-2009 (C) DENX Software Engineering.
+ *
+ * Author: Yuri Tikhonov <yur@emcraft.com>
+ *
+ * This file is licensed under the term of  the GNU General Public License
+ * version 2. The program licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef	_PPC440SPE_DMA_H
+#define _PPC440SPE_DMA_H
+
+#include <linux/types.h>
+
+/* Number of elements in the array with statical CDBs */
+#define	MAX_STAT_DMA_CDBS	16
+/* Number of DMA engines available on the contoller */
+#define DMA_ENGINES_NUM		2
+
+/* Maximum h/w supported number of destinations */
+#define DMA_DEST_MAX_NUM	2
+
+/* FIFO's params */
+#define DMA0_FIFO_SIZE		0x1000
+#define DMA1_FIFO_SIZE		0x1000
+#define DMA_FIFO_ENABLE		(1<<12)
+
+/* DMA Configuration Register. Data Transfer Engine PLB Priority: */
+#define DMA_CFG_DXEPR_LP	(0<<26)
+#define DMA_CFG_DXEPR_HP	(3<<26)
+#define DMA_CFG_DXEPR_HHP	(2<<26)
+#define DMA_CFG_DXEPR_HHHP	(1<<26)
+
+/* DMA Configuration Register. DMA FIFO Manager PLB Priority: */
+#define DMA_CFG_DFMPP_LP	(0<<23)
+#define DMA_CFG_DFMPP_HP	(3<<23)
+#define DMA_CFG_DFMPP_HHP	(2<<23)
+#define DMA_CFG_DFMPP_HHHP	(1<<23)
+
+/* DMA Configuration Register. Force 64-byte Alignment */
+#define DMA_CFG_FALGN		(1 << 19)
+
+/*UIC0:*/
+#define D0CPF_INT		(1<<12)
+#define D0CSF_INT		(1<<11)
+#define D1CPF_INT		(1<<10)
+#define D1CSF_INT		(1<<9)
+/*UIC1:*/
+#define DMAE_INT		(1<<9)
+
+/* I2O IOP Interrupt Mask Register */
+#define I2O_IOPIM_P0SNE		(1<<3)
+#define I2O_IOPIM_P0EM		(1<<5)
+#define I2O_IOPIM_P1SNE		(1<<6)
+#define I2O_IOPIM_P1EM		(1<<8)
+
+/* DMA CDB fields */
+#define DMA_CDB_MSK		(0xF)
+#define DMA_CDB_64B_ADDR	(1<<2)
+#define DMA_CDB_NO_INT		(1<<3)
+#define DMA_CDB_STATUS_MSK	(0x3)
+#define DMA_CDB_ADDR_MSK	(0xFFFFFFF0)
+
+/* DMA CDB OpCodes */
+#define DMA_CDB_OPC_NO_OP	(0x00)
+#define DMA_CDB_OPC_MV_SG1_SG2	(0x01)
+#define DMA_CDB_OPC_MULTICAST	(0x05)
+#define DMA_CDB_OPC_DFILL128	(0x24)
+#define DMA_CDB_OPC_DCHECK128	(0x23)
+
+#define DMA_CUED_XOR_BASE	(0x10000000)
+#define DMA_CUED_XOR_HB		(0x00000008)
+
+#ifdef CONFIG_440SP
+#define DMA_CUED_MULT1_OFF	0
+#define DMA_CUED_MULT2_OFF	8
+#define DMA_CUED_MULT3_OFF	16
+#define DMA_CUED_REGION_OFF	24
+#define DMA_CUED_XOR_WIN_MSK	(0xFC000000)
+#else
+#define DMA_CUED_MULT1_OFF	2
+#define DMA_CUED_MULT2_OFF	10
+#define DMA_CUED_MULT3_OFF	18
+#define DMA_CUED_REGION_OFF	26
+#define DMA_CUED_XOR_WIN_MSK	(0xF0000000)
+#endif
+
+#define DMA_CUED_REGION_MSK	0x3
+#define DMA_RXOR123		0x0
+#define DMA_RXOR124		0x1
+#define DMA_RXOR125		0x2
+#define DMA_RXOR12		0x3
+
+/* S/G addresses */
+#define DMA_CDB_SG_SRC		1
+#define DMA_CDB_SG_DST1		2
+#define DMA_CDB_SG_DST2		3
+
+/*
+ * DMAx engines Command Descriptor Block Type
+ */
+struct dma_cdb {
+	/*
+	 * Basic CDB structure (Table 20-17, p.499, 440spe_um_1_22.pdf)
+	 */
+	u8	pad0[2];        /* reserved */
+	u8	attr;		/* attributes */
+	u8	opc;		/* opcode */
+	u32	sg1u;		/* upper SG1 address */
+	u32	sg1l;		/* lower SG1 address */
+	u32	cnt;		/* SG count, 3B used */
+	u32	sg2u;		/* upper SG2 address */
+	u32	sg2l;		/* lower SG2 address */
+	u32	sg3u;		/* upper SG3 address */
+	u32	sg3l;		/* lower SG3 address */
+};
+
+/*
+ * DMAx hardware registers (p.515 in 440SPe UM 1.22)
+ */
+struct dma_regs {
+	u32	cpfpl;
+	u32	cpfph;
+	u32	csfpl;
+	u32	csfph;
+	u32	dsts;
+	u32	cfg;
+	u8	pad0[0x8];
+	u16	cpfhp;
+	u16	cpftp;
+	u16	csfhp;
+	u16	csftp;
+	u8	pad1[0x8];
+	u32	acpl;
+	u32	acph;
+	u32	s1bpl;
+	u32	s1bph;
+	u32	s2bpl;
+	u32	s2bph;
+	u32	s3bpl;
+	u32	s3bph;
+	u8	pad2[0x10];
+	u32	earl;
+	u32	earh;
+	u8	pad3[0x8];
+	u32	seat;
+	u32	sead;
+	u32	op;
+	u32	fsiz;
+};
+
+/*
+ * I2O hardware registers (p.528 in 440SPe UM 1.22)
+ */
+struct i2o_regs {
+	u32	ists;
+	u32	iseat;
+	u32	isead;
+	u8	pad0[0x14];
+	u32	idbel;
+	u8	pad1[0xc];
+	u32	ihis;
+	u32	ihim;
+	u8	pad2[0x8];
+	u32	ihiq;
+	u32	ihoq;
+	u8	pad3[0x8];
+	u32	iopis;
+	u32	iopim;
+	u32	iopiq;
+	u8	iopoq;
+	u8	pad4[3];
+	u16	iiflh;
+	u16	iiflt;
+	u16	iiplh;
+	u16	iiplt;
+	u16	ioflh;
+	u16	ioflt;
+	u16	ioplh;
+	u16	ioplt;
+	u32	iidc;
+	u32	ictl;
+	u32	ifcpp;
+	u8	pad5[0x4];
+	u16	mfac0;
+	u16	mfac1;
+	u16	mfac2;
+	u16	mfac3;
+	u16	mfac4;
+	u16	mfac5;
+	u16	mfac6;
+	u16	mfac7;
+	u16	ifcfh;
+	u16	ifcht;
+	u8	pad6[0x4];
+	u32	iifmc;
+	u32	iodb;
+	u32	iodbc;
+	u32	ifbal;
+	u32	ifbah;
+	u32	ifsiz;
+	u32	ispd0;
+	u32	ispd1;
+	u32	ispd2;
+	u32	ispd3;
+	u32	ihipl;
+	u32	ihiph;
+	u32	ihopl;
+	u32	ihoph;
+	u32	iiipl;
+	u32	iiiph;
+	u32	iiopl;
+	u32	iioph;
+	u32	ifcpl;
+	u32	ifcph;
+	u8	pad7[0x8];
+	u32	iopt;
+};
+
+#endif /* _PPC440SPE_DMA_H */
diff --git a/drivers/dma/ppc4xx/xor.h b/drivers/dma/ppc4xx/xor.h
new file mode 100644
index 0000000..daed738
--- /dev/null
+++ b/drivers/dma/ppc4xx/xor.h
@@ -0,0 +1,110 @@
+/*
+ * 440SPe's XOR engines support header file
+ *
+ * 2006-2009 (C) DENX Software Engineering.
+ *
+ * Author: Yuri Tikhonov <yur@emcraft.com>
+ *
+ * This file is licensed under the term of  the GNU General Public License
+ * version 2. The program licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _PPC440SPE_XOR_H
+#define _PPC440SPE_XOR_H
+
+#include <linux/types.h>
+
+/* Number of XOR engines available on the contoller */
+#define XOR_ENGINES_NUM		1
+
+/* Number of operands supported in the h/w */
+#define XOR_MAX_OPS		16
+
+/*
+ * XOR Command Block Control Register bits
+ */
+#define XOR_CBCR_LNK_BIT        (1<<31) /* link present */
+#define XOR_CBCR_TGT_BIT        (1<<30) /* target present */
+#define XOR_CBCR_CBCE_BIT       (1<<29) /* command block compete enable */
+#define XOR_CBCR_RNZE_BIT       (1<<28) /* result not zero enable */
+#define XOR_CBCR_XNOR_BIT       (1<<15) /* XOR/XNOR */
+#define XOR_CDCR_OAC_MSK        (0x7F)  /* operand address count */
+
+/*
+ * XORCore Status Register bits
+ */
+#define XOR_SR_XCP_BIT		(1<<31)	/* core processing */
+#define XOR_SR_ICB_BIT		(1<<17)	/* invalid CB */
+#define XOR_SR_IC_BIT		(1<<16)	/* invalid command */
+#define XOR_SR_IPE_BIT		(1<<15)	/* internal parity error */
+#define XOR_SR_RNZ_BIT		(1<<2)	/* result not Zero */
+#define XOR_SR_CBC_BIT		(1<<1)	/* CB complete */
+#define XOR_SR_CBLC_BIT		(1<<0)	/* CB list complete */
+
+/*
+ * XORCore Control Set and Reset Register bits
+ */
+#define XOR_CRSR_XASR_BIT	(1<<31)	/* soft reset */
+#define XOR_CRSR_XAE_BIT	(1<<30)	/* enable */
+#define XOR_CRSR_RCBE_BIT	(1<<29)	/* refetch CB enable */
+#define XOR_CRSR_PAUS_BIT	(1<<28)	/* pause */
+#define XOR_CRSR_64BA_BIT	(1<<27) /* 64/32 CB format */
+#define XOR_CRSR_CLP_BIT	(1<<25)	/* continue list processing */
+
+/*
+ * XORCore Interrupt Enable Register
+ */
+#define XOR_IE_ICBIE_BIT	(1<<17)	/* Invalid Command Block IRQ Enable */
+#define XOR_IE_ICIE_BIT		(1<<16)	/* Invalid Command IRQ Enable */
+#define XOR_IE_RPTIE_BIT	(1<<14)	/* Read PLB Timeout Error IRQ Enable */
+#define XOR_IE_CBCIE_BIT	(1<<1)	/* CB complete interrupt enable */
+#define XOR_IE_CBLCI_BIT	(1<<0)	/* CB list complete interrupt enable */
+
+/*
+ * XOR Accelerator engine Command Block Type
+ */
+struct xor_cb {
+	/*
+	 * Basic 64-bit format XOR CB (Table 19-1, p.463, 440spe_um_1_22.pdf)
+	 */
+	u32	cbc;		/* control */
+	u32	cbbc;		/* byte count */
+	u32	cbs;		/* status */
+	u8	pad0[4];	/* reserved */
+	u32	cbtah;		/* target address high */
+	u32	cbtal;		/* target address low */
+	u32	cblah;		/* link address high */
+	u32	cblal;		/* link address low */
+	struct {
+		u32 h;
+		u32 l;
+	} __attribute__ ((packed)) ops[16];
+} __attribute__ ((packed));
+
+/*
+ * XOR hardware registers Table 19-3, UM 1.22
+ */
+struct xor_regs {
+	u32	op_ar[16][2];	/* operand address[0]-high,[1]-low registers */
+	u8	pad0[352];	/* reserved */
+	u32	cbcr;		/* CB control register */
+	u32	cbbcr;		/* CB byte count register */
+	u32	cbsr;		/* CB status register */
+	u8	pad1[4];	/* reserved */
+	u32	cbtahr;		/* operand target address high register */
+	u32	cbtalr;		/* operand target address low register */
+	u32	cblahr;		/* CB link address high register */
+	u32	cblalr;		/* CB link address low register */
+	u32	crsr;		/* control set register */
+	u32	crrr;		/* control reset register */
+	u32	ccbahr;		/* current CB address high register */
+	u32	ccbalr;		/* current CB address low register */
+	u32	plbr;		/* PLB configuration register */
+	u32	ier;		/* interrupt enable register */
+	u32	pecr;		/* parity error count register */
+	u32	sr;		/* status register */
+	u32	revidr;		/* revision ID register */
+};
+
+#endif /* _PPC440SPE_XOR_H */
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 034ecf0..2e4a54c 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -80,17 +80,17 @@
 	unsigned short dmaor;
 
 	sh_dmae_ctl_stop(id);
-	dmaor = (dmaor_read_reg(id)|DMAOR_INIT);
+	dmaor = dmaor_read_reg(id) | DMAOR_INIT;
 
 	dmaor_write_reg(id, dmaor);
-	if ((dmaor_read_reg(id) & (DMAOR_AE | DMAOR_NMIF))) {
+	if (dmaor_read_reg(id) & (DMAOR_AE | DMAOR_NMIF)) {
 		pr_warning(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
 		return -EINVAL;
 	}
 	return 0;
 }
 
-static int dmae_is_idle(struct sh_dmae_chan *sh_chan)
+static int dmae_is_busy(struct sh_dmae_chan *sh_chan)
 {
 	u32 chcr = sh_dmae_readl(sh_chan, CHCR);
 	if (chcr & CHCR_DE) {
@@ -110,15 +110,14 @@
 {
 	sh_dmae_writel(sh_chan, hw.sar, SAR);
 	sh_dmae_writel(sh_chan, hw.dar, DAR);
-	sh_dmae_writel(sh_chan,
-		(hw.tcr >> calc_xmit_shift(sh_chan)), TCR);
+	sh_dmae_writel(sh_chan, hw.tcr >> calc_xmit_shift(sh_chan), TCR);
 }
 
 static void dmae_start(struct sh_dmae_chan *sh_chan)
 {
 	u32 chcr = sh_dmae_readl(sh_chan, CHCR);
 
-	chcr |= (CHCR_DE|CHCR_IE);
+	chcr |= CHCR_DE | CHCR_IE;
 	sh_dmae_writel(sh_chan, chcr, CHCR);
 }
 
@@ -132,7 +131,7 @@
 
 static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
 {
-	int ret = dmae_is_idle(sh_chan);
+	int ret = dmae_is_busy(sh_chan);
 	/* When DMA was working, can not set data to CHCR */
 	if (ret)
 		return ret;
@@ -149,7 +148,7 @@
 {
 	u32 addr;
 	int shift = 0;
-	int ret = dmae_is_idle(sh_chan);
+	int ret = dmae_is_busy(sh_chan);
 	if (ret)
 		return ret;
 
@@ -307,7 +306,7 @@
 		new = sh_dmae_get_desc(sh_chan);
 		if (!new) {
 			dev_err(sh_chan->dev,
-					"No free memory for link descriptor\n");
+				"No free memory for link descriptor\n");
 			goto err_get_desc;
 		}
 
@@ -388,7 +387,7 @@
 	struct sh_dmae_regs hw;
 
 	/* DMA work check */
-	if (dmae_is_idle(sh_chan))
+	if (dmae_is_busy(sh_chan))
 		return;
 
 	/* Find the first un-transfer desciptor */
@@ -497,8 +496,9 @@
 	struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data;
 	struct sh_desc *desc, *_desc, *cur_desc = NULL;
 	u32 sar_buf = sh_dmae_readl(sh_chan, SAR);
+
 	list_for_each_entry_safe(desc, _desc,
-					&sh_chan->ld_queue, node) {
+				 &sh_chan->ld_queue, node) {
 		if ((desc->hw.sar + desc->hw.tcr) == sar_buf) {
 			cur_desc = desc;
 			break;
@@ -543,8 +543,8 @@
 	/* alloc channel */
 	new_sh_chan = kzalloc(sizeof(struct sh_dmae_chan), GFP_KERNEL);
 	if (!new_sh_chan) {
-		dev_err(shdev->common.dev, "No free memory for allocating "
-				"dma channels!\n");
+		dev_err(shdev->common.dev,
+			"No free memory for allocating dma channels!\n");
 		return -ENOMEM;
 	}
 
@@ -586,8 +586,8 @@
 			"sh-dmae%d", new_sh_chan->id);
 
 	/* set up channel irq */
-	err = request_irq(irq, &sh_dmae_interrupt,
-		irqflags, new_sh_chan->dev_id, new_sh_chan);
+	err = request_irq(irq, &sh_dmae_interrupt, irqflags,
+			  new_sh_chan->dev_id, new_sh_chan);
 	if (err) {
 		dev_err(shdev->common.dev, "DMA channel %d request_irq error "
 			"with return %d\n", id, err);
@@ -676,6 +676,8 @@
 	shdev->common.device_is_tx_complete = sh_dmae_is_complete;
 	shdev->common.device_issue_pending = sh_dmae_memcpy_issue_pending;
 	shdev->common.dev = &pdev->dev;
+	/* Default transfer size of 32 bytes requires 32-byte alignment */
+	shdev->common.copy_align = 5;
 
 #if defined(CONFIG_CPU_SH4)
 	/* Non Mix IRQ mode SH7722/SH7730 etc... */
@@ -688,8 +690,8 @@
 	}
 
 	for (ecnt = 0 ; ecnt < ARRAY_SIZE(eirq); ecnt++) {
-		err = request_irq(eirq[ecnt], sh_dmae_err,
-			irqflags, "DMAC Address Error", shdev);
+		err = request_irq(eirq[ecnt], sh_dmae_err, irqflags,
+				  "DMAC Address Error", shdev);
 		if (err) {
 			dev_err(&pdev->dev, "DMA device request_irq"
 				"error (irq %d) with return %d\n",
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 2b4bc15..60b81e5 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -35,15 +35,15 @@
 
 struct sh_dmae_chan {
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
-	spinlock_t desc_lock;			/* Descriptor operation lock */
-	struct list_head ld_queue;		/* Link descriptors queue */
-	struct list_head ld_free;		/* Link descriptors free */
-	struct dma_chan common;			/* DMA common channel */
-	struct device *dev;				/* Channel device */
+	spinlock_t desc_lock;		/* Descriptor operation lock */
+	struct list_head ld_queue;	/* Link descriptors queue */
+	struct list_head ld_free;	/* Link descriptors free */
+	struct dma_chan common;		/* DMA common channel */
+	struct device *dev;		/* Channel device */
 	struct tasklet_struct tasklet;	/* Tasklet */
-	int descs_allocated;			/* desc count */
+	int descs_allocated;		/* desc count */
 	int id;				/* Raw id of this channel */
-	char dev_id[16];	/* unique name per DMAC of channel */
+	char dev_id[16];		/* unique name per DMAC of channel */
 
 	/* Set chcr */
 	int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c
index c693fcc..8fc91a0 100644
--- a/drivers/edac/edac_mce_amd.c
+++ b/drivers/edac/edac_mce_amd.c
@@ -299,6 +299,12 @@
 	if (!handle_errors)
 		return;
 
+	/*
+	 * GART TLB error reporting is disabled by default. Bail out early.
+	 */
+	if (TLB_ERROR(ec) && !report_gart_errors)
+		return;
+
 	pr_emerg(" Northbridge Error, node %d", node_id);
 
 	/*
@@ -310,10 +316,9 @@
 		if (regs->nbsh & K8_NBSH_ERR_CPU_VAL)
 			pr_cont(", core: %u\n", (u8)(regs->nbsh & 0xf));
 	} else {
-		pr_cont(", core: %d\n", ilog2((regs->nbsh & 0xf)));
+		pr_cont(", core: %d\n", fls((regs->nbsh & 0xf) - 1));
 	}
 
-
 	pr_emerg("%s.\n", EXT_ERR_MSG(xec));
 
 	if (BUS_ERROR(ec) && nb_bus_decoder)
@@ -333,21 +338,6 @@
 static inline void amd_decode_err_code(unsigned int ec)
 {
 	if (TLB_ERROR(ec)) {
-		/*
-		 * GART errors are intended to help graphics driver developers
-		 * to detect bad GART PTEs. It is recommended by AMD to disable
-		 * GART table walk error reporting by default[1] (currently
-		 * being disabled in mce_cpu_quirks()) and according to the
-		 * comment in mce_cpu_quirks(), such GART errors can be
-		 * incorrectly triggered. We may see these errors anyway and
-		 * unless requested by the user, they won't be reported.
-		 *
-		 * [1] section 13.10.1 on BIOS and Kernel Developers Guide for
-		 *     AMD NPT family 0Fh processors
-		 */
-		if (!report_gart_errors)
-			return;
-
 		pr_emerg(" Transaction: %s, Cache Level %s\n",
 			 TT_MSG(ec), LL_MSG(ec));
 	} else if (MEM_ERROR(ec)) {
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index 22db05a..7785d8f 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -9,6 +9,11 @@
  * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
  *      http://download.intel.com/design/chipsets/datashts/318378.pdf
  *
+ * The intel 5100 has two independent channels. EDAC core currently
+ * can not reflect this configuration so instead the chip-select
+ * rows for each respective channel are layed out one after another,
+ * the first half belonging to channel 0, the second half belonging
+ * to channel 1.
  */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -25,6 +30,8 @@
 
 /* device 16, func 1 */
 #define I5100_MC		0x40	/* Memory Control Register */
+#define 	I5100_MC_SCRBEN_MASK	(1 << 7)
+#define 	I5100_MC_SCRBDONE_MASK	(1 << 4)
 #define I5100_MS		0x44	/* Memory Status Register */
 #define I5100_SPDDATA		0x48	/* Serial Presence Detect Status Reg */
 #define I5100_SPDCMD		0x4c	/* Serial Presence Detect Command Reg */
@@ -72,11 +79,21 @@
 
 /* bit field accessors */
 
+static inline u32 i5100_mc_scrben(u32 mc)
+{
+	return mc >> 7 & 1;
+}
+
 static inline u32 i5100_mc_errdeten(u32 mc)
 {
 	return mc >> 5 & 1;
 }
 
+static inline u32 i5100_mc_scrbdone(u32 mc)
+{
+	return mc >> 4 & 1;
+}
+
 static inline u16 i5100_spddata_rdo(u16 a)
 {
 	return a >> 15 & 1;
@@ -265,42 +282,43 @@
 }
 
 /* some generic limits */
-#define I5100_MAX_RANKS_PER_CTLR	6
-#define I5100_MAX_CTLRS			2
+#define I5100_MAX_RANKS_PER_CHAN	6
+#define I5100_CHANNELS			    2
 #define I5100_MAX_RANKS_PER_DIMM	4
 #define I5100_DIMM_ADDR_LINES		(6 - 3)	/* 64 bits / 8 bits per byte */
-#define I5100_MAX_DIMM_SLOTS_PER_CTLR	4
+#define I5100_MAX_DIMM_SLOTS_PER_CHAN	4
 #define I5100_MAX_RANK_INTERLEAVE	4
 #define I5100_MAX_DMIRS			5
+#define I5100_SCRUB_REFRESH_RATE	(5 * 60 * HZ)
 
 struct i5100_priv {
 	/* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
-	int dimm_numrank[I5100_MAX_CTLRS][I5100_MAX_DIMM_SLOTS_PER_CTLR];
+	int dimm_numrank[I5100_CHANNELS][I5100_MAX_DIMM_SLOTS_PER_CHAN];
 
 	/*
 	 * mainboard chip select map -- maps i5100 chip selects to
 	 * DIMM slot chip selects.  In the case of only 4 ranks per
-	 * controller, the mapping is fairly obvious but not unique.
-	 * we map -1 -> NC and assume both controllers use the same
+	 * channel, the mapping is fairly obvious but not unique.
+	 * we map -1 -> NC and assume both channels use the same
 	 * map...
 	 *
 	 */
-	int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CTLR][I5100_MAX_RANKS_PER_DIMM];
+	int dimm_csmap[I5100_MAX_DIMM_SLOTS_PER_CHAN][I5100_MAX_RANKS_PER_DIMM];
 
 	/* memory interleave range */
 	struct {
 		u64	 limit;
 		unsigned way[2];
-	} mir[I5100_MAX_CTLRS];
+	} mir[I5100_CHANNELS];
 
 	/* adjusted memory interleave range register */
-	unsigned amir[I5100_MAX_CTLRS];
+	unsigned amir[I5100_CHANNELS];
 
 	/* dimm interleave range */
 	struct {
 		unsigned rank[I5100_MAX_RANK_INTERLEAVE];
 		u64	 limit;
-	} dmir[I5100_MAX_CTLRS][I5100_MAX_DMIRS];
+	} dmir[I5100_CHANNELS][I5100_MAX_DMIRS];
 
 	/* memory technology registers... */
 	struct {
@@ -310,30 +328,33 @@
 		unsigned numbank;	/* 2 or 3 lines */
 		unsigned numrow;	/* 13 .. 16 lines */
 		unsigned numcol;	/* 11 .. 12 lines */
-	} mtr[I5100_MAX_CTLRS][I5100_MAX_RANKS_PER_CTLR];
+	} mtr[I5100_CHANNELS][I5100_MAX_RANKS_PER_CHAN];
 
 	u64 tolm;		/* top of low memory in bytes */
-	unsigned ranksperctlr;	/* number of ranks per controller */
+	unsigned ranksperchan;	/* number of ranks per channel */
 
 	struct pci_dev *mc;	/* device 16 func 1 */
 	struct pci_dev *ch0mm;	/* device 21 func 0 */
 	struct pci_dev *ch1mm;	/* device 22 func 0 */
+
+	struct delayed_work i5100_scrubbing;
+	int scrub_enable;
 };
 
-/* map a rank/ctlr to a slot number on the mainboard */
+/* map a rank/chan to a slot number on the mainboard */
 static int i5100_rank_to_slot(const struct mem_ctl_info *mci,
-			      int ctlr, int rank)
+			      int chan, int rank)
 {
 	const struct i5100_priv *priv = mci->pvt_info;
 	int i;
 
-	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CHAN; i++) {
 		int j;
-		const int numrank = priv->dimm_numrank[ctlr][i];
+		const int numrank = priv->dimm_numrank[chan][i];
 
 		for (j = 0; j < numrank; j++)
 			if (priv->dimm_csmap[i][j] == rank)
-				return i * 2 + ctlr;
+				return i * 2 + chan;
 	}
 
 	return -1;
@@ -374,32 +395,32 @@
 	return "none";
 }
 
-/* convert csrow index into a rank (per controller -- 0..5) */
+/* convert csrow index into a rank (per channel -- 0..5) */
 static int i5100_csrow_to_rank(const struct mem_ctl_info *mci, int csrow)
 {
 	const struct i5100_priv *priv = mci->pvt_info;
 
-	return csrow % priv->ranksperctlr;
+	return csrow % priv->ranksperchan;
 }
 
-/* convert csrow index into a controller (0..1) */
-static int i5100_csrow_to_cntlr(const struct mem_ctl_info *mci, int csrow)
+/* convert csrow index into a channel (0..1) */
+static int i5100_csrow_to_chan(const struct mem_ctl_info *mci, int csrow)
 {
 	const struct i5100_priv *priv = mci->pvt_info;
 
-	return csrow / priv->ranksperctlr;
+	return csrow / priv->ranksperchan;
 }
 
 static unsigned i5100_rank_to_csrow(const struct mem_ctl_info *mci,
-				    int ctlr, int rank)
+				    int chan, int rank)
 {
 	const struct i5100_priv *priv = mci->pvt_info;
 
-	return ctlr * priv->ranksperctlr + rank;
+	return chan * priv->ranksperchan + rank;
 }
 
 static void i5100_handle_ce(struct mem_ctl_info *mci,
-			    int ctlr,
+			    int chan,
 			    unsigned bank,
 			    unsigned rank,
 			    unsigned long syndrome,
@@ -407,12 +428,12 @@
 			    unsigned ras,
 			    const char *msg)
 {
-	const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+	const int csrow = i5100_rank_to_csrow(mci, chan, rank);
 
 	printk(KERN_ERR
-		"CE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+		"CE chan %d, bank %u, rank %u, syndrome 0x%lx, "
 		"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
-		ctlr, bank, rank, syndrome, cas, ras,
+		chan, bank, rank, syndrome, cas, ras,
 		csrow, mci->csrows[csrow].channels[0].label, msg);
 
 	mci->ce_count++;
@@ -421,7 +442,7 @@
 }
 
 static void i5100_handle_ue(struct mem_ctl_info *mci,
-			    int ctlr,
+			    int chan,
 			    unsigned bank,
 			    unsigned rank,
 			    unsigned long syndrome,
@@ -429,23 +450,23 @@
 			    unsigned ras,
 			    const char *msg)
 {
-	const int csrow = i5100_rank_to_csrow(mci, ctlr, rank);
+	const int csrow = i5100_rank_to_csrow(mci, chan, rank);
 
 	printk(KERN_ERR
-		"UE ctlr %d, bank %u, rank %u, syndrome 0x%lx, "
+		"UE chan %d, bank %u, rank %u, syndrome 0x%lx, "
 		"cas %u, ras %u, csrow %u, label \"%s\": %s\n",
-		ctlr, bank, rank, syndrome, cas, ras,
+		chan, bank, rank, syndrome, cas, ras,
 		csrow, mci->csrows[csrow].channels[0].label, msg);
 
 	mci->ue_count++;
 	mci->csrows[csrow].ue_count++;
 }
 
-static void i5100_read_log(struct mem_ctl_info *mci, int ctlr,
+static void i5100_read_log(struct mem_ctl_info *mci, int chan,
 			   u32 ferr, u32 nerr)
 {
 	struct i5100_priv *priv = mci->pvt_info;
-	struct pci_dev *pdev = (ctlr) ? priv->ch1mm : priv->ch0mm;
+	struct pci_dev *pdev = (chan) ? priv->ch1mm : priv->ch0mm;
 	u32 dw;
 	u32 dw2;
 	unsigned syndrome = 0;
@@ -484,7 +505,7 @@
 		else
 			msg = i5100_err_msg(nerr);
 
-		i5100_handle_ce(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+		i5100_handle_ce(mci, chan, bank, rank, syndrome, cas, ras, msg);
 	}
 
 	if (i5100_validlog_nrecmemvalid(dw)) {
@@ -506,7 +527,7 @@
 		else
 			msg = i5100_err_msg(nerr);
 
-		i5100_handle_ue(mci, ctlr, bank, rank, syndrome, cas, ras, msg);
+		i5100_handle_ue(mci, chan, bank, rank, syndrome, cas, ras, msg);
 	}
 
 	pci_write_config_dword(pdev, I5100_VALIDLOG, dw);
@@ -534,6 +555,80 @@
 	}
 }
 
+/* The i5100 chipset will scrub the entire memory once, then
+ * set a done bit. Continuous scrubbing is achieved by enqueing
+ * delayed work to a workqueue, checking every few minutes if
+ * the scrubbing has completed and if so reinitiating it.
+ */
+
+static void i5100_refresh_scrubbing(struct work_struct *work)
+{
+	struct delayed_work *i5100_scrubbing = container_of(work,
+							    struct delayed_work,
+							    work);
+	struct i5100_priv *priv = container_of(i5100_scrubbing,
+					       struct i5100_priv,
+					       i5100_scrubbing);
+	u32 dw;
+
+	pci_read_config_dword(priv->mc, I5100_MC, &dw);
+
+	if (priv->scrub_enable) {
+
+		pci_read_config_dword(priv->mc, I5100_MC, &dw);
+
+		if (i5100_mc_scrbdone(dw)) {
+			dw |= I5100_MC_SCRBEN_MASK;
+			pci_write_config_dword(priv->mc, I5100_MC, dw);
+			pci_read_config_dword(priv->mc, I5100_MC, &dw);
+		}
+
+		schedule_delayed_work(&(priv->i5100_scrubbing),
+				      I5100_SCRUB_REFRESH_RATE);
+	}
+}
+/*
+ * The bandwidth is based on experimentation, feel free to refine it.
+ */
+static int i5100_set_scrub_rate(struct mem_ctl_info *mci,
+				       u32 *bandwidth)
+{
+	struct i5100_priv *priv = mci->pvt_info;
+	u32 dw;
+
+	pci_read_config_dword(priv->mc, I5100_MC, &dw);
+	if (*bandwidth) {
+		priv->scrub_enable = 1;
+		dw |= I5100_MC_SCRBEN_MASK;
+		schedule_delayed_work(&(priv->i5100_scrubbing),
+				      I5100_SCRUB_REFRESH_RATE);
+	} else {
+		priv->scrub_enable = 0;
+		dw &= ~I5100_MC_SCRBEN_MASK;
+		cancel_delayed_work(&(priv->i5100_scrubbing));
+	}
+	pci_write_config_dword(priv->mc, I5100_MC, dw);
+
+	pci_read_config_dword(priv->mc, I5100_MC, &dw);
+
+	*bandwidth = 5900000 * i5100_mc_scrben(dw);
+
+	return 0;
+}
+
+static int i5100_get_scrub_rate(struct mem_ctl_info *mci,
+				u32 *bandwidth)
+{
+	struct i5100_priv *priv = mci->pvt_info;
+	u32 dw;
+
+	pci_read_config_dword(priv->mc, I5100_MC, &dw);
+
+	*bandwidth = 5900000 * i5100_mc_scrben(dw);
+
+	return 0;
+}
+
 static struct pci_dev *pci_get_device_func(unsigned vendor,
 					   unsigned device,
 					   unsigned func)
@@ -557,19 +652,19 @@
 					    int csrow)
 {
 	struct i5100_priv *priv = mci->pvt_info;
-	const unsigned ctlr_rank = i5100_csrow_to_rank(mci, csrow);
-	const unsigned ctlr = i5100_csrow_to_cntlr(mci, csrow);
+	const unsigned chan_rank = i5100_csrow_to_rank(mci, csrow);
+	const unsigned chan = i5100_csrow_to_chan(mci, csrow);
 	unsigned addr_lines;
 
 	/* dimm present? */
-	if (!priv->mtr[ctlr][ctlr_rank].present)
+	if (!priv->mtr[chan][chan_rank].present)
 		return 0ULL;
 
 	addr_lines =
 		I5100_DIMM_ADDR_LINES +
-		priv->mtr[ctlr][ctlr_rank].numcol +
-		priv->mtr[ctlr][ctlr_rank].numrow +
-		priv->mtr[ctlr][ctlr_rank].numbank;
+		priv->mtr[chan][chan_rank].numcol +
+		priv->mtr[chan][chan_rank].numrow +
+		priv->mtr[chan][chan_rank].numbank;
 
 	return (unsigned long)
 		((unsigned long long) (1ULL << addr_lines) / PAGE_SIZE);
@@ -581,11 +676,11 @@
 	struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm };
 	int i;
 
-	for (i = 0; i < I5100_MAX_CTLRS; i++) {
+	for (i = 0; i < I5100_CHANNELS; i++) {
 		int j;
 		struct pci_dev *pdev = mms[i];
 
-		for (j = 0; j < I5100_MAX_RANKS_PER_CTLR; j++) {
+		for (j = 0; j < I5100_MAX_RANKS_PER_CHAN; j++) {
 			const unsigned addr =
 				(j < 4) ? I5100_MTR_0 + j * 2 :
 					  I5100_MTR_4 + (j - 4) * 2;
@@ -644,7 +739,6 @@
  * fill dimm chip select map
  *
  * FIXME:
- *   o only valid for 4 ranks per controller
  *   o not the only way to may chip selects to dimm slots
  *   o investigate if there is some way to obtain this map from the bios
  */
@@ -653,9 +747,7 @@
 	struct i5100_priv *priv = mci->pvt_info;
 	int i;
 
-	WARN_ON(priv->ranksperctlr != 4);
-
-	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CTLR; i++) {
+	for (i = 0; i < I5100_MAX_DIMM_SLOTS_PER_CHAN; i++) {
 		int j;
 
 		for (j = 0; j < I5100_MAX_RANKS_PER_DIMM; j++)
@@ -663,12 +755,21 @@
 	}
 
 	/* only 2 chip selects per slot... */
-	priv->dimm_csmap[0][0] = 0;
-	priv->dimm_csmap[0][1] = 3;
-	priv->dimm_csmap[1][0] = 1;
-	priv->dimm_csmap[1][1] = 2;
-	priv->dimm_csmap[2][0] = 2;
-	priv->dimm_csmap[3][0] = 3;
+	if (priv->ranksperchan == 4) {
+		priv->dimm_csmap[0][0] = 0;
+		priv->dimm_csmap[0][1] = 3;
+		priv->dimm_csmap[1][0] = 1;
+		priv->dimm_csmap[1][1] = 2;
+		priv->dimm_csmap[2][0] = 2;
+		priv->dimm_csmap[3][0] = 3;
+	} else {
+		priv->dimm_csmap[0][0] = 0;
+		priv->dimm_csmap[0][1] = 1;
+		priv->dimm_csmap[1][0] = 2;
+		priv->dimm_csmap[1][1] = 3;
+		priv->dimm_csmap[2][0] = 4;
+		priv->dimm_csmap[2][1] = 5;
+	}
 }
 
 static void __devinit i5100_init_dimm_layout(struct pci_dev *pdev,
@@ -677,10 +778,10 @@
 	struct i5100_priv *priv = mci->pvt_info;
 	int i;
 
-	for (i = 0; i < I5100_MAX_CTLRS; i++) {
+	for (i = 0; i < I5100_CHANNELS; i++) {
 		int j;
 
-		for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CTLR; j++) {
+		for (j = 0; j < I5100_MAX_DIMM_SLOTS_PER_CHAN; j++) {
 			u8 rank;
 
 			if (i5100_read_spd_byte(mci, i, j, 5, &rank) < 0)
@@ -720,7 +821,7 @@
 	pci_read_config_word(pdev, I5100_AMIR_1, &w);
 	priv->amir[1] = w;
 
-	for (i = 0; i < I5100_MAX_CTLRS; i++) {
+	for (i = 0; i < I5100_CHANNELS; i++) {
 		int j;
 
 		for (j = 0; j < 5; j++) {
@@ -747,7 +848,7 @@
 
 	for (i = 0; i < mci->nr_csrows; i++) {
 		const unsigned long npages = i5100_npages(mci, i);
-		const unsigned cntlr = i5100_csrow_to_cntlr(mci, i);
+		const unsigned chan = i5100_csrow_to_chan(mci, i);
 		const unsigned rank = i5100_csrow_to_rank(mci, i);
 
 		if (!npages)
@@ -765,7 +866,7 @@
 		mci->csrows[i].grain = 32;
 		mci->csrows[i].csrow_idx = i;
 		mci->csrows[i].dtype =
-			(priv->mtr[cntlr][rank].width == 4) ? DEV_X4 : DEV_X8;
+			(priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8;
 		mci->csrows[i].ue_count = 0;
 		mci->csrows[i].ce_count = 0;
 		mci->csrows[i].mtype = MEM_RDDR2;
@@ -777,7 +878,7 @@
 		mci->csrows[i].channels[0].csrow = mci->csrows + i;
 		snprintf(mci->csrows[i].channels[0].label,
 			 sizeof(mci->csrows[i].channels[0].label),
-			 "DIMM%u", i5100_rank_to_slot(mci, cntlr, rank));
+			 "DIMM%u", i5100_rank_to_slot(mci, chan, rank));
 
 		total_pages += npages;
 	}
@@ -815,13 +916,6 @@
 	pci_read_config_dword(pdev, I5100_MS, &dw);
 	ranksperch = !!(dw & (1 << 8)) * 2 + 4;
 
-	if (ranksperch != 4) {
-		/* FIXME: get 6 ranks / controller to work - need hw... */
-		printk(KERN_INFO "i5100_edac: unsupported configuration.\n");
-		ret = -ENODEV;
-		goto bail_pdev;
-	}
-
 	/* enable error reporting... */
 	pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw);
 	dw &= ~I5100_FERR_NF_MEM_ANY_MASK;
@@ -864,11 +958,21 @@
 	mci->dev = &pdev->dev;
 
 	priv = mci->pvt_info;
-	priv->ranksperctlr = ranksperch;
+	priv->ranksperchan = ranksperch;
 	priv->mc = pdev;
 	priv->ch0mm = ch0mm;
 	priv->ch1mm = ch1mm;
 
+	INIT_DELAYED_WORK(&(priv->i5100_scrubbing), i5100_refresh_scrubbing);
+
+	/* If scrubbing was already enabled by the bios, start maintaining it */
+	pci_read_config_dword(pdev, I5100_MC, &dw);
+	if (i5100_mc_scrben(dw)) {
+		priv->scrub_enable = 1;
+		schedule_delayed_work(&(priv->i5100_scrubbing),
+				      I5100_SCRUB_REFRESH_RATE);
+	}
+
 	i5100_init_dimm_layout(pdev, mci);
 	i5100_init_interleaving(pdev, mci);
 
@@ -882,6 +986,8 @@
 	mci->ctl_page_to_phys = NULL;
 
 	mci->edac_check = i5100_check_error;
+	mci->set_sdram_scrub_rate = i5100_set_scrub_rate;
+	mci->get_sdram_scrub_rate = i5100_get_scrub_rate;
 
 	i5100_init_csrows(mci);
 
@@ -897,12 +1003,14 @@
 
 	if (edac_mc_add_mc(mci)) {
 		ret = -ENODEV;
-		goto bail_mc;
+		goto bail_scrub;
 	}
 
 	return ret;
 
-bail_mc:
+bail_scrub:
+	priv->scrub_enable = 0;
+	cancel_delayed_work_sync(&(priv->i5100_scrubbing));
 	edac_mc_free(mci);
 
 bail_disable_ch1:
@@ -935,6 +1043,10 @@
 		return;
 
 	priv = mci->pvt_info;
+
+	priv->scrub_enable = 0;
+	cancel_delayed_work_sync(&(priv->i5100_scrubbing));
+
 	pci_disable_device(pdev);
 	pci_disable_device(priv->ch0mm);
 	pci_disable_device(priv->ch1mm);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 57ca339..a019b49 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -206,6 +206,12 @@
 	help
 	  Say Y here to support Intel Moorestown platform GPIO.
 
+config GPIO_TIMBERDALE
+	bool "Support for timberdale GPIO IP"
+	depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM
+	---help---
+	Add support for the GPIO IP in the timberdale FPGA.
+
 comment "SPI GPIO expanders:"
 
 config GPIO_MAX7301
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 270b6d7..52fe4cf 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -13,6 +13,7 @@
 obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
 obj-$(CONFIG_GPIO_PL061)	+= pl061.o
+obj-$(CONFIG_GPIO_TIMBERDALE)	+= timbgpio.o
 obj-$(CONFIG_GPIO_TWL4030)	+= twl4030-gpio.o
 obj-$(CONFIG_GPIO_UCB1400)	+= ucb1400_gpio.o
 obj-$(CONFIG_GPIO_XILINX)	+= xilinx_gpio.o
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 50de0f5..a25ad28 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -53,6 +53,7 @@
 #define FLAG_SYSFS	4	/* exported via /sys/class/gpio/control */
 #define FLAG_TRIG_FALL	5	/* trigger on falling edge */
 #define FLAG_TRIG_RISE	6	/* trigger on rising edge */
+#define FLAG_ACTIVE_LOW	7	/* sysfs value has active low */
 
 #define PDESC_ID_SHIFT	16	/* add new flags before this one */
 
@@ -210,6 +211,11 @@
  *      * configures behavior of poll(2) on /value
  *      * available only if pin can generate IRQs on input
  *      * is read/write as "none", "falling", "rising", or "both"
+ *   /active_low
+ *      * configures polarity of /value
+ *      * is read/write as zero/nonzero
+ *      * also affects existing and subsequent "falling" and "rising"
+ *        /edge configuration
  */
 
 static ssize_t gpio_direction_show(struct device *dev,
@@ -255,7 +261,7 @@
 	return status ? : size;
 }
 
-static const DEVICE_ATTR(direction, 0644,
+static /* const */ DEVICE_ATTR(direction, 0644,
 		gpio_direction_show, gpio_direction_store);
 
 static ssize_t gpio_value_show(struct device *dev,
@@ -267,10 +273,17 @@
 
 	mutex_lock(&sysfs_lock);
 
-	if (!test_bit(FLAG_EXPORT, &desc->flags))
+	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
 		status = -EIO;
-	else
-		status = sprintf(buf, "%d\n", !!gpio_get_value_cansleep(gpio));
+	} else {
+		int value;
+
+		value = !!gpio_get_value_cansleep(gpio);
+		if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+			value = !value;
+
+		status = sprintf(buf, "%d\n", value);
+	}
 
 	mutex_unlock(&sysfs_lock);
 	return status;
@@ -294,6 +307,8 @@
 
 		status = strict_strtol(buf, 0, &value);
 		if (status == 0) {
+			if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+				value = !value;
 			gpio_set_value_cansleep(gpio, value != 0);
 			status = size;
 		}
@@ -303,7 +318,7 @@
 	return status;
 }
 
-static /*const*/ DEVICE_ATTR(value, 0644,
+static const DEVICE_ATTR(value, 0644,
 		gpio_value_show, gpio_value_store);
 
 static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
@@ -352,9 +367,11 @@
 
 	irq_flags = IRQF_SHARED;
 	if (test_bit(FLAG_TRIG_FALL, &gpio_flags))
-		irq_flags |= IRQF_TRIGGER_FALLING;
+		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
 	if (test_bit(FLAG_TRIG_RISE, &gpio_flags))
-		irq_flags |= IRQF_TRIGGER_RISING;
+		irq_flags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
+			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
 
 	if (!pdesc) {
 		pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL);
@@ -475,9 +492,79 @@
 
 static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store);
 
+static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev,
+				int value)
+{
+	int			status = 0;
+
+	if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
+		return 0;
+
+	if (value)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+	else
+		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	/* reconfigure poll(2) support if enabled on one edge only */
+	if (dev != NULL && (!!test_bit(FLAG_TRIG_RISE, &desc->flags) ^
+				!!test_bit(FLAG_TRIG_FALL, &desc->flags))) {
+		unsigned long trigger_flags = desc->flags & GPIO_TRIGGER_MASK;
+
+		gpio_setup_irq(desc, dev, 0);
+		status = gpio_setup_irq(desc, dev, trigger_flags);
+	}
+
+	return status;
+}
+
+static ssize_t gpio_active_low_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	const struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags))
+		status = -EIO;
+	else
+		status = sprintf(buf, "%d\n",
+				!!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
+
+	mutex_unlock(&sysfs_lock);
+
+	return status;
+}
+
+static ssize_t gpio_active_low_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct gpio_desc	*desc = dev_get_drvdata(dev);
+	ssize_t			status;
+
+	mutex_lock(&sysfs_lock);
+
+	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+		status = -EIO;
+	} else {
+		long		value;
+
+		status = strict_strtol(buf, 0, &value);
+		if (status == 0)
+			status = sysfs_set_active_low(desc, dev, value != 0);
+	}
+
+	mutex_unlock(&sysfs_lock);
+
+	return status ? : size;
+}
+
+static const DEVICE_ATTR(active_low, 0644,
+		gpio_active_low_show, gpio_active_low_store);
+
 static const struct attribute *gpio_attrs[] = {
-	&dev_attr_direction.attr,
 	&dev_attr_value.attr,
+	&dev_attr_active_low.attr,
 	NULL,
 };
 
@@ -662,12 +749,12 @@
 		dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
 				desc, ioname ? ioname : "gpio%d", gpio);
 		if (!IS_ERR(dev)) {
-			if (direction_may_change)
-				status = sysfs_create_group(&dev->kobj,
+			status = sysfs_create_group(&dev->kobj,
 						&gpio_attr_group);
-			else
+
+			if (!status && direction_may_change)
 				status = device_create_file(dev,
-						&dev_attr_value);
+						&dev_attr_direction);
 
 			if (!status && gpio_to_irq(gpio) >= 0
 					&& (direction_may_change
@@ -744,6 +831,55 @@
 }
 EXPORT_SYMBOL_GPL(gpio_export_link);
 
+
+/**
+ * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value
+ * @gpio: gpio to change
+ * @value: non-zero to use active low, i.e. inverted values
+ *
+ * Set the polarity of /sys/class/gpio/gpioN/value sysfs attribute.
+ * The GPIO does not have to be exported yet.  If poll(2) support has
+ * been enabled for either rising or falling edge, it will be
+ * reconfigured to follow the new polarity.
+ *
+ * Returns zero on success, else an error.
+ */
+int gpio_sysfs_set_active_low(unsigned gpio, int value)
+{
+	struct gpio_desc	*desc;
+	struct device		*dev = NULL;
+	int			status = -EINVAL;
+
+	if (!gpio_is_valid(gpio))
+		goto done;
+
+	mutex_lock(&sysfs_lock);
+
+	desc = &gpio_desc[gpio];
+
+	if (test_bit(FLAG_EXPORT, &desc->flags)) {
+		struct device *dev;
+
+		dev = class_find_device(&gpio_class, NULL, desc, match_export);
+		if (dev == NULL) {
+			status = -ENODEV;
+			goto unlock;
+		}
+	}
+
+	status = sysfs_set_active_low(desc, dev, value);
+
+unlock:
+	mutex_unlock(&sysfs_lock);
+
+done:
+	if (status)
+		pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
+
 /**
  * gpio_unexport - reverse effect of gpio_export()
  * @gpio: gpio to make unavailable
@@ -1094,6 +1230,7 @@
 		}
 		desc_set_label(desc, NULL);
 		module_put(desc->chip->owner);
+		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
 		clear_bit(FLAG_REQUESTED, &desc->flags);
 	} else
 		WARN_ON(extra_checks);
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index 4baf3d7..6c0ebbd 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -123,7 +123,7 @@
 	void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]);
 	void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]);
 
-	if (gpio < 0 || gpio > lnw->chip.ngpio)
+	if (gpio >= lnw->chip.ngpio)
 		return -EINVAL;
 	spin_lock_irqsave(&lnw->lock, flags);
 	if (type & IRQ_TYPE_EDGE_RISING)
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
new file mode 100644
index 0000000..a4d344b
--- /dev/null
+++ b/drivers/gpio/timbgpio.c
@@ -0,0 +1,342 @@
+/*
+ * timbgpio.c timberdale FPGA GPIO driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Supports:
+ * Timberdale FPGA GPIO
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/timb_gpio.h>
+#include <linux/interrupt.h>
+
+#define DRIVER_NAME "timb-gpio"
+
+#define TGPIOVAL	0x00
+#define TGPIODIR	0x04
+#define TGPIO_IER	0x08
+#define TGPIO_ISR	0x0c
+#define TGPIO_IPR	0x10
+#define TGPIO_ICR	0x14
+#define TGPIO_FLR	0x18
+#define TGPIO_LVR	0x1c
+
+struct timbgpio {
+	void __iomem		*membase;
+	spinlock_t		lock; /* mutual exclusion */
+	struct gpio_chip	gpio;
+	int			irq_base;
+};
+
+static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
+	unsigned offset, bool enabled)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+	u32 reg;
+
+	spin_lock(&tgpio->lock);
+	reg = ioread32(tgpio->membase + offset);
+
+	if (enabled)
+		reg |= (1 << index);
+	else
+		reg &= ~(1 << index);
+
+	iowrite32(reg, tgpio->membase + offset);
+	spin_unlock(&tgpio->lock);
+
+	return 0;
+}
+
+static int timbgpio_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
+{
+	return timbgpio_update_bit(gpio, nr, TGPIODIR, true);
+}
+
+static int timbgpio_gpio_get(struct gpio_chip *gpio, unsigned nr)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+	u32 value;
+
+	value = ioread32(tgpio->membase + TGPIOVAL);
+	return (value & (1 << nr)) ? 1 : 0;
+}
+
+static int timbgpio_gpio_direction_output(struct gpio_chip *gpio,
+						unsigned nr, int val)
+{
+	return timbgpio_update_bit(gpio, nr, TGPIODIR, false);
+}
+
+static void timbgpio_gpio_set(struct gpio_chip *gpio,
+				unsigned nr, int val)
+{
+	timbgpio_update_bit(gpio, nr, TGPIOVAL, val != 0);
+}
+
+static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset)
+{
+	struct timbgpio *tgpio = container_of(gpio, struct timbgpio, gpio);
+
+	if (tgpio->irq_base <= 0)
+		return -EINVAL;
+
+	return tgpio->irq_base + offset;
+}
+
+/*
+ * GPIO IRQ
+ */
+static void timbgpio_irq_disable(unsigned irq)
+{
+	struct timbgpio *tgpio = get_irq_chip_data(irq);
+	int offset = irq - tgpio->irq_base;
+
+	timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0);
+}
+
+static void timbgpio_irq_enable(unsigned irq)
+{
+	struct timbgpio *tgpio = get_irq_chip_data(irq);
+	int offset = irq - tgpio->irq_base;
+
+	timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1);
+}
+
+static int timbgpio_irq_type(unsigned irq, unsigned trigger)
+{
+	struct timbgpio *tgpio = get_irq_chip_data(irq);
+	int offset = irq - tgpio->irq_base;
+	unsigned long flags;
+	u32 lvr, flr;
+
+	if (offset < 0 || offset > tgpio->gpio.ngpio)
+		return -EINVAL;
+
+	spin_lock_irqsave(&tgpio->lock, flags);
+
+	lvr = ioread32(tgpio->membase + TGPIO_LVR);
+	flr = ioread32(tgpio->membase + TGPIO_FLR);
+
+	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+		flr &= ~(1 << offset);
+		if (trigger & IRQ_TYPE_LEVEL_HIGH)
+			lvr |= 1 << offset;
+		else
+			lvr &= ~(1 << offset);
+	}
+
+	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
+		return -EINVAL;
+	else {
+		flr |= 1 << offset;
+		/* opposite compared to the datasheet, but it mirrors the
+		 * reality
+		 */
+		if (trigger & IRQ_TYPE_EDGE_FALLING)
+			lvr |= 1 << offset;
+		else
+			lvr &= ~(1 << offset);
+	}
+
+	iowrite32(lvr, tgpio->membase + TGPIO_LVR);
+	iowrite32(flr, tgpio->membase + TGPIO_FLR);
+	iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
+	spin_unlock_irqrestore(&tgpio->lock, flags);
+
+	return 0;
+}
+
+static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct timbgpio *tgpio = get_irq_data(irq);
+	unsigned long ipr;
+	int offset;
+
+	desc->chip->ack(irq);
+	ipr = ioread32(tgpio->membase + TGPIO_IPR);
+	iowrite32(ipr, tgpio->membase + TGPIO_ICR);
+
+	for_each_bit(offset, &ipr, tgpio->gpio.ngpio)
+		generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
+}
+
+static struct irq_chip timbgpio_irqchip = {
+	.name		= "GPIO",
+	.enable		= timbgpio_irq_enable,
+	.disable	= timbgpio_irq_disable,
+	.set_type	= timbgpio_irq_type,
+};
+
+static int __devinit timbgpio_probe(struct platform_device *pdev)
+{
+	int err, i;
+	struct gpio_chip *gc;
+	struct timbgpio *tgpio;
+	struct resource *iomem;
+	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+	int irq = platform_get_irq(pdev, 0);
+
+	if (!pdata || pdata->nr_pins > 32) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+
+	tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
+	if (!tgpio) {
+		err = -EINVAL;
+		goto err_mem;
+	}
+	tgpio->irq_base = pdata->irq_base;
+
+	spin_lock_init(&tgpio->lock);
+
+	if (!request_mem_region(iomem->start, resource_size(iomem),
+		DRIVER_NAME)) {
+		err = -EBUSY;
+		goto err_request;
+	}
+
+	tgpio->membase = ioremap(iomem->start, resource_size(iomem));
+	if (!tgpio->membase) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	gc = &tgpio->gpio;
+
+	gc->label = dev_name(&pdev->dev);
+	gc->owner = THIS_MODULE;
+	gc->dev = &pdev->dev;
+	gc->direction_input = timbgpio_gpio_direction_input;
+	gc->get = timbgpio_gpio_get;
+	gc->direction_output = timbgpio_gpio_direction_output;
+	gc->set = timbgpio_gpio_set;
+	gc->to_irq = (irq >= 0 && tgpio->irq_base > 0) ? timbgpio_to_irq : NULL;
+	gc->dbg_show = NULL;
+	gc->base = pdata->gpio_base;
+	gc->ngpio = pdata->nr_pins;
+	gc->can_sleep = 0;
+
+	err = gpiochip_add(gc);
+	if (err)
+		goto err_chipadd;
+
+	platform_set_drvdata(pdev, tgpio);
+
+	/* make sure to disable interrupts */
+	iowrite32(0x0, tgpio->membase + TGPIO_IER);
+
+	if (irq < 0 || tgpio->irq_base <= 0)
+		return 0;
+
+	for (i = 0; i < pdata->nr_pins; i++) {
+		set_irq_chip_and_handler_name(tgpio->irq_base + i,
+			&timbgpio_irqchip, handle_simple_irq, "mux");
+		set_irq_chip_data(tgpio->irq_base + i, tgpio);
+#ifdef CONFIG_ARM
+		set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
+#endif
+	}
+
+	set_irq_data(irq, tgpio);
+	set_irq_chained_handler(irq, timbgpio_irq);
+
+	return 0;
+
+err_chipadd:
+	iounmap(tgpio->membase);
+err_ioremap:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_request:
+	kfree(tgpio);
+err_mem:
+	printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
+
+	return err;
+}
+
+static int __devexit timbgpio_remove(struct platform_device *pdev)
+{
+	int err;
+	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+	struct timbgpio *tgpio = platform_get_drvdata(pdev);
+	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (irq >= 0 && tgpio->irq_base > 0) {
+		int i;
+		for (i = 0; i < pdata->nr_pins; i++) {
+			set_irq_chip(tgpio->irq_base + i, NULL);
+			set_irq_chip_data(tgpio->irq_base + i, NULL);
+		}
+
+		set_irq_handler(irq, NULL);
+		set_irq_data(irq, NULL);
+	}
+
+	err = gpiochip_remove(&tgpio->gpio);
+	if (err)
+		printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
+
+	iounmap(tgpio->membase);
+	release_mem_region(iomem->start, resource_size(iomem));
+	kfree(tgpio);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver timbgpio_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= timbgpio_probe,
+	.remove		= timbgpio_remove,
+};
+
+/*--------------------------------------------------------------------------*/
+
+static int __init timbgpio_init(void)
+{
+	return platform_driver_register(&timbgpio_platform_driver);
+}
+
+static void __exit timbgpio_exit(void)
+{
+	platform_driver_unregister(&timbgpio_platform_driver);
+}
+
+module_init(timbgpio_init);
+module_exit(timbgpio_exit);
+
+MODULE_DESCRIPTION("Timberdale GPIO driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mocean Laboratories");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 470ef67..39c5aa7 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_DRM_I915)  += i915/
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
+obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/
 obj-$(CONFIG_DRM_VIA)	+=via/
 obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/
 obj-y			+= i2c/
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index d823e63..b1bc1ea 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -30,11 +30,12 @@
 	  via debugfs.
 
 menu "I2C encoder or helper chips"
-     depends on DRM
+     depends on DRM && I2C
 
 config DRM_I2C_CH7006
 	tristate "Chrontel ch7006 TV encoder"
-	default m if DRM_NOUVEAU
+	depends on DRM_NOUVEAU
+	default m
 	help
 	  Support for Chrontel ch7006 and similar TV encoders, found
 	  on some nVidia video cards.
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 320a14b..aa2dfbc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -311,8 +311,10 @@
 	struct drm_device *dev = dev_priv->dev;
 
 	switch (dev_priv->gart_info.type) {
+#if __OS_HAS_AGP
 	case NOUVEAU_GART_AGP:
 		return ttm_agp_backend_init(bdev, dev->agp->bridge);
+#endif
 	case NOUVEAU_GART_SGDMA:
 		return nouveau_sgdma_init_ttm(dev);
 	default:
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 0cff7eb..dacac9a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -205,7 +205,7 @@
 			schedule_timeout(1);
 
 		if (intr && signal_pending(current)) {
-			ret = -ERESTART;
+			ret = -ERESTARTSYS;
 			break;
 		}
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 11f831f..18fd8ac 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -342,8 +342,6 @@
 			}
 
 			ret = ttm_bo_wait_cpu(&nvbo->bo, false);
-			if (ret == -ERESTART)
-				ret = -EAGAIN;
 			if (ret)
 				return ret;
 			goto retry;
@@ -915,8 +913,6 @@
 			goto out;
 
 		ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait);
-		if (ret == -ERESTART)
-			ret = -EAGAIN;
 		if (ret)
 			goto out;
 	}
@@ -925,9 +921,6 @@
 		ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
 	} else {
 		ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
-		if (ret == -ERESTART)
-			ret = -EAGAIN;
-		else
 		if (ret == 0)
 			nvbo->cpu_filp = file_priv;
 	}
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 0275571..5158a12 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -407,6 +407,7 @@
 	return 0;
 }
 
+#if __OS_HAS_AGP
 static void nouveau_mem_reset_agp(struct drm_device *dev)
 {
 	uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
@@ -432,10 +433,12 @@
 	nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
 	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
 }
+#endif
 
 int
 nouveau_mem_init_agp(struct drm_device *dev)
 {
+#if __OS_HAS_AGP
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_agp_info info;
 	struct drm_agp_mode mode;
@@ -471,6 +474,7 @@
 	dev_priv->gart_info.type	= NOUVEAU_GART_AGP;
 	dev_priv->gart_info.aper_base	= info.aperture_base;
 	dev_priv->gart_info.aper_size	= info.aperture_size;
+#endif
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c
index d3e0a2a..7e8547c 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -252,8 +252,9 @@
 		memcpy(pgraph->ctxprog, fw->data, fw->size);
 
 		cp = pgraph->ctxprog;
-		if (cp->signature != 0x5043564e || cp->version != 0 ||
-		    cp->length != ((fw->size - 7) / 4)) {
+		if (le32_to_cpu(cp->signature) != 0x5043564e ||
+		    cp->version != 0 ||
+		    le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
 			NV_ERROR(dev, "ctxprog invalid\n");
 			release_firmware(fw);
 			nv40_grctx_fini(dev);
@@ -281,8 +282,9 @@
 		memcpy(pgraph->ctxvals, fw->data, fw->size);
 
 		cv = (void *)pgraph->ctxvals;
-		if (cv->signature != 0x5643564e || cv->version != 0 ||
-		    cv->length != ((fw->size - 9) / 8)) {
+		if (le32_to_cpu(cv->signature) != 0x5643564e ||
+		    cv->version != 0 ||
+		    le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
 			NV_ERROR(dev, "ctxvals invalid\n");
 			release_firmware(fw);
 			nv40_grctx_fini(dev);
@@ -294,8 +296,9 @@
 	cp = pgraph->ctxprog;
 
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
-	for (i = 0; i < cp->length; i++)
-		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp->data[i]);
+	for (i = 0; i < le16_to_cpu(cp->length); i++)
+		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
+			le32_to_cpu(cp->data[i]));
 
 	pgraph->accel_blocked = false;
 	return 0;
@@ -329,8 +332,9 @@
 	if (!cv)
 		return;
 
-	for (i = 0; i < cv->length; i++)
-		nv_wo32(dev, ctx, cv->data[i].offset, cv->data[i].value);
+	for (i = 0; i < le32_to_cpu(cv->length); i++)
+		nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
+			le32_to_cpu(cv->data[i].value));
 }
 
 /*
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index feb52ee..b5f5fe7 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -49,7 +49,7 @@
 	radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
 	rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
-	r600_blit_kms.o radeon_pm.o atombios_dp.o
+	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 824cc64..84e5df7 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1374,7 +1374,6 @@
 		case RADEON_TXFORMAT_ARGB4444:
 		case RADEON_TXFORMAT_VYUY422:
 		case RADEON_TXFORMAT_YVYU422:
-		case RADEON_TXFORMAT_DXT1:
 		case RADEON_TXFORMAT_SHADOW16:
 		case RADEON_TXFORMAT_LDUDV655:
 		case RADEON_TXFORMAT_DUDV88:
@@ -1382,12 +1381,19 @@
 			break;
 		case RADEON_TXFORMAT_ARGB8888:
 		case RADEON_TXFORMAT_RGBA8888:
-		case RADEON_TXFORMAT_DXT23:
-		case RADEON_TXFORMAT_DXT45:
 		case RADEON_TXFORMAT_SHADOW32:
 		case RADEON_TXFORMAT_LDUDUV8888:
 			track->textures[i].cpp = 4;
 			break;
+		case RADEON_TXFORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
+		case RADEON_TXFORMAT_DXT23:
+		case RADEON_TXFORMAT_DXT45:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
+			break;
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
 		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
@@ -2731,6 +2737,7 @@
 	DRM_ERROR("coordinate type            %d\n", t->tex_coord_type);
 	DRM_ERROR("width round to power of 2  %d\n", t->roundup_w);
 	DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
+	DRM_ERROR("compress format            %d\n", t->compress_format);
 }
 
 static int r100_cs_track_cube(struct radeon_device *rdev,
@@ -2760,6 +2767,36 @@
 	return 0;
 }
 
+static int r100_track_compress_size(int compress_format, int w, int h)
+{
+	int block_width, block_height, block_bytes;
+	int wblocks, hblocks;
+	int min_wblocks;
+	int sz;
+
+	block_width = 4;
+	block_height = 4;
+
+	switch (compress_format) {
+	case R100_TRACK_COMP_DXT1:
+		block_bytes = 8;
+		min_wblocks = 4;
+		break;
+	default:
+	case R100_TRACK_COMP_DXT35:
+		block_bytes = 16;
+		min_wblocks = 2;
+		break;
+	}
+
+	hblocks = (h + block_height - 1) / block_height;
+	wblocks = (w + block_width - 1) / block_width;
+	if (wblocks < min_wblocks)
+		wblocks = min_wblocks;
+	sz = wblocks * hblocks * block_bytes;
+	return sz;
+}
+
 static int r100_cs_track_texture_check(struct radeon_device *rdev,
 				       struct r100_cs_track *track)
 {
@@ -2797,9 +2834,15 @@
 			h = h / (1 << i);
 			if (track->textures[u].roundup_h)
 				h = roundup_pow_of_two(h);
-			size += w * h;
+			if (track->textures[u].compress_format) {
+
+				size += r100_track_compress_size(track->textures[u].compress_format, w, h);
+				/* compressed textures are block based */
+			} else
+				size += w * h;
 		}
 		size *= track->textures[u].cpp;
+
 		switch (track->textures[u].tex_coord_type) {
 		case 0:
 			break;
@@ -2967,6 +3010,7 @@
 		track->arrays[i].esize = 0x7F;
 	}
 	for (i = 0; i < track->num_texture; i++) {
+		track->textures[i].compress_format = R100_TRACK_COMP_NONE;
 		track->textures[i].pitch = 16536;
 		track->textures[i].width = 16536;
 		track->textures[i].height = 16536;
@@ -3399,6 +3443,8 @@
 	r100_errata(rdev);
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	r100_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h
index ca50903..7188c37 100644
--- a/drivers/gpu/drm/radeon/r100_track.h
+++ b/drivers/gpu/drm/radeon/r100_track.h
@@ -28,6 +28,10 @@
 	unsigned		height;
 };
 
+#define R100_TRACK_COMP_NONE   0
+#define R100_TRACK_COMP_DXT1   1
+#define R100_TRACK_COMP_DXT35  2
+
 struct r100_cs_track_texture {
 	struct radeon_bo	*robj;
 	struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */
@@ -44,6 +48,7 @@
 	bool			enabled;
 	bool			roundup_w;
 	bool			roundup_h;
+	unsigned                compress_format;
 };
 
 struct r100_cs_track_limits {
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c
index eb740fc..2094212 100644
--- a/drivers/gpu/drm/radeon/r200.c
+++ b/drivers/gpu/drm/radeon/r200.c
@@ -401,7 +401,6 @@
 		case R200_TXFORMAT_Y8:
 			track->textures[i].cpp = 1;
 			break;
-		case R200_TXFORMAT_DXT1:
 		case R200_TXFORMAT_AI88:
 		case R200_TXFORMAT_ARGB1555:
 		case R200_TXFORMAT_RGB565:
@@ -418,9 +417,16 @@
 		case R200_TXFORMAT_ABGR8888:
 		case R200_TXFORMAT_BGR111110:
 		case R200_TXFORMAT_LDVDU8888:
+			track->textures[i].cpp = 4;
+			break;
+		case R200_TXFORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
 		case R200_TXFORMAT_DXT23:
 		case R200_TXFORMAT_DXT45:
-			track->textures[i].cpp = 4;
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
 			break;
 		}
 		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 83378c3..83490c2 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -686,7 +686,15 @@
 			r100_cs_dump_packet(p, pkt);
 			return r;
 		}
-		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
+
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+			tile_flags |= R300_TXO_MACRO_TILE;
+		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+			tile_flags |= R300_TXO_MICRO_TILE;
+
+		tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+		tmp |= tile_flags;
+		ib[idx] = tmp;
 		track->textures[i].robj = reloc->robj;
 		break;
 	/* Tracked registers */
@@ -852,7 +860,6 @@
 		case R300_TX_FORMAT_Z6Y5X5:
 		case R300_TX_FORMAT_W4Z4Y4X4:
 		case R300_TX_FORMAT_W1Z5Y5X5:
-		case R300_TX_FORMAT_DXT1:
 		case R300_TX_FORMAT_D3DMFT_CxV8U8:
 		case R300_TX_FORMAT_B8G8_B8G8:
 		case R300_TX_FORMAT_G8R8_G8B8:
@@ -866,8 +873,6 @@
 		case 0x17:
 		case R300_TX_FORMAT_FL_I32:
 		case 0x1e:
-		case R300_TX_FORMAT_DXT3:
-		case R300_TX_FORMAT_DXT5:
 			track->textures[i].cpp = 4;
 			break;
 		case R300_TX_FORMAT_W16Z16Y16X16:
@@ -878,6 +883,15 @@
 		case R300_TX_FORMAT_FL_R32G32B32A32:
 			track->textures[i].cpp = 16;
 			break;
+		case R300_TX_FORMAT_DXT1:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
+			break;
+		case R300_TX_FORMAT_DXT3:
+		case R300_TX_FORMAT_DXT5:
+			track->textures[i].cpp = 1;
+			track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
+			break;
 		default:
 			DRM_ERROR("Invalid texture format %u\n",
 				  (idx_value & 0x1F));
@@ -1324,6 +1338,8 @@
 	r300_errata(rdev);
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	r300_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 36656bd..a0ac3c1 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1863,6 +1863,14 @@
 	}
 	r600_gpu_init(rdev);
 
+	if (!rdev->r600_blit.shader_obj) {
+		r = r600_blit_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed blitter (%d).\n", r);
+			return r;
+		}
+	}
+
 	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
 	if (unlikely(r != 0))
 		return r;
@@ -2038,12 +2046,6 @@
 	if (r)
 		return r;
 
-	r = r600_blit_init(rdev);
-	if (r) {
-		DRM_ERROR("radeon: failed blitter (%d).\n", r);
-		return r;
-	}
-
 	rdev->accel_working = true;
 	r = r600_startup(rdev);
 	if (r) {
@@ -2065,6 +2067,10 @@
 			rdev->accel_working = false;
 		}
 	}
+
+	r = r600_audio_init(rdev);
+	if (r)
+		return r; /* TODO error handling */
 	return 0;
 }
 
@@ -2073,6 +2079,7 @@
 	/* Suspend operations */
 	r600_suspend(rdev);
 
+	r600_audio_fini(rdev);
 	r600_blit_fini(rdev);
 	r600_irq_fini(rdev);
 	radeon_irq_kms_fini(rdev);
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
new file mode 100644
index 0000000..99e2c38
--- /dev/null
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Christian König.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+#include "drmP.h"
+#include "radeon.h"
+#include "radeon_reg.h"
+#include "atom.h"
+
+#define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
+
+/*
+ * check if the chipset is supported
+ */
+static int r600_audio_chipset_supported(struct radeon_device *rdev)
+{
+	return rdev->family >= CHIP_R600
+		|| rdev->family == CHIP_RS600
+		|| rdev->family == CHIP_RS690
+		|| rdev->family == CHIP_RS740;
+}
+
+/*
+ * current number of channels
+ */
+static int r600_audio_channels(struct radeon_device *rdev)
+{
+	return (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0x7) + 1;
+}
+
+/*
+ * current bits per sample
+ */
+static int r600_audio_bits_per_sample(struct radeon_device *rdev)
+{
+	uint32_t value = (RREG32(R600_AUDIO_RATE_BPS_CHANNEL) & 0xF0) >> 4;
+	switch (value) {
+	case 0x0: return  8;
+	case 0x1: return 16;
+	case 0x2: return 20;
+	case 0x3: return 24;
+	case 0x4: return 32;
+	}
+
+	DRM_ERROR("Unknown bits per sample 0x%x using 16 instead.\n", (int)value);
+
+	return 16;
+}
+
+/*
+ * current sampling rate in HZ
+ */
+static int r600_audio_rate(struct radeon_device *rdev)
+{
+	uint32_t value = RREG32(R600_AUDIO_RATE_BPS_CHANNEL);
+	uint32_t result;
+
+	if (value & 0x4000)
+		result = 44100;
+	else
+		result = 48000;
+
+	result *= ((value >> 11) & 0x7) + 1;
+	result /= ((value >> 8) & 0x7) + 1;
+
+	return result;
+}
+
+/*
+ * iec 60958 status bits
+ */
+static uint8_t r600_audio_status_bits(struct radeon_device *rdev)
+{
+	return RREG32(R600_AUDIO_STATUS_BITS) & 0xff;
+}
+
+/*
+ * iec 60958 category code
+ */
+static uint8_t r600_audio_category_code(struct radeon_device *rdev)
+{
+	return (RREG32(R600_AUDIO_STATUS_BITS) >> 8) & 0xff;
+}
+
+/*
+ * update all hdmi interfaces with current audio parameters
+ */
+static void r600_audio_update_hdmi(unsigned long param)
+{
+	struct radeon_device *rdev = (struct radeon_device *)param;
+	struct drm_device *dev = rdev->ddev;
+
+	int channels = r600_audio_channels(rdev);
+	int rate = r600_audio_rate(rdev);
+	int bps = r600_audio_bits_per_sample(rdev);
+	uint8_t status_bits = r600_audio_status_bits(rdev);
+	uint8_t category_code = r600_audio_category_code(rdev);
+
+	struct drm_encoder *encoder;
+	int changes = 0;
+
+	changes |= channels != rdev->audio_channels;
+	changes |= rate != rdev->audio_rate;
+	changes |= bps != rdev->audio_bits_per_sample;
+	changes |= status_bits != rdev->audio_status_bits;
+	changes |= category_code != rdev->audio_category_code;
+
+	if (changes) {
+		rdev->audio_channels = channels;
+		rdev->audio_rate = rate;
+		rdev->audio_bits_per_sample = bps;
+		rdev->audio_status_bits = status_bits;
+		rdev->audio_category_code = category_code;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (changes || r600_hdmi_buffer_status_changed(encoder))
+			r600_hdmi_update_audio_settings(
+				encoder, channels,
+				rate, bps, status_bits,
+				category_code);
+	}
+
+	mod_timer(&rdev->audio_timer,
+		jiffies + msecs_to_jiffies(AUDIO_TIMER_INTERVALL));
+}
+
+/*
+ * initialize the audio vars and register the update timer
+ */
+int r600_audio_init(struct radeon_device *rdev)
+{
+	if (!r600_audio_chipset_supported(rdev))
+		return 0;
+
+	DRM_INFO("%s audio support", radeon_audio ? "Enabling" : "Disabling");
+	WREG32_P(R600_AUDIO_ENABLE, radeon_audio ? 0x81000000 : 0x0, ~0x81000000);
+
+	rdev->audio_channels = -1;
+	rdev->audio_rate = -1;
+	rdev->audio_bits_per_sample = -1;
+	rdev->audio_status_bits = 0;
+	rdev->audio_category_code = 0;
+
+	setup_timer(
+		&rdev->audio_timer,
+		r600_audio_update_hdmi,
+		(unsigned long)rdev);
+
+	mod_timer(&rdev->audio_timer, jiffies + 1);
+
+	return 0;
+}
+
+/*
+ * determin how the encoders and audio interface is wired together
+ */
+int r600_audio_tmds_index(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	struct drm_encoder *other;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		return 0;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		/* special case check if an TMDS1 is present */
+		list_for_each_entry(other, &dev->mode_config.encoder_list, head) {
+			if (to_radeon_encoder(other)->encoder_id ==
+				ENCODER_OBJECT_ID_INTERNAL_TMDS1)
+				return 1;
+		}
+		return 0;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		return 1;
+
+	default:
+		DRM_ERROR("Unsupported encoder type 0x%02X\n",
+			  radeon_encoder->encoder_id);
+		return -1;
+	}
+}
+
+/*
+ * atach the audio codec to the clock source of the encoder
+ */
+void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int base_rate = 48000;
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		WREG32_P(R600_AUDIO_TIMING, 0, ~0x301);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		WREG32_P(R600_AUDIO_TIMING, 0x100, ~0x301);
+		break;
+
+	default:
+		DRM_ERROR("Unsupported encoder type 0x%02X\n",
+			  radeon_encoder->encoder_id);
+		return;
+	}
+
+	switch (r600_audio_tmds_index(encoder)) {
+	case 0:
+		WREG32(R600_AUDIO_PLL1_MUL, base_rate*50);
+		WREG32(R600_AUDIO_PLL1_DIV, clock*100);
+		WREG32(R600_AUDIO_CLK_SRCSEL, 0);
+		break;
+
+	case 1:
+		WREG32(R600_AUDIO_PLL2_MUL, base_rate*50);
+		WREG32(R600_AUDIO_PLL2_DIV, clock*100);
+		WREG32(R600_AUDIO_CLK_SRCSEL, 1);
+		break;
+	}
+}
+
+/*
+ * release the audio timer
+ * TODO: How to do this correctly on SMP systems?
+ */
+void r600_audio_fini(struct radeon_device *rdev)
+{
+	if (!r600_audio_chipset_supported(rdev))
+		return;
+
+	WREG32_P(R600_AUDIO_ENABLE, 0x0, ~0x81000000);
+
+	del_timer(&rdev->audio_timer);
+}
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
new file mode 100644
index 0000000..fcc949d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Christian König.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+#include "drmP.h"
+#include "radeon_drm.h"
+#include "radeon.h"
+#include "atom.h"
+
+/*
+ * HDMI color format
+ */
+enum r600_hdmi_color_format {
+	RGB = 0,
+	YCC_422 = 1,
+	YCC_444 = 2
+};
+
+/*
+ * IEC60958 status bits
+ */
+enum r600_hdmi_iec_status_bits {
+	AUDIO_STATUS_DIG_ENABLE   = 0x01,
+	AUDIO_STATUS_V	    = 0x02,
+	AUDIO_STATUS_VCFG	 = 0x04,
+	AUDIO_STATUS_EMPHASIS     = 0x08,
+	AUDIO_STATUS_COPYRIGHT    = 0x10,
+	AUDIO_STATUS_NONAUDIO     = 0x20,
+	AUDIO_STATUS_PROFESSIONAL = 0x40,
+	AUDIO_STATUS_LEVEL	= 0x80
+};
+
+struct {
+	uint32_t Clock;
+
+	int N_32kHz;
+	int CTS_32kHz;
+
+	int N_44_1kHz;
+	int CTS_44_1kHz;
+
+	int N_48kHz;
+	int CTS_48kHz;
+
+} r600_hdmi_ACR[] = {
+    /*	     32kHz	  44.1kHz	48kHz    */
+    /* Clock      N     CTS      N     CTS      N     CTS */
+    {  25174,  4576,  28125,  7007,  31250,  6864,  28125 }, /*  25,20/1.001 MHz */
+    {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
+    {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
+    {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
+    {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
+    {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
+    {  74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /*  74.25/1.001 MHz */
+    {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
+    { 148351, 11648, 421875,  8918, 234375,  5824, 140625 }, /* 148.50/1.001 MHz */
+    { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
+    {      0,  4096,      0,  6272,      0,  6144,      0 }  /* Other */
+};
+
+/*
+ * calculate CTS value if it's not found in the table
+ */
+static void r600_hdmi_calc_CTS(uint32_t clock, int *CTS, int N, int freq)
+{
+	if (*CTS == 0)
+		*CTS = clock*N/(128*freq)*1000;
+	DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n",
+		  N, *CTS, freq);
+}
+
+/*
+ * update the N and CTS parameters for a given pixel clock rate
+ */
+static void r600_hdmi_update_ACR(struct drm_encoder *encoder, uint32_t clock)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+	int CTS;
+	int N;
+	int i;
+
+	for (i = 0; r600_hdmi_ACR[i].Clock != clock && r600_hdmi_ACR[i].Clock != 0; i++);
+
+	CTS = r600_hdmi_ACR[i].CTS_32kHz;
+	N = r600_hdmi_ACR[i].N_32kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 32000);
+	WREG32(offset+R600_HDMI_32kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_32kHz_N, N);
+
+	CTS = r600_hdmi_ACR[i].CTS_44_1kHz;
+	N = r600_hdmi_ACR[i].N_44_1kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 44100);
+	WREG32(offset+R600_HDMI_44_1kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_44_1kHz_N, N);
+
+	CTS = r600_hdmi_ACR[i].CTS_48kHz;
+	N = r600_hdmi_ACR[i].N_48kHz;
+	r600_hdmi_calc_CTS(clock, &CTS, N, 48000);
+	WREG32(offset+R600_HDMI_48kHz_CTS, CTS << 12);
+	WREG32(offset+R600_HDMI_48kHz_N, N);
+}
+
+/*
+ * calculate the crc for a given info frame
+ */
+static void r600_hdmi_infoframe_checksum(uint8_t packetType,
+					 uint8_t versionNumber,
+					 uint8_t length,
+					 uint8_t *frame)
+{
+    int i;
+    frame[0] = packetType + versionNumber + length;
+    for (i = 1; i <= length; i++)
+	frame[0] += frame[i];
+    frame[0] = 0x100 - frame[0];
+}
+
+/*
+ * build a HDMI Video Info Frame
+ */
+static void r600_hdmi_videoinfoframe(
+	struct drm_encoder *encoder,
+	enum r600_hdmi_color_format color_format,
+	int active_information_present,
+	uint8_t active_format_aspect_ratio,
+	uint8_t scan_information,
+	uint8_t colorimetry,
+	uint8_t ex_colorimetry,
+	uint8_t quantization,
+	int ITC,
+	uint8_t picture_aspect_ratio,
+	uint8_t video_format_identification,
+	uint8_t pixel_repetition,
+	uint8_t non_uniform_picture_scaling,
+	uint8_t bar_info_data_valid,
+	uint16_t top_bar,
+	uint16_t bottom_bar,
+	uint16_t left_bar,
+	uint16_t right_bar
+)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint8_t frame[14];
+
+	frame[0x0] = 0;
+	frame[0x1] =
+		(scan_information & 0x3) |
+		((bar_info_data_valid & 0x3) << 2) |
+		((active_information_present & 0x1) << 4) |
+		((color_format & 0x3) << 5);
+	frame[0x2] =
+		(active_format_aspect_ratio & 0xF) |
+		((picture_aspect_ratio & 0x3) << 4) |
+		((colorimetry & 0x3) << 6);
+	frame[0x3] =
+		(non_uniform_picture_scaling & 0x3) |
+		((quantization & 0x3) << 2) |
+		((ex_colorimetry & 0x7) << 4) |
+		((ITC & 0x1) << 7);
+	frame[0x4] = (video_format_identification & 0x7F);
+	frame[0x5] = (pixel_repetition & 0xF);
+	frame[0x6] = (top_bar & 0xFF);
+	frame[0x7] = (top_bar >> 8);
+	frame[0x8] = (bottom_bar & 0xFF);
+	frame[0x9] = (bottom_bar >> 8);
+	frame[0xA] = (left_bar & 0xFF);
+	frame[0xB] = (left_bar >> 8);
+	frame[0xC] = (right_bar & 0xFF);
+	frame[0xD] = (right_bar >> 8);
+
+	r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
+
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0,
+		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_1,
+		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x7] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_2,
+		frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
+	WREG32(offset+R600_HDMI_VIDEOINFOFRAME_3,
+		frame[0xC] | (frame[0xD] << 8));
+}
+
+/*
+ * build a Audio Info Frame
+ */
+static void r600_hdmi_audioinfoframe(
+	struct drm_encoder *encoder,
+	uint8_t channel_count,
+	uint8_t coding_type,
+	uint8_t sample_size,
+	uint8_t sample_frequency,
+	uint8_t format,
+	uint8_t channel_allocation,
+	uint8_t level_shift,
+	int downmix_inhibit
+)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint8_t frame[11];
+
+	frame[0x0] = 0;
+	frame[0x1] = (channel_count & 0x7) | ((coding_type & 0xF) << 4);
+	frame[0x2] = (sample_size & 0x3) | ((sample_frequency & 0x7) << 2);
+	frame[0x3] = format;
+	frame[0x4] = channel_allocation;
+	frame[0x5] = ((level_shift & 0xF) << 3) | ((downmix_inhibit & 0x1) << 7);
+	frame[0x6] = 0;
+	frame[0x7] = 0;
+	frame[0x8] = 0;
+	frame[0x9] = 0;
+	frame[0xA] = 0;
+
+	r600_hdmi_infoframe_checksum(0x84, 0x01, 0x0A, frame);
+
+	WREG32(offset+R600_HDMI_AUDIOINFOFRAME_0,
+		frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+	WREG32(offset+R600_HDMI_AUDIOINFOFRAME_1,
+		frame[0x4] | (frame[0x5] << 8) | (frame[0x6] << 16) | (frame[0x8] << 24));
+}
+
+/*
+ * test if audio buffer is filled enough to start playing
+ */
+static int r600_hdmi_is_audio_buffer_filled(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	return (RREG32(offset+R600_HDMI_STATUS) & 0x10) != 0;
+}
+
+/*
+ * have buffer status changed since last call?
+ */
+int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	int status, result;
+
+	if (!radeon_encoder->hdmi_offset)
+		return 0;
+
+	status = r600_hdmi_is_audio_buffer_filled(encoder);
+	result = radeon_encoder->hdmi_buffer_status != status;
+	radeon_encoder->hdmi_buffer_status = status;
+
+	return result;
+}
+
+/*
+ * write the audio workaround status to the hardware
+ */
+void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t offset = radeon_encoder->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	if (r600_hdmi_is_audio_buffer_filled(encoder)) {
+		/* disable audio workaround and start delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00000001, ~0x00001001);
+
+	} else if (radeon_encoder->hdmi_audio_workaround) {
+		/* enable audio workaround and start delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00001001, ~0x00001001);
+
+	} else {
+		/* disable audio workaround and stop delivering of audio frames */
+		WREG32_P(offset+R600_HDMI_CNTL, 0x00000000, ~0x00001001);
+	}
+}
+
+
+/*
+ * update the info frames with the data from the current display mode
+ */
+void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	r600_audio_set_clock(encoder, mode->clock);
+
+	WREG32(offset+R600_HDMI_UNKNOWN_0, 0x1000);
+	WREG32(offset+R600_HDMI_UNKNOWN_1, 0x0);
+	WREG32(offset+R600_HDMI_UNKNOWN_2, 0x1000);
+
+	r600_hdmi_update_ACR(encoder, mode->clock);
+
+	WREG32(offset+R600_HDMI_VIDEOCNTL, 0x13);
+
+	WREG32(offset+R600_HDMI_VERSION, 0x202);
+
+	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+	/* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
+	WREG32(offset+R600_HDMI_AUDIO_DEBUG_3, 0x00000001);
+
+	r600_hdmi_audio_workaround(encoder);
+
+	/* audio packets per line, does anyone know how to calc this ? */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x00040000, ~0x001F0000);
+
+	/* update? reset? don't realy know */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x14000000, ~0x14000000);
+}
+
+/*
+ * update settings with current parameters from audio engine
+ */
+void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
+				     int channels,
+				     int rate,
+				     int bps,
+				     uint8_t status_bits,
+				     uint8_t category_code)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	uint32_t iec;
+
+	if (!offset)
+		return;
+
+	DRM_DEBUG("%s with %d channels, %d Hz sampling rate, %d bits per sample,\n",
+		 r600_hdmi_is_audio_buffer_filled(encoder) ? "playing" : "stopped",
+		channels, rate, bps);
+	DRM_DEBUG("0x%02X IEC60958 status bits and 0x%02X category code\n",
+		  (int)status_bits, (int)category_code);
+
+	iec = 0;
+	if (status_bits & AUDIO_STATUS_PROFESSIONAL)
+		iec |= 1 << 0;
+	if (status_bits & AUDIO_STATUS_NONAUDIO)
+		iec |= 1 << 1;
+	if (status_bits & AUDIO_STATUS_COPYRIGHT)
+		iec |= 1 << 2;
+	if (status_bits & AUDIO_STATUS_EMPHASIS)
+		iec |= 1 << 3;
+
+	iec |= category_code << 8;
+
+	switch (rate) {
+	case  32000: iec |= 0x3 << 24; break;
+	case  44100: iec |= 0x0 << 24; break;
+	case  88200: iec |= 0x8 << 24; break;
+	case 176400: iec |= 0xc << 24; break;
+	case  48000: iec |= 0x2 << 24; break;
+	case  96000: iec |= 0xa << 24; break;
+	case 192000: iec |= 0xe << 24; break;
+	}
+
+	WREG32(offset+R600_HDMI_IEC60958_1, iec);
+
+	iec = 0;
+	switch (bps) {
+	case 16: iec |= 0x2; break;
+	case 20: iec |= 0x3; break;
+	case 24: iec |= 0xb; break;
+	}
+	if (status_bits & AUDIO_STATUS_V)
+		iec |= 0x5 << 16;
+
+	WREG32_P(offset+R600_HDMI_IEC60958_2, iec, ~0x5000f);
+
+	/* 0x021 or 0x031 sets the audio frame length */
+	WREG32(offset+R600_HDMI_AUDIOCNTL, 0x31);
+	r600_hdmi_audioinfoframe(encoder, channels-1, 0, 0, 0, 0, 0, 0, 0);
+
+	r600_hdmi_audio_workaround(encoder);
+
+	/* update? reset? don't realy know */
+	WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
+}
+
+/*
+ * enable/disable the HDMI engine
+ */
+void r600_hdmi_enable(struct drm_encoder *encoder, int enable)
+{
+	struct drm_device *dev = encoder->dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
+
+	if (!offset)
+		return;
+
+	DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset);
+
+	/* some version of atombios ignore the enable HDMI flag
+	 * so enabling/disabling HDMI was moved here for TMDS1+2 */
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+		WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4);
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4);
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0);
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		/* This part is doubtfull in my opinion */
+		WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0);
+		break;
+
+	default:
+		DRM_ERROR("unknown HDMI output type\n");
+		break;
+	}
+}
+
+/*
+ * determin at which register offset the HDMI encoder is
+ */
+void r600_hdmi_init(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	switch (radeon_encoder->encoder_id) {
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+		radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
+		switch (r600_audio_tmds_index(encoder)) {
+		case 0:
+			radeon_encoder->hdmi_offset = R600_HDMI_TMDS1;
+			break;
+		case 1:
+			radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
+			break;
+		default:
+			radeon_encoder->hdmi_offset = 0;
+			break;
+		}
+	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+		radeon_encoder->hdmi_offset = R600_HDMI_TMDS2;
+		break;
+
+	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
+		radeon_encoder->hdmi_offset = R600_HDMI_DIG;
+		break;
+
+	default:
+		radeon_encoder->hdmi_offset = 0;
+		break;
+	}
+
+	DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n",
+		  radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
+
+	/* TODO: make this configureable */
+	radeon_encoder->hdmi_audio_workaround = 0;
+}
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h
index e2d1f5f..d0e28ff 100644
--- a/drivers/gpu/drm/radeon/r600_reg.h
+++ b/drivers/gpu/drm/radeon/r600_reg.h
@@ -110,5 +110,79 @@
 #define R600_BIOS_6_SCRATCH               0x173c
 #define R600_BIOS_7_SCRATCH               0x1740
 
+/* Audio, these regs were reverse enginered,
+ * so the chance is high that the naming is wrong
+ * R6xx+ ??? */
+
+/* Audio clocks */
+#define R600_AUDIO_PLL1_MUL               0x0514
+#define R600_AUDIO_PLL1_DIV               0x0518
+#define R600_AUDIO_PLL2_MUL               0x0524
+#define R600_AUDIO_PLL2_DIV               0x0528
+#define R600_AUDIO_CLK_SRCSEL             0x0534
+
+/* Audio general */
+#define R600_AUDIO_ENABLE                 0x7300
+#define R600_AUDIO_TIMING                 0x7344
+
+/* Audio params */
+#define R600_AUDIO_VENDOR_ID              0x7380
+#define R600_AUDIO_REVISION_ID            0x7384
+#define R600_AUDIO_ROOT_NODE_COUNT        0x7388
+#define R600_AUDIO_NID1_NODE_COUNT        0x738c
+#define R600_AUDIO_NID1_TYPE              0x7390
+#define R600_AUDIO_SUPPORTED_SIZE_RATE    0x7394
+#define R600_AUDIO_SUPPORTED_CODEC        0x7398
+#define R600_AUDIO_SUPPORTED_POWER_STATES 0x739c
+#define R600_AUDIO_NID2_CAPS              0x73a0
+#define R600_AUDIO_NID3_CAPS              0x73a4
+#define R600_AUDIO_NID3_PIN_CAPS          0x73a8
+
+/* Audio conn list */
+#define R600_AUDIO_CONN_LIST_LEN          0x73ac
+#define R600_AUDIO_CONN_LIST              0x73b0
+
+/* Audio verbs */
+#define R600_AUDIO_RATE_BPS_CHANNEL       0x73c0
+#define R600_AUDIO_PLAYING                0x73c4
+#define R600_AUDIO_IMPLEMENTATION_ID      0x73c8
+#define R600_AUDIO_CONFIG_DEFAULT         0x73cc
+#define R600_AUDIO_PIN_SENSE              0x73d0
+#define R600_AUDIO_PIN_WIDGET_CNTL        0x73d4
+#define R600_AUDIO_STATUS_BITS            0x73d8
+
+/* HDMI base register addresses */
+#define R600_HDMI_TMDS1                   0x7400
+#define R600_HDMI_TMDS2                   0x7700
+#define R600_HDMI_DIG                     0x7800
+
+/* HDMI registers */
+#define R600_HDMI_ENABLE           0x00
+#define R600_HDMI_STATUS           0x04
+#define R600_HDMI_CNTL             0x08
+#define R600_HDMI_UNKNOWN_0        0x0C
+#define R600_HDMI_AUDIOCNTL        0x10
+#define R600_HDMI_VIDEOCNTL        0x14
+#define R600_HDMI_VERSION          0x18
+#define R600_HDMI_UNKNOWN_1        0x28
+#define R600_HDMI_VIDEOINFOFRAME_0 0x54
+#define R600_HDMI_VIDEOINFOFRAME_1 0x58
+#define R600_HDMI_VIDEOINFOFRAME_2 0x5c
+#define R600_HDMI_VIDEOINFOFRAME_3 0x60
+#define R600_HDMI_32kHz_CTS        0xac
+#define R600_HDMI_32kHz_N          0xb0
+#define R600_HDMI_44_1kHz_CTS      0xb4
+#define R600_HDMI_44_1kHz_N        0xb8
+#define R600_HDMI_48kHz_CTS        0xbc
+#define R600_HDMI_48kHz_N          0xc0
+#define R600_HDMI_AUDIOINFOFRAME_0 0xcc
+#define R600_HDMI_AUDIOINFOFRAME_1 0xd0
+#define R600_HDMI_IEC60958_1       0xd4
+#define R600_HDMI_IEC60958_2       0xd8
+#define R600_HDMI_UNKNOWN_2        0xdc
+#define R600_HDMI_AUDIO_DEBUG_0    0xe0
+#define R600_HDMI_AUDIO_DEBUG_1    0xe4
+#define R600_HDMI_AUDIO_DEBUG_2    0xe8
+#define R600_HDMI_AUDIO_DEBUG_3    0xec
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c938bb5..cd650fd 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -89,6 +89,7 @@
 extern int radeon_connector_table;
 extern int radeon_tv;
 extern int radeon_new_pll;
+extern int radeon_audio;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -814,6 +815,14 @@
 	struct r600_ih ih; /* r6/700 interrupt ring */
 	struct workqueue_struct *wq;
 	struct work_struct hotplug_work;
+
+	/* audio stuff */
+	struct timer_list	audio_timer;
+	int			audio_channels;
+	int			audio_rate;
+	int			audio_bits_per_sample;
+	uint8_t			audio_status_bits;
+	uint8_t			audio_category_code;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -1016,6 +1025,7 @@
 extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable);
 extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
 extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
+extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
 
 /* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
 struct r100_mc_save {
@@ -1146,6 +1156,21 @@
 extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
 extern int r600_irq_set(struct radeon_device *rdev);
 
+extern int r600_audio_init(struct radeon_device *rdev);
+extern int r600_audio_tmds_index(struct drm_encoder *encoder);
+extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
+extern void r600_audio_fini(struct radeon_device *rdev);
+extern void r600_hdmi_init(struct drm_encoder *encoder);
+extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable);
+extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
+extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
+extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
+					    int channels,
+					    int rate,
+					    int bps,
+					    uint8_t status_bits,
+					    uint8_t category_code);
+
 #include "radeon_object.h"
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index c5c45e6..dbd56ef 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -87,6 +87,7 @@
 int radeon_connector_table = 0;
 int radeon_tv = 1;
 int radeon_new_pll = 1;
+int radeon_audio = 1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -124,6 +125,9 @@
 MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips");
 module_param_named(new_pll, radeon_new_pll, int, 0444);
 
+MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
+module_param_named(audio, radeon_audio, int, 0444);
+
 static int radeon_suspend(struct drm_device *dev, pm_message_t state)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index b4f23ec..0d1d908 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -438,6 +438,7 @@
 	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 	union lvds_encoder_control args;
 	int index = 0;
+	int hdmi_detected = 0;
 	uint8_t frev, crev;
 	struct radeon_encoder_atom_dig *dig;
 	struct drm_connector *connector;
@@ -458,6 +459,9 @@
 	if (!radeon_connector->con_priv)
 		return;
 
+	if (drm_detect_hdmi_monitor(radeon_connector->edid))
+		hdmi_detected = 1;
+
 	dig_connector = radeon_connector->con_priv;
 
 	memset(&args, 0, sizeof(args));
@@ -487,7 +491,7 @@
 		case 1:
 			args.v1.ucMisc = 0;
 			args.v1.ucAction = action;
-			if (drm_detect_hdmi_monitor(radeon_connector->edid))
+			if (hdmi_detected)
 				args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
 			args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
@@ -512,7 +516,7 @@
 				if (dig->coherent_mode)
 					args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT;
 			}
-			if (drm_detect_hdmi_monitor(radeon_connector->edid))
+			if (hdmi_detected)
 				args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE;
 			args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
 			args.v2.ucTruncate = 0;
@@ -552,7 +556,7 @@
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
+	r600_hdmi_enable(encoder, hdmi_detected);
 }
 
 int
@@ -893,7 +897,6 @@
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
 }
 
 static void
@@ -1162,7 +1165,6 @@
 	}
 
 	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
 }
 
 static void
@@ -1265,6 +1267,8 @@
 		break;
 	}
 	atombios_apply_encoder_quirks(encoder, adjusted_mode);
+
+	r600_hdmi_setmode(encoder, adjusted_mode);
 }
 
 static bool
@@ -1510,4 +1514,6 @@
 		drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
 		break;
 	}
+
+	r600_hdmi_init(encoder);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 2944486..60df2d7 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -66,8 +66,9 @@
 	}
 	r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj);
 	if (r) {
-		DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
-			  size, initial_domain, alignment);
+		if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
+				  size, initial_domain, alignment, r);
 		mutex_lock(&rdev->ddev->struct_mutex);
 		drm_gem_object_unreference(gobj);
 		mutex_unlock(&rdev->ddev->struct_mutex);
@@ -350,9 +351,10 @@
 	rbo = gobj->driver_private;
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
-		return r;
+		goto out;
 	radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch);
 	radeon_bo_unreserve(rbo);
+out:
 	mutex_lock(&dev->struct_mutex);
 	drm_gem_object_unreference(gobj);
 	mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 44d4b65..3dcbe13 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -334,6 +334,9 @@
 	enum radeon_rmx_type rmx_type;
 	struct drm_display_mode native_mode;
 	void *enc_priv;
+	int hdmi_offset;
+	int hdmi_audio_workaround;
+	int hdmi_buffer_status;
 };
 
 struct radeon_connector_atom_dig {
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 544e18f..d9ffe1f 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -56,6 +56,13 @@
 	kfree(bo);
 }
 
+bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
+{
+	if (bo->destroy == &radeon_ttm_bo_destroy)
+		return true;
+	return false;
+}
+
 void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
 {
 	u32 c = 0;
@@ -71,6 +78,8 @@
 		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
 	if (domain & RADEON_GEM_DOMAIN_CPU)
 		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+	if (!c)
+		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
 	rbo->placement.num_placement = c;
 	rbo->placement.num_busy_placement = c;
 }
@@ -481,14 +490,20 @@
 }
 
 void radeon_bo_move_notify(struct ttm_buffer_object *bo,
-				struct ttm_mem_reg *mem)
+			   struct ttm_mem_reg *mem)
 {
-	struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
+	struct radeon_bo *rbo;
+	if (!radeon_ttm_bo_is_radeon_bo(bo))
+		return;
+	rbo = container_of(bo, struct radeon_bo, tbo);
 	radeon_bo_check_tiling(rbo, 0, 1);
 }
 
 void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 {
-	struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
+	struct radeon_bo *rbo;
+	if (!radeon_ttm_bo_is_radeon_bo(bo))
+		return;
+	rbo = container_of(bo, struct radeon_bo, tbo);
 	radeon_bo_check_tiling(rbo, 0, 0);
 }
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index f6b69c2..a02f180 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -59,19 +59,17 @@
  *
  * Returns:
  * -EBUSY: buffer is busy and @no_wait is true
- * -ERESTART: A wait for the buffer to become unreserved was interrupted by
+ * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
  * a signal. Release all buffer reservations and return to user-space.
  */
 static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
 {
 	int r;
 
-retry:
 	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
 	if (unlikely(r != 0)) {
-		if (r == -ERESTART)
-			goto retry;
-		dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
 		return r;
 	}
 	return 0;
@@ -125,12 +123,10 @@
 {
 	int r;
 
-retry:
 	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
 	if (unlikely(r != 0)) {
-		if (r == -ERESTART)
-			goto retry;
-		dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
+		if (r != -ERESTARTSYS)
+			dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
 		return r;
 	}
 	spin_lock(&bo->tbo.lock);
@@ -140,8 +136,6 @@
 		r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
 	spin_unlock(&bo->tbo.lock);
 	ttm_bo_unreserve(&bo->tbo);
-	if (unlikely(r == -ERESTART))
-		goto retry;
 	return r;
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 34b08d3..8bce64c 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -44,8 +44,11 @@
 	struct drm_device *dev = node->minor->dev;
 	struct radeon_device *rdev = dev->dev_private;
 
-	seq_printf(m, "engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
-	seq_printf(m, "memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
+	seq_printf(m, "default engine clock: %u0 kHz\n", rdev->clock.default_sclk);
+	seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
+	seq_printf(m, "default memory clock: %u0 kHz\n", rdev->clock.default_mclk);
+	if (rdev->asic->get_memory_clock)
+		seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 5a19d52..d7fd160 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -200,7 +200,19 @@
 static void radeon_evict_flags(struct ttm_buffer_object *bo,
 				struct ttm_placement *placement)
 {
-	struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
+	struct radeon_bo *rbo;
+	static u32 placements = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
+
+	if (!radeon_ttm_bo_is_radeon_bo(bo)) {
+		placement->fpfn = 0;
+		placement->lpfn = 0;
+		placement->placement = &placements;
+		placement->busy_placement = &placements;
+		placement->num_placement = 1;
+		placement->num_busy_placement = 1;
+		return;
+	}
+	rbo = container_of(bo, struct radeon_bo, tbo);
 	switch (bo->mem.mem_type) {
 	case TTM_PL_VRAM:
 		radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT);
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index c1fcddd..368415d 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -497,6 +497,8 @@
 
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
+	/* Initialize power management */
+	radeon_pm_init(rdev);
 	/* Get vram informations */
 	rs400_vram_info(rdev);
 	/* Initialize memory controller (also test AGP) */
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index fbb0357..3bcb66e 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -892,6 +892,14 @@
 	}
 	rv770_gpu_init(rdev);
 
+	if (!rdev->r600_blit.shader_obj) {
+		r = r600_blit_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed blitter (%d).\n", r);
+			return r;
+		}
+	}
+
 	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
 	if (unlikely(r != 0))
 		return r;
@@ -1051,12 +1059,6 @@
 	if (r)
 		return r;
 
-	r = r600_blit_init(rdev);
-	if (r) {
-		DRM_ERROR("radeon: failed blitter (%d).\n", r);
-		return r;
-	}
-
 	rdev->accel_working = true;
 	r = rv770_startup(rdev);
 	if (r) {
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 1fbb2ee..2920f9a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -71,34 +71,34 @@
 	return -EINVAL;
 }
 
-static void ttm_mem_type_manager_debug(struct ttm_bo_global *glob,
-					struct ttm_mem_type_manager *man)
+static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type)
 {
+	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+
 	printk(KERN_ERR TTM_PFX "    has_type: %d\n", man->has_type);
 	printk(KERN_ERR TTM_PFX "    use_type: %d\n", man->use_type);
 	printk(KERN_ERR TTM_PFX "    flags: 0x%08X\n", man->flags);
 	printk(KERN_ERR TTM_PFX "    gpu_offset: 0x%08lX\n", man->gpu_offset);
 	printk(KERN_ERR TTM_PFX "    io_offset: 0x%08lX\n", man->io_offset);
 	printk(KERN_ERR TTM_PFX "    io_size: %ld\n", man->io_size);
-	printk(KERN_ERR TTM_PFX "    size: %ld\n", (unsigned long)man->size);
+	printk(KERN_ERR TTM_PFX "    size: %llu\n", man->size);
 	printk(KERN_ERR TTM_PFX "    available_caching: 0x%08X\n",
 		man->available_caching);
 	printk(KERN_ERR TTM_PFX "    default_caching: 0x%08X\n",
 		man->default_caching);
-	spin_lock(&glob->lru_lock);
-	drm_mm_debug_table(&man->manager, TTM_PFX);
-	spin_unlock(&glob->lru_lock);
+	if (mem_type != TTM_PL_SYSTEM) {
+		spin_lock(&bdev->glob->lru_lock);
+		drm_mm_debug_table(&man->manager, TTM_PFX);
+		spin_unlock(&bdev->glob->lru_lock);
+	}
 }
 
 static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo,
 					struct ttm_placement *placement)
 {
-	struct ttm_bo_device *bdev = bo->bdev;
-	struct ttm_bo_global *glob = bo->glob;
-	struct ttm_mem_type_manager *man;
 	int i, ret, mem_type;
 
-	printk(KERN_ERR TTM_PFX "No space for %p (%ld pages, %ldK, %ldM)\n",
+	printk(KERN_ERR TTM_PFX "No space for %p (%lu pages, %luK, %luM)\n",
 		bo, bo->mem.num_pages, bo->mem.size >> 10,
 		bo->mem.size >> 20);
 	for (i = 0; i < placement->num_placement; i++) {
@@ -106,10 +106,9 @@
 						&mem_type);
 		if (ret)
 			return;
-		man = &bdev->man[mem_type];
 		printk(KERN_ERR TTM_PFX "  placement[%d]=0x%08X (%d)\n",
 			i, placement->placement[i], mem_type);
-		ttm_mem_type_manager_debug(glob, man);
+		ttm_mem_type_debug(bo->bdev, mem_type);
 	}
 }
 
@@ -465,6 +464,8 @@
 		spin_unlock(&bo->lock);
 
 		spin_lock(&glob->lru_lock);
+		put_count = ttm_bo_del_from_lru(bo);
+
 		ret = ttm_bo_reserve_locked(bo, false, false, false, 0);
 		BUG_ON(ret);
 		if (bo->ttm)
@@ -472,20 +473,19 @@
 
 		if (!list_empty(&bo->ddestroy)) {
 			list_del_init(&bo->ddestroy);
-			kref_put(&bo->list_kref, ttm_bo_ref_bug);
+			++put_count;
 		}
 		if (bo->mem.mm_node) {
 			bo->mem.mm_node->private = NULL;
 			drm_mm_put_block(bo->mem.mm_node);
 			bo->mem.mm_node = NULL;
 		}
-		put_count = ttm_bo_del_from_lru(bo);
 		spin_unlock(&glob->lru_lock);
 
 		atomic_set(&bo->reserved, 0);
 
 		while (put_count--)
-			kref_put(&bo->list_kref, ttm_bo_release_list);
+			kref_put(&bo->list_kref, ttm_bo_ref_bug);
 
 		return 0;
 	}
@@ -684,19 +684,45 @@
 	struct ttm_buffer_object *bo;
 	int ret, put_count = 0;
 
+retry:
 	spin_lock(&glob->lru_lock);
+	if (list_empty(&man->lru)) {
+		spin_unlock(&glob->lru_lock);
+		return -EBUSY;
+	}
+
 	bo = list_first_entry(&man->lru, struct ttm_buffer_object, lru);
 	kref_get(&bo->list_kref);
-	ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, false, 0);
-	if (likely(ret == 0))
-		put_count = ttm_bo_del_from_lru(bo);
+
+	ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
+
+	if (unlikely(ret == -EBUSY)) {
+		spin_unlock(&glob->lru_lock);
+		if (likely(!no_wait))
+			ret = ttm_bo_wait_unreserved(bo, interruptible);
+
+		kref_put(&bo->list_kref, ttm_bo_release_list);
+
+		/**
+		 * We *need* to retry after releasing the lru lock.
+		 */
+
+		if (unlikely(ret != 0))
+			return ret;
+		goto retry;
+	}
+
+	put_count = ttm_bo_del_from_lru(bo);
 	spin_unlock(&glob->lru_lock);
-	if (unlikely(ret != 0))
-		return ret;
+
+	BUG_ON(ret != 0);
+
 	while (put_count--)
 		kref_put(&bo->list_kref, ttm_bo_ref_bug);
+
 	ret = ttm_bo_evict(bo, interruptible, no_wait);
 	ttm_bo_unreserve(bo);
+
 	kref_put(&bo->list_kref, ttm_bo_release_list);
 	return ret;
 }
@@ -849,7 +875,7 @@
 	int i, ret;
 
 	mem->mm_node = NULL;
-	for (i = 0; i <= placement->num_placement; ++i) {
+	for (i = 0; i < placement->num_placement; ++i) {
 		ret = ttm_mem_type_from_flags(placement->placement[i],
 						&mem_type);
 		if (ret)
@@ -900,8 +926,8 @@
 	if (!type_found)
 		return -EINVAL;
 
-	for (i = 0; i <= placement->num_busy_placement; ++i) {
-		ret = ttm_mem_type_from_flags(placement->placement[i],
+	for (i = 0; i < placement->num_busy_placement; ++i) {
+		ret = ttm_mem_type_from_flags(placement->busy_placement[i],
 						&mem_type);
 		if (ret)
 			return ret;
@@ -911,7 +937,7 @@
 		if (!ttm_bo_mt_compatible(man,
 						bo->type == ttm_bo_type_user,
 						mem_type,
-						placement->placement[i],
+						placement->busy_placement[i],
 						&cur_flags))
 			continue;
 
@@ -921,7 +947,7 @@
 		 * Use the access and other non-mapping-related flag bits from
 		 * the memory placement flags to the current flags
 		 */
-		ttm_flag_masked(&cur_flags, placement->placement[i],
+		ttm_flag_masked(&cur_flags, placement->busy_placement[i],
 				~TTM_PL_MASK_MEMTYPE);
 
 		ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
@@ -1115,6 +1141,7 @@
 	bo->glob = bdev->glob;
 	bo->type = type;
 	bo->num_pages = num_pages;
+	bo->mem.size = num_pages << PAGE_SHIFT;
 	bo->mem.mem_type = TTM_PL_SYSTEM;
 	bo->mem.num_pages = bo->num_pages;
 	bo->mem.mm_node = NULL;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 609a85a..668dbe8 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -320,7 +320,7 @@
 		return -EFAULT;
 
 	driver = bo->bdev->driver;
-	if (unlikely(driver->verify_access)) {
+	if (unlikely(!driver->verify_access)) {
 		ret = -EPERM;
 		goto out_unref;
 	}
diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig
new file mode 100644
index 0000000..f20b8bc
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/Kconfig
@@ -0,0 +1,13 @@
+config DRM_VMWGFX
+	tristate "DRM driver for VMware Virtual GPU"
+	depends on DRM && PCI
+	select FB_DEFERRED_IO
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select DRM_TTM
+	help
+	  KMS enabled DRM driver for SVGA2 virtual hardware.
+
+	  If unsure say n. The compiled module will be
+	  called vmwgfx.ko
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
new file mode 100644
index 0000000..1a3cb68
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -0,0 +1,9 @@
+
+ccflags-y := -Iinclude/drm
+
+vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
+	    vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \
+	    vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
+	    vmwgfx_overlay.o
+
+obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
new file mode 100644
index 0000000..77cb453
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga3d_reg.h
@@ -0,0 +1,1793 @@
+/**********************************************************
+ * Copyright 1998-2009 VMware, Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/*
+ * svga3d_reg.h --
+ *
+ *       SVGA 3D hardware definitions
+ */
+
+#ifndef _SVGA3D_REG_H_
+#define _SVGA3D_REG_H_
+
+#include "svga_reg.h"
+
+
+/*
+ * 3D Hardware Version
+ *
+ *   The hardware version is stored in the SVGA_FIFO_3D_HWVERSION fifo
+ *   register.   Is set by the host and read by the guest.  This lets
+ *   us make new guest drivers which are backwards-compatible with old
+ *   SVGA hardware revisions.  It does not let us support old guest
+ *   drivers.  Good enough for now.
+ *
+ */
+
+#define SVGA3D_MAKE_HWVERSION(major, minor)      (((major) << 16) | ((minor) & 0xFF))
+#define SVGA3D_MAJOR_HWVERSION(version)          ((version) >> 16)
+#define SVGA3D_MINOR_HWVERSION(version)          ((version) & 0xFF)
+
+typedef enum {
+   SVGA3D_HWVERSION_WS5_RC1   = SVGA3D_MAKE_HWVERSION(0, 1),
+   SVGA3D_HWVERSION_WS5_RC2   = SVGA3D_MAKE_HWVERSION(0, 2),
+   SVGA3D_HWVERSION_WS51_RC1  = SVGA3D_MAKE_HWVERSION(0, 3),
+   SVGA3D_HWVERSION_WS6_B1    = SVGA3D_MAKE_HWVERSION(1, 1),
+   SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4),
+   SVGA3D_HWVERSION_WS65_B1   = SVGA3D_MAKE_HWVERSION(2, 0),
+   SVGA3D_HWVERSION_CURRENT   = SVGA3D_HWVERSION_WS65_B1,
+} SVGA3dHardwareVersion;
+
+/*
+ * Generic Types
+ */
+
+typedef uint32 SVGA3dBool; /* 32-bit Bool definition */
+#define SVGA3D_NUM_CLIPPLANES                   6
+#define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS  8
+
+
+/*
+ * Surface formats.
+ *
+ * If you modify this list, be sure to keep GLUtil.c in sync. It
+ * includes the internal format definition of each surface in
+ * GLUtil_ConvertSurfaceFormat, and it contains a table of
+ * human-readable names in GLUtil_GetFormatName.
+ */
+
+typedef enum SVGA3dSurfaceFormat {
+   SVGA3D_FORMAT_INVALID = 0,
+
+   SVGA3D_X8R8G8B8       = 1,
+   SVGA3D_A8R8G8B8       = 2,
+
+   SVGA3D_R5G6B5         = 3,
+   SVGA3D_X1R5G5B5       = 4,
+   SVGA3D_A1R5G5B5       = 5,
+   SVGA3D_A4R4G4B4       = 6,
+
+   SVGA3D_Z_D32          = 7,
+   SVGA3D_Z_D16          = 8,
+   SVGA3D_Z_D24S8        = 9,
+   SVGA3D_Z_D15S1        = 10,
+
+   SVGA3D_LUMINANCE8            = 11,
+   SVGA3D_LUMINANCE4_ALPHA4     = 12,
+   SVGA3D_LUMINANCE16           = 13,
+   SVGA3D_LUMINANCE8_ALPHA8     = 14,
+
+   SVGA3D_DXT1           = 15,
+   SVGA3D_DXT2           = 16,
+   SVGA3D_DXT3           = 17,
+   SVGA3D_DXT4           = 18,
+   SVGA3D_DXT5           = 19,
+
+   SVGA3D_BUMPU8V8       = 20,
+   SVGA3D_BUMPL6V5U5     = 21,
+   SVGA3D_BUMPX8L8V8U8   = 22,
+   SVGA3D_BUMPL8V8U8     = 23,
+
+   SVGA3D_ARGB_S10E5     = 24,   /* 16-bit floating-point ARGB */
+   SVGA3D_ARGB_S23E8     = 25,   /* 32-bit floating-point ARGB */
+
+   SVGA3D_A2R10G10B10    = 26,
+
+   /* signed formats */
+   SVGA3D_V8U8           = 27,
+   SVGA3D_Q8W8V8U8       = 28,
+   SVGA3D_CxV8U8         = 29,
+
+   /* mixed formats */
+   SVGA3D_X8L8V8U8       = 30,
+   SVGA3D_A2W10V10U10    = 31,
+
+   SVGA3D_ALPHA8         = 32,
+
+   /* Single- and dual-component floating point formats */
+   SVGA3D_R_S10E5        = 33,
+   SVGA3D_R_S23E8        = 34,
+   SVGA3D_RG_S10E5       = 35,
+   SVGA3D_RG_S23E8       = 36,
+
+   /*
+    * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
+    * the most efficient format to use when creating new surfaces
+    * expressly for index or vertex data.
+    */
+   SVGA3D_BUFFER         = 37,
+
+   SVGA3D_Z_D24X8        = 38,
+
+   SVGA3D_V16U16         = 39,
+
+   SVGA3D_G16R16         = 40,
+   SVGA3D_A16B16G16R16   = 41,
+
+   /* Packed Video formats */
+   SVGA3D_UYVY           = 42,
+   SVGA3D_YUY2           = 43,
+
+   SVGA3D_FORMAT_MAX
+} SVGA3dSurfaceFormat;
+
+typedef uint32 SVGA3dColor; /* a, r, g, b */
+
+/*
+ * These match the D3DFORMAT_OP definitions used by Direct3D. We need
+ * them so that we can query the host for what the supported surface
+ * operations are (when we're using the D3D backend, in particular),
+ * and so we can send those operations to the guest.
+ */
+typedef enum {
+   SVGA3DFORMAT_OP_TEXTURE                               = 0x00000001,
+   SVGA3DFORMAT_OP_VOLUMETEXTURE                         = 0x00000002,
+   SVGA3DFORMAT_OP_CUBETEXTURE                           = 0x00000004,
+   SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET                = 0x00000008,
+   SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET              = 0x00000010,
+   SVGA3DFORMAT_OP_ZSTENCIL                              = 0x00000040,
+   SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH   = 0x00000080,
+
+/*
+ * This format can be used as a render target if the current display mode
+ * is the same depth if the alpha channel is ignored. e.g. if the device
+ * can render to A8R8G8B8 when the display mode is X8R8G8B8, then the
+ * format op list entry for A8R8G8B8 should have this cap.
+ */
+   SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET  = 0x00000100,
+
+/*
+ * This format contains DirectDraw support (including Flip).  This flag
+ * should not to be set on alpha formats.
+ */
+   SVGA3DFORMAT_OP_DISPLAYMODE                           = 0x00000400,
+
+/*
+ * The rasterizer can support some level of Direct3D support in this format
+ * and implies that the driver can create a Context in this mode (for some
+ * render target format).  When this flag is set, the SVGA3DFORMAT_OP_DISPLAYMODE
+ * flag must also be set.
+ */
+   SVGA3DFORMAT_OP_3DACCELERATION                        = 0x00000800,
+
+/*
+ * This is set for a private format when the driver has put the bpp in
+ * the structure.
+ */
+   SVGA3DFORMAT_OP_PIXELSIZE                             = 0x00001000,
+
+/*
+ * Indicates that this format can be converted to any RGB format for which
+ * SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB is specified
+ */
+   SVGA3DFORMAT_OP_CONVERT_TO_ARGB                       = 0x00002000,
+
+/*
+ * Indicates that this format can be used to create offscreen plain surfaces.
+ */
+   SVGA3DFORMAT_OP_OFFSCREENPLAIN                        = 0x00004000,
+
+/*
+ * Indicated that this format can be read as an SRGB texture (meaning that the
+ * sampler will linearize the looked up data)
+ */
+   SVGA3DFORMAT_OP_SRGBREAD                              = 0x00008000,
+
+/*
+ * Indicates that this format can be used in the bumpmap instructions
+ */
+   SVGA3DFORMAT_OP_BUMPMAP                               = 0x00010000,
+
+/*
+ * Indicates that this format can be sampled by the displacement map sampler
+ */
+   SVGA3DFORMAT_OP_DMAP                                  = 0x00020000,
+
+/*
+ * Indicates that this format cannot be used with texture filtering
+ */
+   SVGA3DFORMAT_OP_NOFILTER                              = 0x00040000,
+
+/*
+ * Indicates that format conversions are supported to this RGB format if
+ * SVGA3DFORMAT_OP_CONVERT_TO_ARGB is specified in the source format.
+ */
+   SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB                    = 0x00080000,
+
+/*
+ * Indicated that this format can be written as an SRGB target (meaning that the
+ * pixel pipe will DE-linearize data on output to format)
+ */
+   SVGA3DFORMAT_OP_SRGBWRITE                             = 0x00100000,
+
+/*
+ * Indicates that this format cannot be used with alpha blending
+ */
+   SVGA3DFORMAT_OP_NOALPHABLEND                          = 0x00200000,
+
+/*
+ * Indicates that the device can auto-generated sublevels for resources
+ * of this format
+ */
+   SVGA3DFORMAT_OP_AUTOGENMIPMAP                         = 0x00400000,
+
+/*
+ * Indicates that this format can be used by vertex texture sampler
+ */
+   SVGA3DFORMAT_OP_VERTEXTEXTURE                         = 0x00800000,
+
+/*
+ * Indicates that this format supports neither texture coordinate wrap
+ * modes, nor mipmapping
+ */
+   SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP                  = 0x01000000
+} SVGA3dFormatOp;
+
+/*
+ * This structure is a conversion of SVGA3DFORMAT_OP_*.
+ * Entries must be located at the same position.
+ */
+typedef union {
+   uint32 value;
+   struct {
+      uint32 texture : 1;
+      uint32 volumeTexture : 1;
+      uint32 cubeTexture : 1;
+      uint32 offscreenRenderTarget : 1;
+      uint32 sameFormatRenderTarget : 1;
+      uint32 unknown1 : 1;
+      uint32 zStencil : 1;
+      uint32 zStencilArbitraryDepth : 1;
+      uint32 sameFormatUpToAlpha : 1;
+      uint32 unknown2 : 1;
+      uint32 displayMode : 1;
+      uint32 acceleration3d : 1;
+      uint32 pixelSize : 1;
+      uint32 convertToARGB : 1;
+      uint32 offscreenPlain : 1;
+      uint32 sRGBRead : 1;
+      uint32 bumpMap : 1;
+      uint32 dmap : 1;
+      uint32 noFilter : 1;
+      uint32 memberOfGroupARGB : 1;
+      uint32 sRGBWrite : 1;
+      uint32 noAlphaBlend : 1;
+      uint32 autoGenMipMap : 1;
+      uint32 vertexTexture : 1;
+      uint32 noTexCoordWrapNorMip : 1;
+   };
+} SVGA3dSurfaceFormatCaps;
+
+/*
+ * SVGA_3D_CMD_SETRENDERSTATE Types.  All value types
+ * must fit in a uint32.
+ */
+
+typedef enum {
+   SVGA3D_RS_INVALID                   = 0,
+   SVGA3D_RS_ZENABLE                   = 1,     /* SVGA3dBool */
+   SVGA3D_RS_ZWRITEENABLE              = 2,     /* SVGA3dBool */
+   SVGA3D_RS_ALPHATESTENABLE           = 3,     /* SVGA3dBool */
+   SVGA3D_RS_DITHERENABLE              = 4,     /* SVGA3dBool */
+   SVGA3D_RS_BLENDENABLE               = 5,     /* SVGA3dBool */
+   SVGA3D_RS_FOGENABLE                 = 6,     /* SVGA3dBool */
+   SVGA3D_RS_SPECULARENABLE            = 7,     /* SVGA3dBool */
+   SVGA3D_RS_STENCILENABLE             = 8,     /* SVGA3dBool */
+   SVGA3D_RS_LIGHTINGENABLE            = 9,     /* SVGA3dBool */
+   SVGA3D_RS_NORMALIZENORMALS          = 10,    /* SVGA3dBool */
+   SVGA3D_RS_POINTSPRITEENABLE         = 11,    /* SVGA3dBool */
+   SVGA3D_RS_POINTSCALEENABLE          = 12,    /* SVGA3dBool */
+   SVGA3D_RS_STENCILREF                = 13,    /* uint32 */
+   SVGA3D_RS_STENCILMASK               = 14,    /* uint32 */
+   SVGA3D_RS_STENCILWRITEMASK          = 15,    /* uint32 */
+   SVGA3D_RS_FOGSTART                  = 16,    /* float */
+   SVGA3D_RS_FOGEND                    = 17,    /* float */
+   SVGA3D_RS_FOGDENSITY                = 18,    /* float */
+   SVGA3D_RS_POINTSIZE                 = 19,    /* float */
+   SVGA3D_RS_POINTSIZEMIN              = 20,    /* float */
+   SVGA3D_RS_POINTSIZEMAX              = 21,    /* float */
+   SVGA3D_RS_POINTSCALE_A              = 22,    /* float */
+   SVGA3D_RS_POINTSCALE_B              = 23,    /* float */
+   SVGA3D_RS_POINTSCALE_C              = 24,    /* float */
+   SVGA3D_RS_FOGCOLOR                  = 25,    /* SVGA3dColor */
+   SVGA3D_RS_AMBIENT                   = 26,    /* SVGA3dColor */
+   SVGA3D_RS_CLIPPLANEENABLE           = 27,    /* SVGA3dClipPlanes */
+   SVGA3D_RS_FOGMODE                   = 28,    /* SVGA3dFogMode */
+   SVGA3D_RS_FILLMODE                  = 29,    /* SVGA3dFillMode */
+   SVGA3D_RS_SHADEMODE                 = 30,    /* SVGA3dShadeMode */
+   SVGA3D_RS_LINEPATTERN               = 31,    /* SVGA3dLinePattern */
+   SVGA3D_RS_SRCBLEND                  = 32,    /* SVGA3dBlendOp */
+   SVGA3D_RS_DSTBLEND                  = 33,    /* SVGA3dBlendOp */
+   SVGA3D_RS_BLENDEQUATION             = 34,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_CULLMODE                  = 35,    /* SVGA3dFace */
+   SVGA3D_RS_ZFUNC                     = 36,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_ALPHAFUNC                 = 37,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_STENCILFUNC               = 38,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_STENCILFAIL               = 39,    /* SVGA3dStencilOp */
+   SVGA3D_RS_STENCILZFAIL              = 40,    /* SVGA3dStencilOp */
+   SVGA3D_RS_STENCILPASS               = 41,    /* SVGA3dStencilOp */
+   SVGA3D_RS_ALPHAREF                  = 42,    /* float (0.0 .. 1.0) */
+   SVGA3D_RS_FRONTWINDING              = 43,    /* SVGA3dFrontWinding */
+   SVGA3D_RS_COORDINATETYPE            = 44,    /* SVGA3dCoordinateType */
+   SVGA3D_RS_ZBIAS                     = 45,    /* float */
+   SVGA3D_RS_RANGEFOGENABLE            = 46,    /* SVGA3dBool */
+   SVGA3D_RS_COLORWRITEENABLE          = 47,    /* SVGA3dColorMask */
+   SVGA3D_RS_VERTEXMATERIALENABLE      = 48,    /* SVGA3dBool */
+   SVGA3D_RS_DIFFUSEMATERIALSOURCE     = 49,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_SPECULARMATERIALSOURCE    = 50,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_AMBIENTMATERIALSOURCE     = 51,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_EMISSIVEMATERIALSOURCE    = 52,    /* SVGA3dVertexMaterial */
+   SVGA3D_RS_TEXTUREFACTOR             = 53,    /* SVGA3dColor */
+   SVGA3D_RS_LOCALVIEWER               = 54,    /* SVGA3dBool */
+   SVGA3D_RS_SCISSORTESTENABLE         = 55,    /* SVGA3dBool */
+   SVGA3D_RS_BLENDCOLOR                = 56,    /* SVGA3dColor */
+   SVGA3D_RS_STENCILENABLE2SIDED       = 57,    /* SVGA3dBool */
+   SVGA3D_RS_CCWSTENCILFUNC            = 58,    /* SVGA3dCmpFunc */
+   SVGA3D_RS_CCWSTENCILFAIL            = 59,    /* SVGA3dStencilOp */
+   SVGA3D_RS_CCWSTENCILZFAIL           = 60,    /* SVGA3dStencilOp */
+   SVGA3D_RS_CCWSTENCILPASS            = 61,    /* SVGA3dStencilOp */
+   SVGA3D_RS_VERTEXBLEND               = 62,    /* SVGA3dVertexBlendFlags */
+   SVGA3D_RS_SLOPESCALEDEPTHBIAS       = 63,    /* float */
+   SVGA3D_RS_DEPTHBIAS                 = 64,    /* float */
+
+
+   /*
+    * Output Gamma Level
+    *
+    * Output gamma effects the gamma curve of colors that are output from the
+    * rendering pipeline.  A value of 1.0 specifies a linear color space. If the
+    * value is <= 0.0, gamma correction is ignored and linear color space is
+    * used.
+    */
+
+   SVGA3D_RS_OUTPUTGAMMA               = 65,    /* float */
+   SVGA3D_RS_ZVISIBLE                  = 66,    /* SVGA3dBool */
+   SVGA3D_RS_LASTPIXEL                 = 67,    /* SVGA3dBool */
+   SVGA3D_RS_CLIPPING                  = 68,    /* SVGA3dBool */
+   SVGA3D_RS_WRAP0                     = 69,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP1                     = 70,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP2                     = 71,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP3                     = 72,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP4                     = 73,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP5                     = 74,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP6                     = 75,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP7                     = 76,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP8                     = 77,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP9                     = 78,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP10                    = 79,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP11                    = 80,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP12                    = 81,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP13                    = 82,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP14                    = 83,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_WRAP15                    = 84,    /* SVGA3dWrapFlags */
+   SVGA3D_RS_MULTISAMPLEANTIALIAS      = 85,    /* SVGA3dBool */
+   SVGA3D_RS_MULTISAMPLEMASK           = 86,    /* uint32 */
+   SVGA3D_RS_INDEXEDVERTEXBLENDENABLE  = 87,    /* SVGA3dBool */
+   SVGA3D_RS_TWEENFACTOR               = 88,    /* float */
+   SVGA3D_RS_ANTIALIASEDLINEENABLE     = 89,    /* SVGA3dBool */
+   SVGA3D_RS_COLORWRITEENABLE1         = 90,    /* SVGA3dColorMask */
+   SVGA3D_RS_COLORWRITEENABLE2         = 91,    /* SVGA3dColorMask */
+   SVGA3D_RS_COLORWRITEENABLE3         = 92,    /* SVGA3dColorMask */
+   SVGA3D_RS_SEPARATEALPHABLENDENABLE  = 93,    /* SVGA3dBool */
+   SVGA3D_RS_SRCBLENDALPHA             = 94,    /* SVGA3dBlendOp */
+   SVGA3D_RS_DSTBLENDALPHA             = 95,    /* SVGA3dBlendOp */
+   SVGA3D_RS_BLENDEQUATIONALPHA        = 96,    /* SVGA3dBlendEquation */
+   SVGA3D_RS_MAX
+} SVGA3dRenderStateName;
+
+typedef enum {
+   SVGA3D_VERTEXMATERIAL_NONE     = 0,    /* Use the value in the current material */
+   SVGA3D_VERTEXMATERIAL_DIFFUSE  = 1,    /* Use the value in the diffuse component */
+   SVGA3D_VERTEXMATERIAL_SPECULAR = 2,    /* Use the value in the specular component */
+} SVGA3dVertexMaterial;
+
+typedef enum {
+   SVGA3D_FILLMODE_INVALID = 0,
+   SVGA3D_FILLMODE_POINT   = 1,
+   SVGA3D_FILLMODE_LINE    = 2,
+   SVGA3D_FILLMODE_FILL    = 3,
+   SVGA3D_FILLMODE_MAX
+} SVGA3dFillModeType;
+
+
+typedef
+union {
+   struct {
+      uint16   mode;       /* SVGA3dFillModeType */
+      uint16   face;       /* SVGA3dFace */
+   };
+   uint32 uintValue;
+} SVGA3dFillMode;
+
+typedef enum {
+   SVGA3D_SHADEMODE_INVALID = 0,
+   SVGA3D_SHADEMODE_FLAT    = 1,
+   SVGA3D_SHADEMODE_SMOOTH  = 2,
+   SVGA3D_SHADEMODE_PHONG   = 3,     /* Not supported */
+   SVGA3D_SHADEMODE_MAX
+} SVGA3dShadeMode;
+
+typedef
+union {
+   struct {
+      uint16 repeat;
+      uint16 pattern;
+   };
+   uint32 uintValue;
+} SVGA3dLinePattern;
+
+typedef enum {
+   SVGA3D_BLENDOP_INVALID            = 0,
+   SVGA3D_BLENDOP_ZERO               = 1,
+   SVGA3D_BLENDOP_ONE                = 2,
+   SVGA3D_BLENDOP_SRCCOLOR           = 3,
+   SVGA3D_BLENDOP_INVSRCCOLOR        = 4,
+   SVGA3D_BLENDOP_SRCALPHA           = 5,
+   SVGA3D_BLENDOP_INVSRCALPHA        = 6,
+   SVGA3D_BLENDOP_DESTALPHA          = 7,
+   SVGA3D_BLENDOP_INVDESTALPHA       = 8,
+   SVGA3D_BLENDOP_DESTCOLOR          = 9,
+   SVGA3D_BLENDOP_INVDESTCOLOR       = 10,
+   SVGA3D_BLENDOP_SRCALPHASAT        = 11,
+   SVGA3D_BLENDOP_BLENDFACTOR        = 12,
+   SVGA3D_BLENDOP_INVBLENDFACTOR     = 13,
+   SVGA3D_BLENDOP_MAX
+} SVGA3dBlendOp;
+
+typedef enum {
+   SVGA3D_BLENDEQ_INVALID            = 0,
+   SVGA3D_BLENDEQ_ADD                = 1,
+   SVGA3D_BLENDEQ_SUBTRACT           = 2,
+   SVGA3D_BLENDEQ_REVSUBTRACT        = 3,
+   SVGA3D_BLENDEQ_MINIMUM            = 4,
+   SVGA3D_BLENDEQ_MAXIMUM            = 5,
+   SVGA3D_BLENDEQ_MAX
+} SVGA3dBlendEquation;
+
+typedef enum {
+   SVGA3D_FRONTWINDING_INVALID = 0,
+   SVGA3D_FRONTWINDING_CW      = 1,
+   SVGA3D_FRONTWINDING_CCW     = 2,
+   SVGA3D_FRONTWINDING_MAX
+} SVGA3dFrontWinding;
+
+typedef enum {
+   SVGA3D_FACE_INVALID  = 0,
+   SVGA3D_FACE_NONE     = 1,
+   SVGA3D_FACE_FRONT    = 2,
+   SVGA3D_FACE_BACK     = 3,
+   SVGA3D_FACE_FRONT_BACK = 4,
+   SVGA3D_FACE_MAX
+} SVGA3dFace;
+
+/*
+ * The order and the values should not be changed
+ */
+
+typedef enum {
+   SVGA3D_CMP_INVALID              = 0,
+   SVGA3D_CMP_NEVER                = 1,
+   SVGA3D_CMP_LESS                 = 2,
+   SVGA3D_CMP_EQUAL                = 3,
+   SVGA3D_CMP_LESSEQUAL            = 4,
+   SVGA3D_CMP_GREATER              = 5,
+   SVGA3D_CMP_NOTEQUAL             = 6,
+   SVGA3D_CMP_GREATEREQUAL         = 7,
+   SVGA3D_CMP_ALWAYS               = 8,
+   SVGA3D_CMP_MAX
+} SVGA3dCmpFunc;
+
+/*
+ * SVGA3D_FOGFUNC_* specifies the fog equation, or PER_VERTEX which allows
+ * the fog factor to be specified in the alpha component of the specular
+ * (a.k.a. secondary) vertex color.
+ */
+typedef enum {
+   SVGA3D_FOGFUNC_INVALID          = 0,
+   SVGA3D_FOGFUNC_EXP              = 1,
+   SVGA3D_FOGFUNC_EXP2             = 2,
+   SVGA3D_FOGFUNC_LINEAR           = 3,
+   SVGA3D_FOGFUNC_PER_VERTEX       = 4
+} SVGA3dFogFunction;
+
+/*
+ * SVGA3D_FOGTYPE_* specifies if fog factors are computed on a per-vertex
+ * or per-pixel basis.
+ */
+typedef enum {
+   SVGA3D_FOGTYPE_INVALID          = 0,
+   SVGA3D_FOGTYPE_VERTEX           = 1,
+   SVGA3D_FOGTYPE_PIXEL            = 2,
+   SVGA3D_FOGTYPE_MAX              = 3
+} SVGA3dFogType;
+
+/*
+ * SVGA3D_FOGBASE_* selects depth or range-based fog. Depth-based fog is
+ * computed using the eye Z value of each pixel (or vertex), whereas range-
+ * based fog is computed using the actual distance (range) to the eye.
+ */
+typedef enum {
+   SVGA3D_FOGBASE_INVALID          = 0,
+   SVGA3D_FOGBASE_DEPTHBASED       = 1,
+   SVGA3D_FOGBASE_RANGEBASED       = 2,
+   SVGA3D_FOGBASE_MAX              = 3
+} SVGA3dFogBase;
+
+typedef enum {
+   SVGA3D_STENCILOP_INVALID        = 0,
+   SVGA3D_STENCILOP_KEEP           = 1,
+   SVGA3D_STENCILOP_ZERO           = 2,
+   SVGA3D_STENCILOP_REPLACE        = 3,
+   SVGA3D_STENCILOP_INCRSAT        = 4,
+   SVGA3D_STENCILOP_DECRSAT        = 5,
+   SVGA3D_STENCILOP_INVERT         = 6,
+   SVGA3D_STENCILOP_INCR           = 7,
+   SVGA3D_STENCILOP_DECR           = 8,
+   SVGA3D_STENCILOP_MAX
+} SVGA3dStencilOp;
+
+typedef enum {
+   SVGA3D_CLIPPLANE_0              = (1 << 0),
+   SVGA3D_CLIPPLANE_1              = (1 << 1),
+   SVGA3D_CLIPPLANE_2              = (1 << 2),
+   SVGA3D_CLIPPLANE_3              = (1 << 3),
+   SVGA3D_CLIPPLANE_4              = (1 << 4),
+   SVGA3D_CLIPPLANE_5              = (1 << 5),
+} SVGA3dClipPlanes;
+
+typedef enum {
+   SVGA3D_CLEAR_COLOR              = 0x1,
+   SVGA3D_CLEAR_DEPTH              = 0x2,
+   SVGA3D_CLEAR_STENCIL            = 0x4
+} SVGA3dClearFlag;
+
+typedef enum {
+   SVGA3D_RT_DEPTH                 = 0,
+   SVGA3D_RT_STENCIL               = 1,
+   SVGA3D_RT_COLOR0                = 2,
+   SVGA3D_RT_COLOR1                = 3,
+   SVGA3D_RT_COLOR2                = 4,
+   SVGA3D_RT_COLOR3                = 5,
+   SVGA3D_RT_COLOR4                = 6,
+   SVGA3D_RT_COLOR5                = 7,
+   SVGA3D_RT_COLOR6                = 8,
+   SVGA3D_RT_COLOR7                = 9,
+   SVGA3D_RT_MAX,
+   SVGA3D_RT_INVALID               = ((uint32)-1),
+} SVGA3dRenderTargetType;
+
+#define SVGA3D_MAX_RT_COLOR (SVGA3D_RT_COLOR7 - SVGA3D_RT_COLOR0 + 1)
+
+typedef
+union {
+   struct {
+      uint32  red   : 1;
+      uint32  green : 1;
+      uint32  blue  : 1;
+      uint32  alpha : 1;
+   };
+   uint32 uintValue;
+} SVGA3dColorMask;
+
+typedef enum {
+   SVGA3D_VBLEND_DISABLE            = 0,
+   SVGA3D_VBLEND_1WEIGHT            = 1,
+   SVGA3D_VBLEND_2WEIGHT            = 2,
+   SVGA3D_VBLEND_3WEIGHT            = 3,
+} SVGA3dVertexBlendFlags;
+
+typedef enum {
+   SVGA3D_WRAPCOORD_0   = 1 << 0,
+   SVGA3D_WRAPCOORD_1   = 1 << 1,
+   SVGA3D_WRAPCOORD_2   = 1 << 2,
+   SVGA3D_WRAPCOORD_3   = 1 << 3,
+   SVGA3D_WRAPCOORD_ALL = 0xF,
+} SVGA3dWrapFlags;
+
+/*
+ * SVGA_3D_CMD_TEXTURESTATE Types.  All value types
+ * must fit in a uint32.
+ */
+
+typedef enum {
+   SVGA3D_TS_INVALID                    = 0,
+   SVGA3D_TS_BIND_TEXTURE               = 1,    /* SVGA3dSurfaceId */
+   SVGA3D_TS_COLOROP                    = 2,    /* SVGA3dTextureCombiner */
+   SVGA3D_TS_COLORARG1                  = 3,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_COLORARG2                  = 4,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAOP                    = 5,    /* SVGA3dTextureCombiner */
+   SVGA3D_TS_ALPHAARG1                  = 6,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAARG2                  = 7,    /* SVGA3dTextureArgData */
+   SVGA3D_TS_ADDRESSU                   = 8,    /* SVGA3dTextureAddress */
+   SVGA3D_TS_ADDRESSV                   = 9,    /* SVGA3dTextureAddress */
+   SVGA3D_TS_MIPFILTER                  = 10,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_MAGFILTER                  = 11,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_MINFILTER                  = 12,   /* SVGA3dTextureFilter */
+   SVGA3D_TS_BORDERCOLOR                = 13,   /* SVGA3dColor */
+   SVGA3D_TS_TEXCOORDINDEX              = 14,   /* uint32 */
+   SVGA3D_TS_TEXTURETRANSFORMFLAGS      = 15,   /* SVGA3dTexTransformFlags */
+   SVGA3D_TS_TEXCOORDGEN                = 16,   /* SVGA3dTextureCoordGen */
+   SVGA3D_TS_BUMPENVMAT00               = 17,   /* float */
+   SVGA3D_TS_BUMPENVMAT01               = 18,   /* float */
+   SVGA3D_TS_BUMPENVMAT10               = 19,   /* float */
+   SVGA3D_TS_BUMPENVMAT11               = 20,   /* float */
+   SVGA3D_TS_TEXTURE_MIPMAP_LEVEL       = 21,   /* uint32 */
+   SVGA3D_TS_TEXTURE_LOD_BIAS           = 22,   /* float */
+   SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL  = 23,   /* uint32 */
+   SVGA3D_TS_ADDRESSW                   = 24,   /* SVGA3dTextureAddress */
+
+
+   /*
+    * Sampler Gamma Level
+    *
+    * Sampler gamma effects the color of samples taken from the sampler.  A
+    * value of 1.0 will produce linear samples.  If the value is <= 0.0 the
+    * gamma value is ignored and a linear space is used.
+    */
+
+   SVGA3D_TS_GAMMA                      = 25,   /* float */
+   SVGA3D_TS_BUMPENVLSCALE              = 26,   /* float */
+   SVGA3D_TS_BUMPENVLOFFSET             = 27,   /* float */
+   SVGA3D_TS_COLORARG0                  = 28,   /* SVGA3dTextureArgData */
+   SVGA3D_TS_ALPHAARG0                  = 29,   /* SVGA3dTextureArgData */
+   SVGA3D_TS_MAX
+} SVGA3dTextureStateName;
+
+typedef enum {
+   SVGA3D_TC_INVALID                   = 0,
+   SVGA3D_TC_DISABLE                   = 1,
+   SVGA3D_TC_SELECTARG1                = 2,
+   SVGA3D_TC_SELECTARG2                = 3,
+   SVGA3D_TC_MODULATE                  = 4,
+   SVGA3D_TC_ADD                       = 5,
+   SVGA3D_TC_ADDSIGNED                 = 6,
+   SVGA3D_TC_SUBTRACT                  = 7,
+   SVGA3D_TC_BLENDTEXTUREALPHA         = 8,
+   SVGA3D_TC_BLENDDIFFUSEALPHA         = 9,
+   SVGA3D_TC_BLENDCURRENTALPHA         = 10,
+   SVGA3D_TC_BLENDFACTORALPHA          = 11,
+   SVGA3D_TC_MODULATE2X                = 12,
+   SVGA3D_TC_MODULATE4X                = 13,
+   SVGA3D_TC_DSDT                      = 14,
+   SVGA3D_TC_DOTPRODUCT3               = 15,
+   SVGA3D_TC_BLENDTEXTUREALPHAPM       = 16,
+   SVGA3D_TC_ADDSIGNED2X               = 17,
+   SVGA3D_TC_ADDSMOOTH                 = 18,
+   SVGA3D_TC_PREMODULATE               = 19,
+   SVGA3D_TC_MODULATEALPHA_ADDCOLOR    = 20,
+   SVGA3D_TC_MODULATECOLOR_ADDALPHA    = 21,
+   SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR = 22,
+   SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA = 23,
+   SVGA3D_TC_BUMPENVMAPLUMINANCE       = 24,
+   SVGA3D_TC_MULTIPLYADD               = 25,
+   SVGA3D_TC_LERP                      = 26,
+   SVGA3D_TC_MAX
+} SVGA3dTextureCombiner;
+
+#define SVGA3D_TC_CAP_BIT(svga3d_tc_op) (svga3d_tc_op ? (1 << (svga3d_tc_op - 1)) : 0)
+
+typedef enum {
+   SVGA3D_TEX_ADDRESS_INVALID    = 0,
+   SVGA3D_TEX_ADDRESS_WRAP       = 1,
+   SVGA3D_TEX_ADDRESS_MIRROR     = 2,
+   SVGA3D_TEX_ADDRESS_CLAMP      = 3,
+   SVGA3D_TEX_ADDRESS_BORDER     = 4,
+   SVGA3D_TEX_ADDRESS_MIRRORONCE = 5,
+   SVGA3D_TEX_ADDRESS_EDGE       = 6,
+   SVGA3D_TEX_ADDRESS_MAX
+} SVGA3dTextureAddress;
+
+/*
+ * SVGA3D_TEX_FILTER_NONE as the minification filter means mipmapping is
+ * disabled, and the rasterizer should use the magnification filter instead.
+ */
+typedef enum {
+   SVGA3D_TEX_FILTER_NONE           = 0,
+   SVGA3D_TEX_FILTER_NEAREST        = 1,
+   SVGA3D_TEX_FILTER_LINEAR         = 2,
+   SVGA3D_TEX_FILTER_ANISOTROPIC    = 3,
+   SVGA3D_TEX_FILTER_FLATCUBIC      = 4, // Deprecated, not implemented
+   SVGA3D_TEX_FILTER_GAUSSIANCUBIC  = 5, // Deprecated, not implemented
+   SVGA3D_TEX_FILTER_PYRAMIDALQUAD  = 6, // Not currently implemented
+   SVGA3D_TEX_FILTER_GAUSSIANQUAD   = 7, // Not currently implemented
+   SVGA3D_TEX_FILTER_MAX
+} SVGA3dTextureFilter;
+
+typedef enum {
+   SVGA3D_TEX_TRANSFORM_OFF    = 0,
+   SVGA3D_TEX_TRANSFORM_S      = (1 << 0),
+   SVGA3D_TEX_TRANSFORM_T      = (1 << 1),
+   SVGA3D_TEX_TRANSFORM_R      = (1 << 2),
+   SVGA3D_TEX_TRANSFORM_Q      = (1 << 3),
+   SVGA3D_TEX_PROJECTED        = (1 << 15),
+} SVGA3dTexTransformFlags;
+
+typedef enum {
+   SVGA3D_TEXCOORD_GEN_OFF              = 0,
+   SVGA3D_TEXCOORD_GEN_EYE_POSITION     = 1,
+   SVGA3D_TEXCOORD_GEN_EYE_NORMAL       = 2,
+   SVGA3D_TEXCOORD_GEN_REFLECTIONVECTOR = 3,
+   SVGA3D_TEXCOORD_GEN_SPHERE           = 4,
+   SVGA3D_TEXCOORD_GEN_MAX
+} SVGA3dTextureCoordGen;
+
+/*
+ * Texture argument constants for texture combiner
+ */
+typedef enum {
+   SVGA3D_TA_INVALID    = 0,
+   SVGA3D_TA_CONSTANT   = 1,
+   SVGA3D_TA_PREVIOUS   = 2,
+   SVGA3D_TA_DIFFUSE    = 3,
+   SVGA3D_TA_TEXTURE    = 4,
+   SVGA3D_TA_SPECULAR   = 5,
+   SVGA3D_TA_MAX
+} SVGA3dTextureArgData;
+
+#define SVGA3D_TM_MASK_LEN 4
+
+/* Modifiers for texture argument constants defined above. */
+typedef enum {
+   SVGA3D_TM_NONE       = 0,
+   SVGA3D_TM_ALPHA      = (1 << SVGA3D_TM_MASK_LEN),
+   SVGA3D_TM_ONE_MINUS  = (2 << SVGA3D_TM_MASK_LEN),
+} SVGA3dTextureArgModifier;
+
+#define SVGA3D_INVALID_ID         ((uint32)-1)
+#define SVGA3D_MAX_CLIP_PLANES    6
+
+/*
+ * This is the limit to the number of fixed-function texture
+ * transforms and texture coordinates we can support. It does *not*
+ * correspond to the number of texture image units (samplers) we
+ * support!
+ */
+#define SVGA3D_MAX_TEXTURE_COORDS 8
+
+/*
+ * Vertex declarations
+ *
+ * Notes:
+ *
+ * SVGA3D_DECLUSAGE_POSITIONT is for pre-transformed vertices. If you
+ * draw with any POSITIONT vertex arrays, the programmable vertex
+ * pipeline will be implicitly disabled. Drawing will take place as if
+ * no vertex shader was bound.
+ */
+
+typedef enum {
+   SVGA3D_DECLUSAGE_POSITION     = 0,
+   SVGA3D_DECLUSAGE_BLENDWEIGHT,       //  1
+   SVGA3D_DECLUSAGE_BLENDINDICES,      //  2
+   SVGA3D_DECLUSAGE_NORMAL,            //  3
+   SVGA3D_DECLUSAGE_PSIZE,             //  4
+   SVGA3D_DECLUSAGE_TEXCOORD,          //  5
+   SVGA3D_DECLUSAGE_TANGENT,           //  6
+   SVGA3D_DECLUSAGE_BINORMAL,          //  7
+   SVGA3D_DECLUSAGE_TESSFACTOR,        //  8
+   SVGA3D_DECLUSAGE_POSITIONT,         //  9
+   SVGA3D_DECLUSAGE_COLOR,             // 10
+   SVGA3D_DECLUSAGE_FOG,               // 11
+   SVGA3D_DECLUSAGE_DEPTH,             // 12
+   SVGA3D_DECLUSAGE_SAMPLE,            // 13
+   SVGA3D_DECLUSAGE_MAX
+} SVGA3dDeclUsage;
+
+typedef enum {
+   SVGA3D_DECLMETHOD_DEFAULT     = 0,
+   SVGA3D_DECLMETHOD_PARTIALU,
+   SVGA3D_DECLMETHOD_PARTIALV,
+   SVGA3D_DECLMETHOD_CROSSUV,          // Normal
+   SVGA3D_DECLMETHOD_UV,
+   SVGA3D_DECLMETHOD_LOOKUP,           // Lookup a displacement map
+   SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map
+} SVGA3dDeclMethod;
+
+typedef enum {
+   SVGA3D_DECLTYPE_FLOAT1        =  0,
+   SVGA3D_DECLTYPE_FLOAT2        =  1,
+   SVGA3D_DECLTYPE_FLOAT3        =  2,
+   SVGA3D_DECLTYPE_FLOAT4        =  3,
+   SVGA3D_DECLTYPE_D3DCOLOR      =  4,
+   SVGA3D_DECLTYPE_UBYTE4        =  5,
+   SVGA3D_DECLTYPE_SHORT2        =  6,
+   SVGA3D_DECLTYPE_SHORT4        =  7,
+   SVGA3D_DECLTYPE_UBYTE4N       =  8,
+   SVGA3D_DECLTYPE_SHORT2N       =  9,
+   SVGA3D_DECLTYPE_SHORT4N       = 10,
+   SVGA3D_DECLTYPE_USHORT2N      = 11,
+   SVGA3D_DECLTYPE_USHORT4N      = 12,
+   SVGA3D_DECLTYPE_UDEC3         = 13,
+   SVGA3D_DECLTYPE_DEC3N         = 14,
+   SVGA3D_DECLTYPE_FLOAT16_2     = 15,
+   SVGA3D_DECLTYPE_FLOAT16_4     = 16,
+   SVGA3D_DECLTYPE_MAX,
+} SVGA3dDeclType;
+
+/*
+ * This structure is used for the divisor for geometry instancing;
+ * it's a direct translation of the Direct3D equivalent.
+ */
+typedef union {
+   struct {
+      /*
+       * For index data, this number represents the number of instances to draw.
+       * For instance data, this number represents the number of
+       * instances/vertex in this stream
+       */
+      uint32 count : 30;
+
+      /*
+       * This is 1 if this is supposed to be the data that is repeated for
+       * every instance.
+       */
+      uint32 indexedData : 1;
+
+      /*
+       * This is 1 if this is supposed to be the per-instance data.
+       */
+      uint32 instanceData : 1;
+   };
+
+   uint32 value;
+} SVGA3dVertexDivisor;
+
+typedef enum {
+   SVGA3D_PRIMITIVE_INVALID                     = 0,
+   SVGA3D_PRIMITIVE_TRIANGLELIST                = 1,
+   SVGA3D_PRIMITIVE_POINTLIST                   = 2,
+   SVGA3D_PRIMITIVE_LINELIST                    = 3,
+   SVGA3D_PRIMITIVE_LINESTRIP                   = 4,
+   SVGA3D_PRIMITIVE_TRIANGLESTRIP               = 5,
+   SVGA3D_PRIMITIVE_TRIANGLEFAN                 = 6,
+   SVGA3D_PRIMITIVE_MAX
+} SVGA3dPrimitiveType;
+
+typedef enum {
+   SVGA3D_COORDINATE_INVALID                   = 0,
+   SVGA3D_COORDINATE_LEFTHANDED                = 1,
+   SVGA3D_COORDINATE_RIGHTHANDED               = 2,
+   SVGA3D_COORDINATE_MAX
+} SVGA3dCoordinateType;
+
+typedef enum {
+   SVGA3D_TRANSFORM_INVALID                     = 0,
+   SVGA3D_TRANSFORM_WORLD                       = 1,
+   SVGA3D_TRANSFORM_VIEW                        = 2,
+   SVGA3D_TRANSFORM_PROJECTION                  = 3,
+   SVGA3D_TRANSFORM_TEXTURE0                    = 4,
+   SVGA3D_TRANSFORM_TEXTURE1                    = 5,
+   SVGA3D_TRANSFORM_TEXTURE2                    = 6,
+   SVGA3D_TRANSFORM_TEXTURE3                    = 7,
+   SVGA3D_TRANSFORM_TEXTURE4                    = 8,
+   SVGA3D_TRANSFORM_TEXTURE5                    = 9,
+   SVGA3D_TRANSFORM_TEXTURE6                    = 10,
+   SVGA3D_TRANSFORM_TEXTURE7                    = 11,
+   SVGA3D_TRANSFORM_WORLD1                      = 12,
+   SVGA3D_TRANSFORM_WORLD2                      = 13,
+   SVGA3D_TRANSFORM_WORLD3                      = 14,
+   SVGA3D_TRANSFORM_MAX
+} SVGA3dTransformType;
+
+typedef enum {
+   SVGA3D_LIGHTTYPE_INVALID                     = 0,
+   SVGA3D_LIGHTTYPE_POINT                       = 1,
+   SVGA3D_LIGHTTYPE_SPOT1                       = 2, /* 1-cone, in degrees */
+   SVGA3D_LIGHTTYPE_SPOT2                       = 3, /* 2-cone, in radians */
+   SVGA3D_LIGHTTYPE_DIRECTIONAL                 = 4,
+   SVGA3D_LIGHTTYPE_MAX
+} SVGA3dLightType;
+
+typedef enum {
+   SVGA3D_CUBEFACE_POSX                         = 0,
+   SVGA3D_CUBEFACE_NEGX                         = 1,
+   SVGA3D_CUBEFACE_POSY                         = 2,
+   SVGA3D_CUBEFACE_NEGY                         = 3,
+   SVGA3D_CUBEFACE_POSZ                         = 4,
+   SVGA3D_CUBEFACE_NEGZ                         = 5,
+} SVGA3dCubeFace;
+
+typedef enum {
+   SVGA3D_SHADERTYPE_COMPILED_DX8               = 0,
+   SVGA3D_SHADERTYPE_VS                         = 1,
+   SVGA3D_SHADERTYPE_PS                         = 2,
+   SVGA3D_SHADERTYPE_MAX
+} SVGA3dShaderType;
+
+typedef enum {
+   SVGA3D_CONST_TYPE_FLOAT                      = 0,
+   SVGA3D_CONST_TYPE_INT                        = 1,
+   SVGA3D_CONST_TYPE_BOOL                       = 2,
+} SVGA3dShaderConstType;
+
+#define SVGA3D_MAX_SURFACE_FACES                6
+
+typedef enum {
+   SVGA3D_STRETCH_BLT_POINT                     = 0,
+   SVGA3D_STRETCH_BLT_LINEAR                    = 1,
+   SVGA3D_STRETCH_BLT_MAX
+} SVGA3dStretchBltMode;
+
+typedef enum {
+   SVGA3D_QUERYTYPE_OCCLUSION                   = 0,
+   SVGA3D_QUERYTYPE_MAX
+} SVGA3dQueryType;
+
+typedef enum {
+   SVGA3D_QUERYSTATE_PENDING     = 0,      /* Waiting on the host (set by guest) */
+   SVGA3D_QUERYSTATE_SUCCEEDED   = 1,      /* Completed successfully (set by host) */
+   SVGA3D_QUERYSTATE_FAILED      = 2,      /* Completed unsuccessfully (set by host) */
+   SVGA3D_QUERYSTATE_NEW         = 3,      /* Never submitted (For guest use only) */
+} SVGA3dQueryState;
+
+typedef enum {
+   SVGA3D_WRITE_HOST_VRAM        = 1,
+   SVGA3D_READ_HOST_VRAM         = 2,
+} SVGA3dTransferType;
+
+/*
+ * The maximum number vertex arrays we're guaranteed to support in
+ * SVGA_3D_CMD_DRAWPRIMITIVES.
+ */
+#define SVGA3D_MAX_VERTEX_ARRAYS   32
+
+/*
+ * Identifiers for commands in the command FIFO.
+ *
+ * IDs between 1000 and 1039 (inclusive) were used by obsolete versions of
+ * the SVGA3D protocol and remain reserved; they should not be used in the
+ * future.
+ *
+ * IDs between 1040 and 1999 (inclusive) are available for use by the
+ * current SVGA3D protocol.
+ *
+ * FIFO clients other than SVGA3D should stay below 1000, or at 2000
+ * and up.
+ */
+
+#define SVGA_3D_CMD_LEGACY_BASE            1000
+#define SVGA_3D_CMD_BASE                   1040
+
+#define SVGA_3D_CMD_SURFACE_DEFINE         SVGA_3D_CMD_BASE + 0
+#define SVGA_3D_CMD_SURFACE_DESTROY        SVGA_3D_CMD_BASE + 1
+#define SVGA_3D_CMD_SURFACE_COPY           SVGA_3D_CMD_BASE + 2
+#define SVGA_3D_CMD_SURFACE_STRETCHBLT     SVGA_3D_CMD_BASE + 3
+#define SVGA_3D_CMD_SURFACE_DMA            SVGA_3D_CMD_BASE + 4
+#define SVGA_3D_CMD_CONTEXT_DEFINE         SVGA_3D_CMD_BASE + 5
+#define SVGA_3D_CMD_CONTEXT_DESTROY        SVGA_3D_CMD_BASE + 6
+#define SVGA_3D_CMD_SETTRANSFORM           SVGA_3D_CMD_BASE + 7
+#define SVGA_3D_CMD_SETZRANGE              SVGA_3D_CMD_BASE + 8
+#define SVGA_3D_CMD_SETRENDERSTATE         SVGA_3D_CMD_BASE + 9
+#define SVGA_3D_CMD_SETRENDERTARGET        SVGA_3D_CMD_BASE + 10
+#define SVGA_3D_CMD_SETTEXTURESTATE        SVGA_3D_CMD_BASE + 11
+#define SVGA_3D_CMD_SETMATERIAL            SVGA_3D_CMD_BASE + 12
+#define SVGA_3D_CMD_SETLIGHTDATA           SVGA_3D_CMD_BASE + 13
+#define SVGA_3D_CMD_SETLIGHTENABLED        SVGA_3D_CMD_BASE + 14
+#define SVGA_3D_CMD_SETVIEWPORT            SVGA_3D_CMD_BASE + 15
+#define SVGA_3D_CMD_SETCLIPPLANE           SVGA_3D_CMD_BASE + 16
+#define SVGA_3D_CMD_CLEAR                  SVGA_3D_CMD_BASE + 17
+#define SVGA_3D_CMD_PRESENT                SVGA_3D_CMD_BASE + 18    // Deprecated
+#define SVGA_3D_CMD_SHADER_DEFINE          SVGA_3D_CMD_BASE + 19
+#define SVGA_3D_CMD_SHADER_DESTROY         SVGA_3D_CMD_BASE + 20
+#define SVGA_3D_CMD_SET_SHADER             SVGA_3D_CMD_BASE + 21
+#define SVGA_3D_CMD_SET_SHADER_CONST       SVGA_3D_CMD_BASE + 22
+#define SVGA_3D_CMD_DRAW_PRIMITIVES        SVGA_3D_CMD_BASE + 23
+#define SVGA_3D_CMD_SETSCISSORRECT         SVGA_3D_CMD_BASE + 24
+#define SVGA_3D_CMD_BEGIN_QUERY            SVGA_3D_CMD_BASE + 25
+#define SVGA_3D_CMD_END_QUERY              SVGA_3D_CMD_BASE + 26
+#define SVGA_3D_CMD_WAIT_FOR_QUERY         SVGA_3D_CMD_BASE + 27
+#define SVGA_3D_CMD_PRESENT_READBACK       SVGA_3D_CMD_BASE + 28    // Deprecated
+#define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29
+#define SVGA_3D_CMD_MAX                    SVGA_3D_CMD_BASE + 30
+
+#define SVGA_3D_CMD_FUTURE_MAX             2000
+
+/*
+ * Common substructures used in multiple FIFO commands:
+ */
+
+typedef struct {
+   union {
+      struct {
+         uint16  function;       // SVGA3dFogFunction
+         uint8   type;           // SVGA3dFogType
+         uint8   base;           // SVGA3dFogBase
+      };
+      uint32     uintValue;
+   };
+} SVGA3dFogMode;
+
+/*
+ * Uniquely identify one image (a 1D/2D/3D array) from a surface. This
+ * is a surface ID as well as face/mipmap indices.
+ */
+
+typedef
+struct SVGA3dSurfaceImageId {
+   uint32               sid;
+   uint32               face;
+   uint32               mipmap;
+} SVGA3dSurfaceImageId;
+
+typedef
+struct SVGA3dGuestImage {
+   SVGAGuestPtr         ptr;
+
+   /*
+    * A note on interpretation of pitch: This value of pitch is the
+    * number of bytes between vertically adjacent image
+    * blocks. Normally this is the number of bytes between the first
+    * pixel of two adjacent scanlines. With compressed textures,
+    * however, this may represent the number of bytes between
+    * compression blocks rather than between rows of pixels.
+    *
+    * XXX: Compressed textures currently must be tightly packed in guest memory.
+    *
+    * If the image is 1-dimensional, pitch is ignored.
+    *
+    * If 'pitch' is zero, the SVGA3D device calculates a pitch value
+    * assuming each row of blocks is tightly packed.
+    */
+   uint32 pitch;
+} SVGA3dGuestImage;
+
+
+/*
+ * FIFO command format definitions:
+ */
+
+/*
+ * The data size header following cmdNum for every 3d command
+ */
+typedef
+struct {
+   uint32               id;
+   uint32               size;
+} SVGA3dCmdHeader;
+
+/*
+ * A surface is a hierarchy of host VRAM surfaces: 1D, 2D, or 3D, with
+ * optional mipmaps and cube faces.
+ */
+
+typedef
+struct {
+   uint32               width;
+   uint32               height;
+   uint32               depth;
+} SVGA3dSize;
+
+typedef enum {
+   SVGA3D_SURFACE_CUBEMAP              = (1 << 0),
+   SVGA3D_SURFACE_HINT_STATIC          = (1 << 1),
+   SVGA3D_SURFACE_HINT_DYNAMIC         = (1 << 2),
+   SVGA3D_SURFACE_HINT_INDEXBUFFER     = (1 << 3),
+   SVGA3D_SURFACE_HINT_VERTEXBUFFER    = (1 << 4),
+   SVGA3D_SURFACE_HINT_TEXTURE         = (1 << 5),
+   SVGA3D_SURFACE_HINT_RENDERTARGET    = (1 << 6),
+   SVGA3D_SURFACE_HINT_DEPTHSTENCIL    = (1 << 7),
+   SVGA3D_SURFACE_HINT_WRITEONLY       = (1 << 8),
+} SVGA3dSurfaceFlags;
+
+typedef
+struct {
+   uint32               numMipLevels;
+} SVGA3dSurfaceFace;
+
+typedef
+struct {
+   uint32                      sid;
+   SVGA3dSurfaceFlags          surfaceFlags;
+   SVGA3dSurfaceFormat         format;
+   SVGA3dSurfaceFace           face[SVGA3D_MAX_SURFACE_FACES];
+   /*
+    * Followed by an SVGA3dSize structure for each mip level in each face.
+    *
+    * A note on surface sizes: Sizes are always specified in pixels,
+    * even if the true surface size is not a multiple of the minimum
+    * block size of the surface's format. For example, a 3x3x1 DXT1
+    * compressed texture would actually be stored as a 4x4x1 image in
+    * memory.
+    */
+} SVGA3dCmdDefineSurface;       /* SVGA_3D_CMD_SURFACE_DEFINE */
+
+typedef
+struct {
+   uint32               sid;
+} SVGA3dCmdDestroySurface;      /* SVGA_3D_CMD_SURFACE_DESTROY */
+
+typedef
+struct {
+   uint32               cid;
+} SVGA3dCmdDefineContext;       /* SVGA_3D_CMD_CONTEXT_DEFINE */
+
+typedef
+struct {
+   uint32               cid;
+} SVGA3dCmdDestroyContext;      /* SVGA_3D_CMD_CONTEXT_DESTROY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dClearFlag      clearFlag;
+   uint32               color;
+   float                depth;
+   uint32               stencil;
+   /* Followed by variable number of SVGA3dRect structures */
+} SVGA3dCmdClear;               /* SVGA_3D_CMD_CLEAR */
+
+typedef
+struct SVGA3dCopyRect {
+   uint32               x;
+   uint32               y;
+   uint32               w;
+   uint32               h;
+   uint32               srcx;
+   uint32               srcy;
+} SVGA3dCopyRect;
+
+typedef
+struct SVGA3dCopyBox {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+   uint32               w;
+   uint32               h;
+   uint32               d;
+   uint32               srcx;
+   uint32               srcy;
+   uint32               srcz;
+} SVGA3dCopyBox;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               w;
+   uint32               h;
+} SVGA3dRect;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+   uint32               w;
+   uint32               h;
+   uint32               d;
+} SVGA3dBox;
+
+typedef
+struct {
+   uint32               x;
+   uint32               y;
+   uint32               z;
+} SVGA3dPoint;
+
+typedef
+struct {
+   SVGA3dLightType      type;
+   SVGA3dBool           inWorldSpace;
+   float                diffuse[4];
+   float                specular[4];
+   float                ambient[4];
+   float                position[4];
+   float                direction[4];
+   float                range;
+   float                falloff;
+   float                attenuation0;
+   float                attenuation1;
+   float                attenuation2;
+   float                theta;
+   float                phi;
+} SVGA3dLightData;
+
+typedef
+struct {
+   uint32               sid;
+   /* Followed by variable number of SVGA3dCopyRect structures */
+} SVGA3dCmdPresent;             /* SVGA_3D_CMD_PRESENT */
+
+typedef
+struct {
+   SVGA3dRenderStateName   state;
+   union {
+      uint32               uintValue;
+      float                floatValue;
+   };
+} SVGA3dRenderState;
+
+typedef
+struct {
+   uint32               cid;
+   /* Followed by variable number of SVGA3dRenderState structures */
+} SVGA3dCmdSetRenderState;      /* SVGA_3D_CMD_SETRENDERSTATE */
+
+typedef
+struct {
+   uint32                 cid;
+   SVGA3dRenderTargetType type;
+   SVGA3dSurfaceImageId   target;
+} SVGA3dCmdSetRenderTarget;     /* SVGA_3D_CMD_SETRENDERTARGET */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId  src;
+   SVGA3dSurfaceImageId  dest;
+   /* Followed by variable number of SVGA3dCopyBox structures */
+} SVGA3dCmdSurfaceCopy;               /* SVGA_3D_CMD_SURFACE_COPY */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId  src;
+   SVGA3dSurfaceImageId  dest;
+   SVGA3dBox             boxSrc;
+   SVGA3dBox             boxDest;
+   SVGA3dStretchBltMode  mode;
+} SVGA3dCmdSurfaceStretchBlt;         /* SVGA_3D_CMD_SURFACE_STRETCHBLT */
+
+typedef
+struct {
+   /*
+    * If the discard flag is present in a surface DMA operation, the host may
+    * discard the contents of the current mipmap level and face of the target
+    * surface before applying the surface DMA contents.
+    */
+   uint32 discard : 1;
+
+   /*
+    * If the unsynchronized flag is present, the host may perform this upload
+    * without syncing to pending reads on this surface.
+    */
+   uint32 unsynchronized : 1;
+
+   /*
+    * Guests *MUST* set the reserved bits to 0 before submitting the command
+    * suffix as future flags may occupy these bits.
+    */
+   uint32 reserved : 30;
+} SVGA3dSurfaceDMAFlags;
+
+typedef
+struct {
+   SVGA3dGuestImage      guest;
+   SVGA3dSurfaceImageId  host;
+   SVGA3dTransferType    transfer;
+   /*
+    * Followed by variable number of SVGA3dCopyBox structures. For consistency
+    * in all clipping logic and coordinate translation, we define the
+    * "source" in each copyBox as the guest image and the
+    * "destination" as the host image, regardless of transfer
+    * direction.
+    *
+    * For efficiency, the SVGA3D device is free to copy more data than
+    * specified. For example, it may round copy boxes outwards such
+    * that they lie on particular alignment boundaries.
+    */
+} SVGA3dCmdSurfaceDMA;                /* SVGA_3D_CMD_SURFACE_DMA */
+
+/*
+ * SVGA3dCmdSurfaceDMASuffix --
+ *
+ *    This is a command suffix that will appear after a SurfaceDMA command in
+ *    the FIFO.  It contains some extra information that hosts may use to
+ *    optimize performance or protect the guest.  This suffix exists to preserve
+ *    backwards compatibility while also allowing for new functionality to be
+ *    implemented.
+ */
+
+typedef
+struct {
+   uint32 suffixSize;
+
+   /*
+    * The maximum offset is used to determine the maximum offset from the
+    * guestPtr base address that will be accessed or written to during this
+    * surfaceDMA.  If the suffix is supported, the host will respect this
+    * boundary while performing surface DMAs.
+    *
+    * Defaults to MAX_UINT32
+    */
+   uint32 maximumOffset;
+
+   /*
+    * A set of flags that describes optimizations that the host may perform
+    * while performing this surface DMA operation.  The guest should never rely
+    * on behaviour that is different when these flags are set for correctness.
+    *
+    * Defaults to 0
+    */
+   SVGA3dSurfaceDMAFlags flags;
+} SVGA3dCmdSurfaceDMASuffix;
+
+/*
+ * SVGA_3D_CMD_DRAW_PRIMITIVES --
+ *
+ *   This command is the SVGA3D device's generic drawing entry point.
+ *   It can draw multiple ranges of primitives, optionally using an
+ *   index buffer, using an arbitrary collection of vertex buffers.
+ *
+ *   Each SVGA3dVertexDecl defines a distinct vertex array to bind
+ *   during this draw call. The declarations specify which surface
+ *   the vertex data lives in, what that vertex data is used for,
+ *   and how to interpret it.
+ *
+ *   Each SVGA3dPrimitiveRange defines a collection of primitives
+ *   to render using the same vertex arrays. An index buffer is
+ *   optional.
+ */
+
+typedef
+struct {
+   /*
+    * A range hint is an optional specification for the range of indices
+    * in an SVGA3dArray that will be used. If 'last' is zero, it is assumed
+    * that the entire array will be used.
+    *
+    * These are only hints. The SVGA3D device may use them for
+    * performance optimization if possible, but it's also allowed to
+    * ignore these values.
+    */
+   uint32               first;
+   uint32               last;
+} SVGA3dArrayRangeHint;
+
+typedef
+struct {
+   /*
+    * Define the origin and shape of a vertex or index array. Both
+    * 'offset' and 'stride' are in bytes. The provided surface will be
+    * reinterpreted as a flat array of bytes in the same format used
+    * by surface DMA operations. To avoid unnecessary conversions, the
+    * surface should be created with the SVGA3D_BUFFER format.
+    *
+    * Index 0 in the array starts 'offset' bytes into the surface.
+    * Index 1 begins at byte 'offset + stride', etc. Array indices may
+    * not be negative.
+    */
+   uint32               surfaceId;
+   uint32               offset;
+   uint32               stride;
+} SVGA3dArray;
+
+typedef
+struct {
+   /*
+    * Describe a vertex array's data type, and define how it is to be
+    * used by the fixed function pipeline or the vertex shader. It
+    * isn't useful to have two VertexDecls with the same
+    * VertexArrayIdentity in one draw call.
+    */
+   SVGA3dDeclType       type;
+   SVGA3dDeclMethod     method;
+   SVGA3dDeclUsage      usage;
+   uint32               usageIndex;
+} SVGA3dVertexArrayIdentity;
+
+typedef
+struct {
+   SVGA3dVertexArrayIdentity  identity;
+   SVGA3dArray                array;
+   SVGA3dArrayRangeHint       rangeHint;
+} SVGA3dVertexDecl;
+
+typedef
+struct {
+   /*
+    * Define a group of primitives to render, from sequential indices.
+    *
+    * The value of 'primitiveType' and 'primitiveCount' imply the
+    * total number of vertices that will be rendered.
+    */
+   SVGA3dPrimitiveType  primType;
+   uint32               primitiveCount;
+
+   /*
+    * Optional index buffer. If indexArray.surfaceId is
+    * SVGA3D_INVALID_ID, we render without an index buffer. Rendering
+    * without an index buffer is identical to rendering with an index
+    * buffer containing the sequence [0, 1, 2, 3, ...].
+    *
+    * If an index buffer is in use, indexWidth specifies the width in
+    * bytes of each index value. It must be less than or equal to
+    * indexArray.stride.
+    *
+    * (Currently, the SVGA3D device requires index buffers to be tightly
+    * packed. In other words, indexWidth == indexArray.stride)
+    */
+   SVGA3dArray          indexArray;
+   uint32               indexWidth;
+
+   /*
+    * Optional index bias. This number is added to all indices from
+    * indexArray before they are used as vertex array indices. This
+    * can be used in multiple ways:
+    *
+    *  - When not using an indexArray, this bias can be used to
+    *    specify where in the vertex arrays to begin rendering.
+    *
+    *  - A positive number here is equivalent to increasing the
+    *    offset in each vertex array.
+    *
+    *  - A negative number can be used to render using a small
+    *    vertex array and an index buffer that contains large
+    *    values. This may be used by some applications that
+    *    crop a vertex buffer without modifying their index
+    *    buffer.
+    *
+    * Note that rendering with a negative bias value may be slower and
+    * use more memory than rendering with a positive or zero bias.
+    */
+   int32                indexBias;
+} SVGA3dPrimitiveRange;
+
+typedef
+struct {
+   uint32               cid;
+   uint32               numVertexDecls;
+   uint32               numRanges;
+
+   /*
+    * There are two variable size arrays after the
+    * SVGA3dCmdDrawPrimitives structure. In order,
+    * they are:
+    *
+    * 1. SVGA3dVertexDecl, quantity 'numVertexDecls'
+    * 2. SVGA3dPrimitiveRange, quantity 'numRanges'
+    * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains
+    *    the frequency divisor for this the corresponding vertex decl)
+    */
+} SVGA3dCmdDrawPrimitives;      /* SVGA_3D_CMD_DRAWPRIMITIVES */
+
+typedef
+struct {
+   uint32                   stage;
+   SVGA3dTextureStateName   name;
+   union {
+      uint32                value;
+      float                 floatValue;
+   };
+} SVGA3dTextureState;
+
+typedef
+struct {
+   uint32               cid;
+   /* Followed by variable number of SVGA3dTextureState structures */
+} SVGA3dCmdSetTextureState;      /* SVGA_3D_CMD_SETTEXTURESTATE */
+
+typedef
+struct {
+   uint32                   cid;
+   SVGA3dTransformType      type;
+   float                    matrix[16];
+} SVGA3dCmdSetTransform;          /* SVGA_3D_CMD_SETTRANSFORM */
+
+typedef
+struct {
+   float                min;
+   float                max;
+} SVGA3dZRange;
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dZRange         zRange;
+} SVGA3dCmdSetZRange;             /* SVGA_3D_CMD_SETZRANGE */
+
+typedef
+struct {
+   float                diffuse[4];
+   float                ambient[4];
+   float                specular[4];
+   float                emissive[4];
+   float                shininess;
+} SVGA3dMaterial;
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dFace           face;
+   SVGA3dMaterial       material;
+} SVGA3dCmdSetMaterial;           /* SVGA_3D_CMD_SETMATERIAL */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   SVGA3dLightData      data;
+} SVGA3dCmdSetLightData;           /* SVGA_3D_CMD_SETLIGHTDATA */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   uint32               enabled;
+} SVGA3dCmdSetLightEnabled;      /* SVGA_3D_CMD_SETLIGHTENABLED */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dRect           rect;
+} SVGA3dCmdSetViewport;           /* SVGA_3D_CMD_SETVIEWPORT */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dRect           rect;
+} SVGA3dCmdSetScissorRect;         /* SVGA_3D_CMD_SETSCISSORRECT */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               index;
+   float                plane[4];
+} SVGA3dCmdSetClipPlane;           /* SVGA_3D_CMD_SETCLIPPLANE */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               shid;
+   SVGA3dShaderType     type;
+   /* Followed by variable number of DWORDs for shader bycode */
+} SVGA3dCmdDefineShader;           /* SVGA_3D_CMD_SHADER_DEFINE */
+
+typedef
+struct {
+   uint32               cid;
+   uint32               shid;
+   SVGA3dShaderType     type;
+} SVGA3dCmdDestroyShader;         /* SVGA_3D_CMD_SHADER_DESTROY */
+
+typedef
+struct {
+   uint32                  cid;
+   uint32                  reg;     /* register number */
+   SVGA3dShaderType        type;
+   SVGA3dShaderConstType   ctype;
+   uint32                  values[4];
+} SVGA3dCmdSetShaderConst;        /* SVGA_3D_CMD_SET_SHADER_CONST */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dShaderType     type;
+   uint32               shid;
+} SVGA3dCmdSetShader;             /* SVGA_3D_CMD_SET_SHADER */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+} SVGA3dCmdBeginQuery;           /* SVGA_3D_CMD_BEGIN_QUERY */
+
+typedef
+struct {
+   uint32               cid;
+   SVGA3dQueryType      type;
+   SVGAGuestPtr         guestResult;  /* Points to an SVGA3dQueryResult structure */
+} SVGA3dCmdEndQuery;                  /* SVGA_3D_CMD_END_QUERY */
+
+typedef
+struct {
+   uint32               cid;          /* Same parameters passed to END_QUERY */
+   SVGA3dQueryType      type;
+   SVGAGuestPtr         guestResult;
+} SVGA3dCmdWaitForQuery;              /* SVGA_3D_CMD_WAIT_FOR_QUERY */
+
+typedef
+struct {
+   uint32               totalSize;    /* Set by guest before query is ended. */
+   SVGA3dQueryState     state;        /* Set by host or guest. See SVGA3dQueryState. */
+   union {                            /* Set by host on exit from PENDING state */
+      uint32            result32;
+   };
+} SVGA3dQueryResult;
+
+/*
+ * SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN --
+ *
+ *    This is a blit from an SVGA3D surface to a Screen Object. Just
+ *    like GMR-to-screen blits, this blit may be directed at a
+ *    specific screen or to the virtual coordinate space.
+ *
+ *    The blit copies from a rectangular region of an SVGA3D surface
+ *    image to a rectangular region of a screen or screens.
+ *
+ *    This command takes an optional variable-length list of clipping
+ *    rectangles after the body of the command. If no rectangles are
+ *    specified, there is no clipping region. The entire destRect is
+ *    drawn to. If one or more rectangles are included, they describe
+ *    a clipping region. The clip rectangle coordinates are measured
+ *    relative to the top-left corner of destRect.
+ *
+ *    This clipping region serves multiple purposes:
+ *
+ *      - It can be used to perform an irregularly shaped blit more
+ *        efficiently than by issuing many separate blit commands.
+ *
+ *      - It is equivalent to allowing blits with non-integer
+ *        source coordinates. You could blit just one half-pixel
+ *        of a source, for example, by specifying a larger
+ *        destination rectangle than you need, then removing
+ *        part of it using a clip rectangle.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ *
+ * Limitations:
+ *
+ *    - Currently, no backend supports blits from a mipmap or face
+ *      other than the first one.
+ */
+
+typedef
+struct {
+   SVGA3dSurfaceImageId srcImage;
+   SVGASignedRect       srcRect;
+   uint32               destScreenId; /* Screen ID or SVGA_ID_INVALID for virt. coords */
+   SVGASignedRect       destRect;     /* Supports scaling if src/rest different size */
+   /* Clipping: zero or more SVGASignedRects follow */
+} SVGA3dCmdBlitSurfaceToScreen;         /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
+
+
+/*
+ * Capability query index.
+ *
+ * Notes:
+ *
+ *   1. SVGA3D_DEVCAP_MAX_TEXTURES reflects the maximum number of
+ *      fixed-function texture units available. Each of these units
+ *      work in both FFP and Shader modes, and they support texture
+ *      transforms and texture coordinates. The host may have additional
+ *      texture image units that are only usable with shaders.
+ *
+ *   2. The BUFFER_FORMAT capabilities are deprecated, and they always
+ *      return TRUE. Even on physical hardware that does not support
+ *      these formats natively, the SVGA3D device will provide an emulation
+ *      which should be invisible to the guest OS.
+ *
+ *      In general, the SVGA3D device should support any operation on
+ *      any surface format, it just may perform some of these
+ *      operations in software depending on the capabilities of the
+ *      available physical hardware.
+ *
+ *      XXX: In the future, we will add capabilities that describe in
+ *      detail what formats are supported in hardware for what kinds
+ *      of operations.
+ */
+
+typedef enum {
+   SVGA3D_DEVCAP_3D                                = 0,
+   SVGA3D_DEVCAP_MAX_LIGHTS                        = 1,
+   SVGA3D_DEVCAP_MAX_TEXTURES                      = 2,  /* See note (1) */
+   SVGA3D_DEVCAP_MAX_CLIP_PLANES                   = 3,
+   SVGA3D_DEVCAP_VERTEX_SHADER_VERSION             = 4,
+   SVGA3D_DEVCAP_VERTEX_SHADER                     = 5,
+   SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION           = 6,
+   SVGA3D_DEVCAP_FRAGMENT_SHADER                   = 7,
+   SVGA3D_DEVCAP_MAX_RENDER_TARGETS                = 8,
+   SVGA3D_DEVCAP_S23E8_TEXTURES                    = 9,
+   SVGA3D_DEVCAP_S10E5_TEXTURES                    = 10,
+   SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND             = 11,
+   SVGA3D_DEVCAP_D16_BUFFER_FORMAT                 = 12, /* See note (2) */
+   SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT               = 13, /* See note (2) */
+   SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT               = 14, /* See note (2) */
+   SVGA3D_DEVCAP_QUERY_TYPES                       = 15,
+   SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING         = 16,
+   SVGA3D_DEVCAP_MAX_POINT_SIZE                    = 17,
+   SVGA3D_DEVCAP_MAX_SHADER_TEXTURES               = 18,
+   SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH                 = 19,
+   SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT                = 20,
+   SVGA3D_DEVCAP_MAX_VOLUME_EXTENT                 = 21,
+   SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT                = 22,
+   SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO          = 23,
+   SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY            = 24,
+   SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT               = 25,
+   SVGA3D_DEVCAP_MAX_VERTEX_INDEX                  = 26,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS    = 27,
+   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS  = 28,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS           = 29,
+   SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS         = 30,
+   SVGA3D_DEVCAP_TEXTURE_OPS                       = 31,
+   SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8               = 32,
+   SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8               = 33,
+   SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10            = 34,
+   SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5               = 35,
+   SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5               = 36,
+   SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4               = 37,
+   SVGA3D_DEVCAP_SURFACEFMT_R5G6B5                 = 38,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16            = 39,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8      = 40,
+   SVGA3D_DEVCAP_SURFACEFMT_ALPHA8                 = 41,
+   SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8             = 42,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D16                  = 43,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8                = 44,
+   SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8                = 45,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT1                   = 46,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT2                   = 47,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT3                   = 48,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT4                   = 49,
+   SVGA3D_DEVCAP_SURFACEFMT_DXT5                   = 50,
+   SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8           = 51,
+   SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10            = 52,
+   SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8               = 53,
+   SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8               = 54,
+   SVGA3D_DEVCAP_SURFACEFMT_CxV8U8                 = 55,
+   SVGA3D_DEVCAP_SURFACEFMT_R_S10E5                = 56,
+   SVGA3D_DEVCAP_SURFACEFMT_R_S23E8                = 57,
+   SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5               = 58,
+   SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8               = 59,
+   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5             = 60,
+   SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8             = 61,
+   SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES        = 63,
+
+   /*
+    * Note that MAX_SIMULTANEOUS_RENDER_TARGETS is a maximum count of color
+    * render targets.  This does no include the depth or stencil targets.
+    */
+   SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS   = 64,
+
+   SVGA3D_DEVCAP_SURFACEFMT_V16U16                 = 65,
+   SVGA3D_DEVCAP_SURFACEFMT_G16R16                 = 66,
+   SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16           = 67,
+   SVGA3D_DEVCAP_SURFACEFMT_UYVY                   = 68,
+   SVGA3D_DEVCAP_SURFACEFMT_YUY2                   = 69,
+
+   /*
+    * Don't add new caps into the previous section; the values in this
+    * enumeration must not change. You can put new values right before
+    * SVGA3D_DEVCAP_MAX.
+    */
+   SVGA3D_DEVCAP_MAX                                  /* This must be the last index. */
+} SVGA3dDevCapIndex;
+
+typedef union {
+   Bool   b;
+   uint32 u;
+   int32  i;
+   float  f;
+} SVGA3dDevCapResult;
+
+#endif /* _SVGA3D_REG_H_ */
diff --git a/drivers/gpu/drm/vmwgfx/svga_escape.h b/drivers/gpu/drm/vmwgfx/svga_escape.h
new file mode 100644
index 0000000..7b85e9b
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga_escape.h
@@ -0,0 +1,89 @@
+/**********************************************************
+ * Copyright 2007-2009 VMware, Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/*
+ * svga_escape.h --
+ *
+ *    Definitions for our own (vendor-specific) SVGA Escape commands.
+ */
+
+#ifndef _SVGA_ESCAPE_H_
+#define _SVGA_ESCAPE_H_
+
+
+/*
+ * Namespace IDs for the escape command
+ */
+
+#define SVGA_ESCAPE_NSID_VMWARE 0x00000000
+#define SVGA_ESCAPE_NSID_DEVEL  0xFFFFFFFF
+
+
+/*
+ * Within SVGA_ESCAPE_NSID_VMWARE, we multiplex commands according to
+ * the first DWORD of escape data (after the nsID and size). As a
+ * guideline we're using the high word and low word as a major and
+ * minor command number, respectively.
+ *
+ * Major command number allocation:
+ *
+ *   0000: Reserved
+ *   0001: SVGA_ESCAPE_VMWARE_LOG (svga_binary_logger.h)
+ *   0002: SVGA_ESCAPE_VMWARE_VIDEO (svga_overlay.h)
+ *   0003: SVGA_ESCAPE_VMWARE_HINT (svga_escape.h)
+ */
+
+#define SVGA_ESCAPE_VMWARE_MAJOR_MASK  0xFFFF0000
+
+
+/*
+ * SVGA Hint commands.
+ *
+ * These escapes let the SVGA driver provide optional information to
+ * he host about the state of the guest or guest applications. The
+ * host can use these hints to make user interface or performance
+ * decisions.
+ *
+ * Notes:
+ *
+ *   - SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN is deprecated for guests
+ *     that use the SVGA Screen Object extension. Instead of sending
+ *     this escape, use the SVGA_SCREEN_FULLSCREEN_HINT flag on your
+ *     Screen Object.
+ */
+
+#define SVGA_ESCAPE_VMWARE_HINT               0x00030000
+#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN    0x00030001  // Deprecated
+
+typedef
+struct {
+   uint32 command;
+   uint32 fullscreen;
+   struct {
+      int32 x, y;
+   } monitorPosition;
+} SVGAEscapeHintFullscreen;
+
+#endif /* _SVGA_ESCAPE_H_ */
diff --git a/drivers/gpu/drm/vmwgfx/svga_overlay.h b/drivers/gpu/drm/vmwgfx/svga_overlay.h
new file mode 100644
index 0000000..f753d73
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga_overlay.h
@@ -0,0 +1,201 @@
+/**********************************************************
+ * Copyright 2007-2009 VMware, Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/*
+ * svga_overlay.h --
+ *
+ *    Definitions for video-overlay support.
+ */
+
+#ifndef _SVGA_OVERLAY_H_
+#define _SVGA_OVERLAY_H_
+
+#include "svga_reg.h"
+
+/*
+ * Video formats we support
+ */
+
+#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2'
+#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2'
+#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y'
+
+typedef enum {
+   SVGA_OVERLAY_FORMAT_INVALID = 0,
+   SVGA_OVERLAY_FORMAT_YV12 = VMWARE_FOURCC_YV12,
+   SVGA_OVERLAY_FORMAT_YUY2 = VMWARE_FOURCC_YUY2,
+   SVGA_OVERLAY_FORMAT_UYVY = VMWARE_FOURCC_UYVY,
+} SVGAOverlayFormat;
+
+#define SVGA_VIDEO_COLORKEY_MASK             0x00ffffff
+
+#define SVGA_ESCAPE_VMWARE_VIDEO             0x00020000
+
+#define SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS    0x00020001
+        /* FIFO escape layout:
+         * Type, Stream Id, (Register Id, Value) pairs */
+
+#define SVGA_ESCAPE_VMWARE_VIDEO_FLUSH       0x00020002
+        /* FIFO escape layout:
+         * Type, Stream Id */
+
+typedef
+struct SVGAEscapeVideoSetRegs {
+   struct {
+      uint32 cmdType;
+      uint32 streamId;
+   } header;
+
+   // May include zero or more items.
+   struct {
+      uint32 registerId;
+      uint32 value;
+   } items[1];
+} SVGAEscapeVideoSetRegs;
+
+typedef
+struct SVGAEscapeVideoFlush {
+   uint32 cmdType;
+   uint32 streamId;
+} SVGAEscapeVideoFlush;
+
+
+/*
+ * Struct definitions for the video overlay commands built on
+ * SVGAFifoCmdEscape.
+ */
+typedef
+struct {
+   uint32 command;
+   uint32 overlay;
+} SVGAFifoEscapeCmdVideoBase;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+} SVGAFifoEscapeCmdVideoFlush;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+   struct {
+      uint32 regId;
+      uint32 value;
+   } items[1];
+} SVGAFifoEscapeCmdVideoSetRegs;
+
+typedef
+struct {
+   SVGAFifoEscapeCmdVideoBase videoCmd;
+   struct {
+      uint32 regId;
+      uint32 value;
+   } items[SVGA_VIDEO_NUM_REGS];
+} SVGAFifoEscapeCmdVideoSetAllRegs;
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VMwareVideoGetAttributes --
+ *
+ *      Computes the size, pitches and offsets for YUV frames.
+ *
+ * Results:
+ *      TRUE on success; otherwise FALSE on failure.
+ *
+ * Side effects:
+ *      Pitches and offsets for the given YUV frame are put in 'pitches'
+ *      and 'offsets' respectively. They are both optional though.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline bool
+VMwareVideoGetAttributes(const SVGAOverlayFormat format,    // IN
+                         uint32 *width,                     // IN / OUT
+                         uint32 *height,                    // IN / OUT
+                         uint32 *size,                      // OUT
+                         uint32 *pitches,                   // OUT (optional)
+                         uint32 *offsets)                   // OUT (optional)
+{
+    int tmp;
+
+    *width = (*width + 1) & ~1;
+
+    if (offsets) {
+        offsets[0] = 0;
+    }
+
+    switch (format) {
+    case VMWARE_FOURCC_YV12:
+       *height = (*height + 1) & ~1;
+       *size = (*width + 3) & ~3;
+
+       if (pitches) {
+          pitches[0] = *size;
+       }
+
+       *size *= *height;
+
+       if (offsets) {
+          offsets[1] = *size;
+       }
+
+       tmp = ((*width >> 1) + 3) & ~3;
+
+       if (pitches) {
+          pitches[1] = pitches[2] = tmp;
+       }
+
+       tmp *= (*height >> 1);
+       *size += tmp;
+
+       if (offsets) {
+          offsets[2] = *size;
+       }
+
+       *size += tmp;
+       break;
+
+    case VMWARE_FOURCC_YUY2:
+    case VMWARE_FOURCC_UYVY:
+       *size = *width * 2;
+
+       if (pitches) {
+          pitches[0] = *size;
+       }
+
+       *size *= *height;
+       break;
+
+    default:
+       return false;
+    }
+
+    return true;
+}
+
+#endif // _SVGA_OVERLAY_H_
diff --git a/drivers/gpu/drm/vmwgfx/svga_reg.h b/drivers/gpu/drm/vmwgfx/svga_reg.h
new file mode 100644
index 0000000..1b96c2e
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga_reg.h
@@ -0,0 +1,1346 @@
+/**********************************************************
+ * Copyright 1998-2009 VMware, Inc.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/*
+ * svga_reg.h --
+ *
+ *    Virtual hardware definitions for the VMware SVGA II device.
+ */
+
+#ifndef _SVGA_REG_H_
+#define _SVGA_REG_H_
+
+/*
+ * PCI device IDs.
+ */
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
+
+/*
+ * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned
+ * cursor bypass mode. This is still supported, but no new guest
+ * drivers should use it.
+ */
+#define SVGA_CURSOR_ON_HIDE            0x0   /* Must be 0 to maintain backward compatibility */
+#define SVGA_CURSOR_ON_SHOW            0x1   /* Must be 1 to maintain backward compatibility */
+#define SVGA_CURSOR_ON_REMOVE_FROM_FB  0x2   /* Remove the cursor from the framebuffer because we need to see what's under it */
+#define SVGA_CURSOR_ON_RESTORE_TO_FB   0x3   /* Put the cursor back in the framebuffer so the user can see it */
+
+/*
+ * The maximum framebuffer size that can traced for e.g. guests in VESA mode.
+ * The changeMap in the monitor is proportional to this number. Therefore, we'd
+ * like to keep it as small as possible to reduce monitor overhead (using
+ * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over
+ * 4k!).
+ *
+ * NB: For compatibility reasons, this value must be greater than 0xff0000.
+ *     See bug 335072.
+ */
+#define SVGA_FB_MAX_TRACEABLE_SIZE      0x1000000
+
+#define SVGA_MAX_PSEUDOCOLOR_DEPTH      8
+#define SVGA_MAX_PSEUDOCOLORS           (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
+#define SVGA_NUM_PALETTE_REGS           (3 * SVGA_MAX_PSEUDOCOLORS)
+
+#define SVGA_MAGIC         0x900000UL
+#define SVGA_MAKE_ID(ver)  (SVGA_MAGIC << 8 | (ver))
+
+/* Version 2 let the address of the frame buffer be unsigned on Win32 */
+#define SVGA_VERSION_2     2
+#define SVGA_ID_2          SVGA_MAKE_ID(SVGA_VERSION_2)
+
+/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so
+   PALETTE_BASE has moved */
+#define SVGA_VERSION_1     1
+#define SVGA_ID_1          SVGA_MAKE_ID(SVGA_VERSION_1)
+
+/* Version 0 is the initial version */
+#define SVGA_VERSION_0     0
+#define SVGA_ID_0          SVGA_MAKE_ID(SVGA_VERSION_0)
+
+/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */
+#define SVGA_ID_INVALID    0xFFFFFFFF
+
+/* Port offsets, relative to BAR0 */
+#define SVGA_INDEX_PORT         0x0
+#define SVGA_VALUE_PORT         0x1
+#define SVGA_BIOS_PORT          0x2
+#define SVGA_IRQSTATUS_PORT     0x8
+
+/*
+ * Interrupt source flags for IRQSTATUS_PORT and IRQMASK.
+ *
+ * Interrupts are only supported when the
+ * SVGA_CAP_IRQMASK capability is present.
+ */
+#define SVGA_IRQFLAG_ANY_FENCE            0x1    /* Any fence was passed */
+#define SVGA_IRQFLAG_FIFO_PROGRESS        0x2    /* Made forward progress in the FIFO */
+#define SVGA_IRQFLAG_FENCE_GOAL           0x4    /* SVGA_FIFO_FENCE_GOAL reached */
+
+/*
+ * Registers
+ */
+
+enum {
+   SVGA_REG_ID = 0,
+   SVGA_REG_ENABLE = 1,
+   SVGA_REG_WIDTH = 2,
+   SVGA_REG_HEIGHT = 3,
+   SVGA_REG_MAX_WIDTH = 4,
+   SVGA_REG_MAX_HEIGHT = 5,
+   SVGA_REG_DEPTH = 6,
+   SVGA_REG_BITS_PER_PIXEL = 7,       /* Current bpp in the guest */
+   SVGA_REG_PSEUDOCOLOR = 8,
+   SVGA_REG_RED_MASK = 9,
+   SVGA_REG_GREEN_MASK = 10,
+   SVGA_REG_BLUE_MASK = 11,
+   SVGA_REG_BYTES_PER_LINE = 12,
+   SVGA_REG_FB_START = 13,            /* (Deprecated) */
+   SVGA_REG_FB_OFFSET = 14,
+   SVGA_REG_VRAM_SIZE = 15,
+   SVGA_REG_FB_SIZE = 16,
+
+   /* ID 0 implementation only had the above registers, then the palette */
+
+   SVGA_REG_CAPABILITIES = 17,
+   SVGA_REG_MEM_START = 18,           /* (Deprecated) */
+   SVGA_REG_MEM_SIZE = 19,
+   SVGA_REG_CONFIG_DONE = 20,         /* Set when memory area configured */
+   SVGA_REG_SYNC = 21,                /* See "FIFO Synchronization Registers" */
+   SVGA_REG_BUSY = 22,                /* See "FIFO Synchronization Registers" */
+   SVGA_REG_GUEST_ID = 23,            /* Set guest OS identifier */
+   SVGA_REG_CURSOR_ID = 24,           /* (Deprecated) */
+   SVGA_REG_CURSOR_X = 25,            /* (Deprecated) */
+   SVGA_REG_CURSOR_Y = 26,            /* (Deprecated) */
+   SVGA_REG_CURSOR_ON = 27,           /* (Deprecated) */
+   SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */
+   SVGA_REG_SCRATCH_SIZE = 29,        /* Number of scratch registers */
+   SVGA_REG_MEM_REGS = 30,            /* Number of FIFO registers */
+   SVGA_REG_NUM_DISPLAYS = 31,        /* (Deprecated) */
+   SVGA_REG_PITCHLOCK = 32,           /* Fixed pitch for all modes */
+   SVGA_REG_IRQMASK = 33,             /* Interrupt mask */
+
+   /* Legacy multi-monitor support */
+   SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */
+   SVGA_REG_DISPLAY_ID = 35,        /* Display ID for the following display attributes */
+   SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */
+   SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */
+   SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */
+   SVGA_REG_DISPLAY_WIDTH = 39,     /* The display's width */
+   SVGA_REG_DISPLAY_HEIGHT = 40,    /* The display's height */
+
+   /* See "Guest memory regions" below. */
+   SVGA_REG_GMR_ID = 41,
+   SVGA_REG_GMR_DESCRIPTOR = 42,
+   SVGA_REG_GMR_MAX_IDS = 43,
+   SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44,
+
+   SVGA_REG_TRACES = 45,            /* Enable trace-based updates even when FIFO is on */
+   SVGA_REG_TOP = 46,               /* Must be 1 more than the last register */
+
+   SVGA_PALETTE_BASE = 1024,        /* Base of SVGA color map */
+   /* Next 768 (== 256*3) registers exist for colormap */
+
+   SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
+                                    /* Base of scratch registers */
+   /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage:
+      First 4 are reserved for VESA BIOS Extension; any remaining are for
+      the use of the current SVGA driver. */
+};
+
+
+/*
+ * Guest memory regions (GMRs):
+ *
+ * This is a new memory mapping feature available in SVGA devices
+ * which have the SVGA_CAP_GMR bit set. Previously, there were two
+ * fixed memory regions available with which to share data between the
+ * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs
+ * are our name for an extensible way of providing arbitrary DMA
+ * buffers for use between the driver and the SVGA device. They are a
+ * new alternative to framebuffer memory, usable for both 2D and 3D
+ * graphics operations.
+ *
+ * Since GMR mapping must be done synchronously with guest CPU
+ * execution, we use a new pair of SVGA registers:
+ *
+ *   SVGA_REG_GMR_ID --
+ *
+ *     Read/write.
+ *     This register holds the 32-bit ID (a small positive integer)
+ *     of a GMR to create, delete, or redefine. Writing this register
+ *     has no side-effects.
+ *
+ *   SVGA_REG_GMR_DESCRIPTOR --
+ *
+ *     Write-only.
+ *     Writing this register will create, delete, or redefine the GMR
+ *     specified by the above ID register. If this register is zero,
+ *     the GMR is deleted. Any pointers into this GMR (including those
+ *     currently being processed by FIFO commands) will be
+ *     synchronously invalidated.
+ *
+ *     If this register is nonzero, it must be the physical page
+ *     number (PPN) of a data structure which describes the physical
+ *     layout of the memory region this GMR should describe. The
+ *     descriptor structure will be read synchronously by the SVGA
+ *     device when this register is written. The descriptor need not
+ *     remain allocated for the lifetime of the GMR.
+ *
+ *     The guest driver should write SVGA_REG_GMR_ID first, then
+ *     SVGA_REG_GMR_DESCRIPTOR.
+ *
+ *   SVGA_REG_GMR_MAX_IDS --
+ *
+ *     Read-only.
+ *     The SVGA device may choose to support a maximum number of
+ *     user-defined GMR IDs. This register holds the number of supported
+ *     IDs. (The maximum supported ID plus 1)
+ *
+ *   SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH --
+ *
+ *     Read-only.
+ *     The SVGA device may choose to put a limit on the total number
+ *     of SVGAGuestMemDescriptor structures it will read when defining
+ *     a single GMR.
+ *
+ * The descriptor structure is an array of SVGAGuestMemDescriptor
+ * structures. Each structure may do one of three things:
+ *
+ *   - Terminate the GMR descriptor list.
+ *     (ppn==0, numPages==0)
+ *
+ *   - Add a PPN or range of PPNs to the GMR's virtual address space.
+ *     (ppn != 0, numPages != 0)
+ *
+ *   - Provide the PPN of the next SVGAGuestMemDescriptor, in order to
+ *     support multi-page GMR descriptor tables without forcing the
+ *     driver to allocate physically contiguous memory.
+ *     (ppn != 0, numPages == 0)
+ *
+ * Note that each physical page of SVGAGuestMemDescriptor structures
+ * can describe at least 2MB of guest memory. If the driver needs to
+ * use more than one page of descriptor structures, it must use one of
+ * its SVGAGuestMemDescriptors to point to an additional page.  The
+ * device will never automatically cross a page boundary.
+ *
+ * Once the driver has described a GMR, it is immediately available
+ * for use via any FIFO command that uses an SVGAGuestPtr structure.
+ * These pointers include a GMR identifier plus an offset into that
+ * GMR.
+ *
+ * The driver must check the SVGA_CAP_GMR bit before using the GMR
+ * registers.
+ */
+
+/*
+ * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer
+ * memory as well.  In the future, these IDs could even be used to
+ * allow legacy memory regions to be redefined by the guest as GMRs.
+ *
+ * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA
+ * is being phased out. Please try to use user-defined GMRs whenever
+ * possible.
+ */
+#define SVGA_GMR_NULL         ((uint32) -1)
+#define SVGA_GMR_FRAMEBUFFER  ((uint32) -2)  // Guest Framebuffer (GFB)
+
+typedef
+struct SVGAGuestMemDescriptor {
+   uint32 ppn;
+   uint32 numPages;
+} SVGAGuestMemDescriptor;
+
+typedef
+struct SVGAGuestPtr {
+   uint32 gmrId;
+   uint32 offset;
+} SVGAGuestPtr;
+
+
+/*
+ * SVGAGMRImageFormat --
+ *
+ *    This is a packed representation of the source 2D image format
+ *    for a GMR-to-screen blit. Currently it is defined as an encoding
+ *    of the screen's color depth and bits-per-pixel, however, 16 bits
+ *    are reserved for future use to identify other encodings (such as
+ *    RGBA or higher-precision images).
+ *
+ *    Currently supported formats:
+ *
+ *       bpp depth  Format Name
+ *       --- -----  -----------
+ *        32    24  32-bit BGRX
+ *        24    24  24-bit BGR
+ *        16    16  RGB 5-6-5
+ *        16    15  RGB 5-5-5
+ *
+ */
+
+typedef
+struct SVGAGMRImageFormat {
+   union {
+      struct {
+         uint32 bitsPerPixel : 8;
+         uint32 colorDepth   : 8;
+         uint32 reserved     : 16;  // Must be zero
+      };
+
+      uint32 value;
+   };
+} SVGAGMRImageFormat;
+
+/*
+ * SVGAColorBGRX --
+ *
+ *    A 24-bit color format (BGRX), which does not depend on the
+ *    format of the legacy guest framebuffer (GFB) or the current
+ *    GMRFB state.
+ */
+
+typedef
+struct SVGAColorBGRX {
+   union {
+      struct {
+         uint32 b : 8;
+         uint32 g : 8;
+         uint32 r : 8;
+         uint32 x : 8;  // Unused
+      };
+
+      uint32 value;
+   };
+} SVGAColorBGRX;
+
+
+/*
+ * SVGASignedRect --
+ * SVGASignedPoint --
+ *
+ *    Signed rectangle and point primitives. These are used by the new
+ *    2D primitives for drawing to Screen Objects, which can occupy a
+ *    signed virtual coordinate space.
+ *
+ *    SVGASignedRect specifies a half-open interval: the (left, top)
+ *    pixel is part of the rectangle, but the (right, bottom) pixel is
+ *    not.
+ */
+
+typedef
+struct SVGASignedRect {
+   int32  left;
+   int32  top;
+   int32  right;
+   int32  bottom;
+} SVGASignedRect;
+
+typedef
+struct SVGASignedPoint {
+   int32  x;
+   int32  y;
+} SVGASignedPoint;
+
+
+/*
+ *  Capabilities
+ *
+ *  Note the holes in the bitfield. Missing bits have been deprecated,
+ *  and must not be reused. Those capabilities will never be reported
+ *  by new versions of the SVGA device.
+ */
+
+#define SVGA_CAP_NONE               0x00000000
+#define SVGA_CAP_RECT_COPY          0x00000002
+#define SVGA_CAP_CURSOR             0x00000020
+#define SVGA_CAP_CURSOR_BYPASS      0x00000040   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_CURSOR_BYPASS_2    0x00000080   // Legacy (Use Cursor Bypass 3 instead)
+#define SVGA_CAP_8BIT_EMULATION     0x00000100
+#define SVGA_CAP_ALPHA_CURSOR       0x00000200
+#define SVGA_CAP_3D                 0x00004000
+#define SVGA_CAP_EXTENDED_FIFO      0x00008000
+#define SVGA_CAP_MULTIMON           0x00010000   // Legacy multi-monitor support
+#define SVGA_CAP_PITCHLOCK          0x00020000
+#define SVGA_CAP_IRQMASK            0x00040000
+#define SVGA_CAP_DISPLAY_TOPOLOGY   0x00080000   // Legacy multi-monitor support
+#define SVGA_CAP_GMR                0x00100000
+#define SVGA_CAP_TRACES             0x00200000
+
+
+/*
+ * FIFO register indices.
+ *
+ * The FIFO is a chunk of device memory mapped into guest physmem.  It
+ * is always treated as 32-bit words.
+ *
+ * The guest driver gets to decide how to partition it between
+ * - FIFO registers (there are always at least 4, specifying where the
+ *   following data area is and how much data it contains; there may be
+ *   more registers following these, depending on the FIFO protocol
+ *   version in use)
+ * - FIFO data, written by the guest and slurped out by the VMX.
+ * These indices are 32-bit word offsets into the FIFO.
+ */
+
+enum {
+   /*
+    * Block 1 (basic registers): The originally defined FIFO registers.
+    * These exist and are valid for all versions of the FIFO protocol.
+    */
+
+   SVGA_FIFO_MIN = 0,
+   SVGA_FIFO_MAX,       /* The distance from MIN to MAX must be at least 10K */
+   SVGA_FIFO_NEXT_CMD,
+   SVGA_FIFO_STOP,
+
+   /*
+    * Block 2 (extended registers): Mandatory registers for the extended
+    * FIFO.  These exist if the SVGA caps register includes
+    * SVGA_CAP_EXTENDED_FIFO; some of them are valid only if their
+    * associated capability bit is enabled.
+    *
+    * Note that when originally defined, SVGA_CAP_EXTENDED_FIFO implied
+    * support only for (FIFO registers) CAPABILITIES, FLAGS, and FENCE.
+    * This means that the guest has to test individually (in most cases
+    * using FIFO caps) for the presence of registers after this; the VMX
+    * can define "extended FIFO" to mean whatever it wants, and currently
+    * won't enable it unless there's room for that set and much more.
+    */
+
+   SVGA_FIFO_CAPABILITIES = 4,
+   SVGA_FIFO_FLAGS,
+   // Valid with SVGA_FIFO_CAP_FENCE:
+   SVGA_FIFO_FENCE,
+
+   /*
+    * Block 3a (optional extended registers): Additional registers for the
+    * extended FIFO, whose presence isn't actually implied by
+    * SVGA_CAP_EXTENDED_FIFO; these exist if SVGA_FIFO_MIN is high enough to
+    * leave room for them.
+    *
+    * These in block 3a, the VMX currently considers mandatory for the
+    * extended FIFO.
+    */
+
+   // Valid if exists (i.e. if extended FIFO enabled):
+   SVGA_FIFO_3D_HWVERSION,       /* See SVGA3dHardwareVersion in svga3d_reg.h */
+   // Valid with SVGA_FIFO_CAP_PITCHLOCK:
+   SVGA_FIFO_PITCHLOCK,
+
+   // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3:
+   SVGA_FIFO_CURSOR_ON,          /* Cursor bypass 3 show/hide register */
+   SVGA_FIFO_CURSOR_X,           /* Cursor bypass 3 x register */
+   SVGA_FIFO_CURSOR_Y,           /* Cursor bypass 3 y register */
+   SVGA_FIFO_CURSOR_COUNT,       /* Incremented when any of the other 3 change */
+   SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */
+
+   // Valid with SVGA_FIFO_CAP_RESERVE:
+   SVGA_FIFO_RESERVED,           /* Bytes past NEXT_CMD with real contents */
+
+   /*
+    * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT:
+    *
+    * By default this is SVGA_ID_INVALID, to indicate that the cursor
+    * coordinates are specified relative to the virtual root. If this
+    * is set to a specific screen ID, cursor position is reinterpreted
+    * as a signed offset relative to that screen's origin. This is the
+    * only way to place the cursor on a non-rooted screen.
+    */
+   SVGA_FIFO_CURSOR_SCREEN_ID,
+
+   /*
+    * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new
+    * registers, but this must be done carefully and with judicious use of
+    * capability bits, since comparisons based on SVGA_FIFO_MIN aren't
+    * enough to tell you whether the register exists: we've shipped drivers
+    * and products that used SVGA_FIFO_3D_CAPS but didn't know about some of
+    * the earlier ones.  The actual order of introduction was:
+    * - PITCHLOCK
+    * - 3D_CAPS
+    * - CURSOR_* (cursor bypass 3)
+    * - RESERVED
+    * So, code that wants to know whether it can use any of the
+    * aforementioned registers, or anything else added after PITCHLOCK and
+    * before 3D_CAPS, needs to reason about something other than
+    * SVGA_FIFO_MIN.
+    */
+
+   /*
+    * 3D caps block space; valid with 3D hardware version >=
+    * SVGA3D_HWVERSION_WS6_B1.
+    */
+   SVGA_FIFO_3D_CAPS      = 32,
+   SVGA_FIFO_3D_CAPS_LAST = 32 + 255,
+
+   /*
+    * End of VMX's current definition of "extended-FIFO registers".
+    * Registers before here are always enabled/disabled as a block; either
+    * the extended FIFO is enabled and includes all preceding registers, or
+    * it's disabled entirely.
+    *
+    * Block 3b (truly optional extended registers): Additional registers for
+    * the extended FIFO, which the VMX already knows how to enable and
+    * disable with correct granularity.
+    *
+    * Registers after here exist if and only if the guest SVGA driver
+    * sets SVGA_FIFO_MIN high enough to leave room for them.
+    */
+
+   // Valid if register exists:
+   SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */
+   SVGA_FIFO_FENCE_GOAL,         /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */
+   SVGA_FIFO_BUSY,               /* See "FIFO Synchronization Registers" */
+
+   /*
+    * Always keep this last.  This defines the maximum number of
+    * registers we know about.  At power-on, this value is placed in
+    * the SVGA_REG_MEM_REGS register, and we expect the guest driver
+    * to allocate this much space in FIFO memory for registers.
+    */
+    SVGA_FIFO_NUM_REGS
+};
+
+
+/*
+ * Definition of registers included in extended FIFO support.
+ *
+ * The guest SVGA driver gets to allocate the FIFO between registers
+ * and data.  It must always allocate at least 4 registers, but old
+ * drivers stopped there.
+ *
+ * The VMX will enable extended FIFO support if and only if the guest
+ * left enough room for all registers defined as part of the mandatory
+ * set for the extended FIFO.
+ *
+ * Note that the guest drivers typically allocate the FIFO only at
+ * initialization time, not at mode switches, so it's likely that the
+ * number of FIFO registers won't change without a reboot.
+ *
+ * All registers less than this value are guaranteed to be present if
+ * svgaUser->fifo.extended is set. Any later registers must be tested
+ * individually for compatibility at each use (in the VMX).
+ *
+ * This value is used only by the VMX, so it can change without
+ * affecting driver compatibility; keep it that way?
+ */
+#define SVGA_FIFO_EXTENDED_MANDATORY_REGS  (SVGA_FIFO_3D_CAPS_LAST + 1)
+
+
+/*
+ * FIFO Synchronization Registers
+ *
+ *  This explains the relationship between the various FIFO
+ *  sync-related registers in IOSpace and in FIFO space.
+ *
+ *  SVGA_REG_SYNC --
+ *
+ *       The SYNC register can be used in two different ways by the guest:
+ *
+ *         1. If the guest wishes to fully sync (drain) the FIFO,
+ *            it will write once to SYNC then poll on the BUSY
+ *            register. The FIFO is sync'ed once BUSY is zero.
+ *
+ *         2. If the guest wants to asynchronously wake up the host,
+ *            it will write once to SYNC without polling on BUSY.
+ *            Ideally it will do this after some new commands have
+ *            been placed in the FIFO, and after reading a zero
+ *            from SVGA_FIFO_BUSY.
+ *
+ *       (1) is the original behaviour that SYNC was designed to
+ *       support.  Originally, a write to SYNC would implicitly
+ *       trigger a read from BUSY. This causes us to synchronously
+ *       process the FIFO.
+ *
+ *       This behaviour has since been changed so that writing SYNC
+ *       will *not* implicitly cause a read from BUSY. Instead, it
+ *       makes a channel call which asynchronously wakes up the MKS
+ *       thread.
+ *
+ *       New guests can use this new behaviour to implement (2)
+ *       efficiently. This lets guests get the host's attention
+ *       without waiting for the MKS to poll, which gives us much
+ *       better CPU utilization on SMP hosts and on UP hosts while
+ *       we're blocked on the host GPU.
+ *
+ *       Old guests shouldn't notice the behaviour change. SYNC was
+ *       never guaranteed to process the entire FIFO, since it was
+ *       bounded to a particular number of CPU cycles. Old guests will
+ *       still loop on the BUSY register until the FIFO is empty.
+ *
+ *       Writing to SYNC currently has the following side-effects:
+ *
+ *         - Sets SVGA_REG_BUSY to TRUE (in the monitor)
+ *         - Asynchronously wakes up the MKS thread for FIFO processing
+ *         - The value written to SYNC is recorded as a "reason", for
+ *           stats purposes.
+ *
+ *       If SVGA_FIFO_BUSY is available, drivers are advised to only
+ *       write to SYNC if SVGA_FIFO_BUSY is FALSE. Drivers should set
+ *       SVGA_FIFO_BUSY to TRUE after writing to SYNC. The MKS will
+ *       eventually set SVGA_FIFO_BUSY on its own, but this approach
+ *       lets the driver avoid sending multiple asynchronous wakeup
+ *       messages to the MKS thread.
+ *
+ *  SVGA_REG_BUSY --
+ *
+ *       This register is set to TRUE when SVGA_REG_SYNC is written,
+ *       and it reads as FALSE when the FIFO has been completely
+ *       drained.
+ *
+ *       Every read from this register causes us to synchronously
+ *       process FIFO commands. There is no guarantee as to how many
+ *       commands each read will process.
+ *
+ *       CPU time spent processing FIFO commands will be billed to
+ *       the guest.
+ *
+ *       New drivers should avoid using this register unless they
+ *       need to guarantee that the FIFO is completely drained. It
+ *       is overkill for performing a sync-to-fence. Older drivers
+ *       will use this register for any type of synchronization.
+ *
+ *  SVGA_FIFO_BUSY --
+ *
+ *       This register is a fast way for the guest driver to check
+ *       whether the FIFO is already being processed. It reads and
+ *       writes at normal RAM speeds, with no monitor intervention.
+ *
+ *       If this register reads as TRUE, the host is guaranteeing that
+ *       any new commands written into the FIFO will be noticed before
+ *       the MKS goes back to sleep.
+ *
+ *       If this register reads as FALSE, no such guarantee can be
+ *       made.
+ *
+ *       The guest should use this register to quickly determine
+ *       whether or not it needs to wake up the host. If the guest
+ *       just wrote a command or group of commands that it would like
+ *       the host to begin processing, it should:
+ *
+ *         1. Read SVGA_FIFO_BUSY. If it reads as TRUE, no further
+ *            action is necessary.
+ *
+ *         2. Write TRUE to SVGA_FIFO_BUSY. This informs future guest
+ *            code that we've already sent a SYNC to the host and we
+ *            don't need to send a duplicate.
+ *
+ *         3. Write a reason to SVGA_REG_SYNC. This will send an
+ *            asynchronous wakeup to the MKS thread.
+ */
+
+
+/*
+ * FIFO Capabilities
+ *
+ *      Fence -- Fence register and command are supported
+ *      Accel Front -- Front buffer only commands are supported
+ *      Pitch Lock -- Pitch lock register is supported
+ *      Video -- SVGA Video overlay units are supported
+ *      Escape -- Escape command is supported
+ *
+ * XXX: Add longer descriptions for each capability, including a list
+ *      of the new features that each capability provides.
+ *
+ * SVGA_FIFO_CAP_SCREEN_OBJECT --
+ *
+ *    Provides dynamic multi-screen rendering, for improved Unity and
+ *    multi-monitor modes. With Screen Object, the guest can
+ *    dynamically create and destroy 'screens', which can represent
+ *    Unity windows or virtual monitors. Screen Object also provides
+ *    strong guarantees that DMA operations happen only when
+ *    guest-initiated. Screen Object deprecates the BAR1 guest
+ *    framebuffer (GFB) and all commands that work only with the GFB.
+ *
+ *    New registers:
+ *       FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID
+ *
+ *    New 2D commands:
+ *       DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN,
+ *       BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY
+ *
+ *    New 3D commands:
+ *       BLIT_SURFACE_TO_SCREEN
+ *
+ *    New guarantees:
+ *
+ *       - The host will not read or write guest memory, including the GFB,
+ *         except when explicitly initiated by a DMA command.
+ *
+ *       - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK,
+ *         is guaranteed to complete before any subsequent FENCEs.
+ *
+ *       - All legacy commands which affect a Screen (UPDATE, PRESENT,
+ *         PRESENT_READBACK) as well as new Screen blit commands will
+ *         all behave consistently as blits, and memory will be read
+ *         or written in FIFO order.
+ *
+ *         For example, if you PRESENT from one SVGA3D surface to multiple
+ *         places on the screen, the data copied will always be from the
+ *         SVGA3D surface at the time the PRESENT was issued in the FIFO.
+ *         This was not necessarily true on devices without Screen Object.
+ *
+ *         This means that on devices that support Screen Object, the
+ *         PRESENT_READBACK command should not be necessary unless you
+ *         actually want to read back the results of 3D rendering into
+ *         system memory. (And for that, the BLIT_SCREEN_TO_GMRFB
+ *         command provides a strict superset of functionality.)
+ *
+ *       - When a screen is resized, either using Screen Object commands or
+ *         legacy multimon registers, its contents are preserved.
+ */
+
+#define SVGA_FIFO_CAP_NONE                  0
+#define SVGA_FIFO_CAP_FENCE             (1<<0)
+#define SVGA_FIFO_CAP_ACCELFRONT        (1<<1)
+#define SVGA_FIFO_CAP_PITCHLOCK         (1<<2)
+#define SVGA_FIFO_CAP_VIDEO             (1<<3)
+#define SVGA_FIFO_CAP_CURSOR_BYPASS_3   (1<<4)
+#define SVGA_FIFO_CAP_ESCAPE            (1<<5)
+#define SVGA_FIFO_CAP_RESERVE           (1<<6)
+#define SVGA_FIFO_CAP_SCREEN_OBJECT     (1<<7)
+
+
+/*
+ * FIFO Flags
+ *
+ *      Accel Front -- Driver should use front buffer only commands
+ */
+
+#define SVGA_FIFO_FLAG_NONE                 0
+#define SVGA_FIFO_FLAG_ACCELFRONT       (1<<0)
+#define SVGA_FIFO_FLAG_RESERVED        (1<<31) // Internal use only
+
+/*
+ * FIFO reservation sentinel value
+ */
+
+#define SVGA_FIFO_RESERVED_UNKNOWN      0xffffffff
+
+
+/*
+ * Video overlay support
+ */
+
+#define SVGA_NUM_OVERLAY_UNITS 32
+
+
+/*
+ * Video capabilities that the guest is currently using
+ */
+
+#define SVGA_VIDEO_FLAG_COLORKEY        0x0001
+
+
+/*
+ * Offsets for the video overlay registers
+ */
+
+enum {
+   SVGA_VIDEO_ENABLED = 0,
+   SVGA_VIDEO_FLAGS,
+   SVGA_VIDEO_DATA_OFFSET,
+   SVGA_VIDEO_FORMAT,
+   SVGA_VIDEO_COLORKEY,
+   SVGA_VIDEO_SIZE,          // Deprecated
+   SVGA_VIDEO_WIDTH,
+   SVGA_VIDEO_HEIGHT,
+   SVGA_VIDEO_SRC_X,
+   SVGA_VIDEO_SRC_Y,
+   SVGA_VIDEO_SRC_WIDTH,
+   SVGA_VIDEO_SRC_HEIGHT,
+   SVGA_VIDEO_DST_X,         // Signed int32
+   SVGA_VIDEO_DST_Y,         // Signed int32
+   SVGA_VIDEO_DST_WIDTH,
+   SVGA_VIDEO_DST_HEIGHT,
+   SVGA_VIDEO_PITCH_1,
+   SVGA_VIDEO_PITCH_2,
+   SVGA_VIDEO_PITCH_3,
+   SVGA_VIDEO_DATA_GMRID,    // Optional, defaults to SVGA_GMR_FRAMEBUFFER
+   SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID)
+   SVGA_VIDEO_NUM_REGS
+};
+
+
+/*
+ * SVGA Overlay Units
+ *
+ *      width and height relate to the entire source video frame.
+ *      srcX, srcY, srcWidth and srcHeight represent subset of the source
+ *      video frame to be displayed.
+ */
+
+typedef struct SVGAOverlayUnit {
+   uint32 enabled;
+   uint32 flags;
+   uint32 dataOffset;
+   uint32 format;
+   uint32 colorKey;
+   uint32 size;
+   uint32 width;
+   uint32 height;
+   uint32 srcX;
+   uint32 srcY;
+   uint32 srcWidth;
+   uint32 srcHeight;
+   int32  dstX;
+   int32  dstY;
+   uint32 dstWidth;
+   uint32 dstHeight;
+   uint32 pitches[3];
+   uint32 dataGMRId;
+   uint32 dstScreenId;
+} SVGAOverlayUnit;
+
+
+/*
+ * SVGAScreenObject --
+ *
+ *    This is a new way to represent a guest's multi-monitor screen or
+ *    Unity window. Screen objects are only supported if the
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set.
+ *
+ *    If Screen Objects are supported, they can be used to fully
+ *    replace the functionality provided by the framebuffer registers
+ *    (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY.
+ *
+ *    The screen object is a struct with guaranteed binary
+ *    compatibility. New flags can be added, and the struct may grow,
+ *    but existing fields must retain their meaning.
+ *
+ */
+
+#define SVGA_SCREEN_HAS_ROOT    (1 << 0)  // Screen is present in the virtual coord space
+#define SVGA_SCREEN_IS_PRIMARY  (1 << 1)  // Guest considers this screen to be 'primary'
+#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2)   // Guest is running a fullscreen app here
+
+typedef
+struct SVGAScreenObject {
+   uint32 structSize;   // sizeof(SVGAScreenObject)
+   uint32 id;
+   uint32 flags;
+   struct {
+      uint32 width;
+      uint32 height;
+   } size;
+   struct {
+      int32 x;
+      int32 y;
+   } root;              // Only used if SVGA_SCREEN_HAS_ROOT is set.
+} SVGAScreenObject;
+
+
+/*
+ *  Commands in the command FIFO:
+ *
+ *  Command IDs defined below are used for the traditional 2D FIFO
+ *  communication (not all commands are available for all versions of the
+ *  SVGA FIFO protocol).
+ *
+ *  Note the holes in the command ID numbers: These commands have been
+ *  deprecated, and the old IDs must not be reused.
+ *
+ *  Command IDs from 1000 to 1999 are reserved for use by the SVGA3D
+ *  protocol.
+ *
+ *  Each command's parameters are described by the comments and
+ *  structs below.
+ */
+
+typedef enum {
+   SVGA_CMD_INVALID_CMD           = 0,
+   SVGA_CMD_UPDATE                = 1,
+   SVGA_CMD_RECT_COPY             = 3,
+   SVGA_CMD_DEFINE_CURSOR         = 19,
+   SVGA_CMD_DEFINE_ALPHA_CURSOR   = 22,
+   SVGA_CMD_UPDATE_VERBOSE        = 25,
+   SVGA_CMD_FRONT_ROP_FILL        = 29,
+   SVGA_CMD_FENCE                 = 30,
+   SVGA_CMD_ESCAPE                = 33,
+   SVGA_CMD_DEFINE_SCREEN         = 34,
+   SVGA_CMD_DESTROY_SCREEN        = 35,
+   SVGA_CMD_DEFINE_GMRFB          = 36,
+   SVGA_CMD_BLIT_GMRFB_TO_SCREEN  = 37,
+   SVGA_CMD_BLIT_SCREEN_TO_GMRFB  = 38,
+   SVGA_CMD_ANNOTATION_FILL       = 39,
+   SVGA_CMD_ANNOTATION_COPY       = 40,
+   SVGA_CMD_MAX
+} SVGAFifoCmdId;
+
+#define SVGA_CMD_MAX_ARGS           64
+
+
+/*
+ * SVGA_CMD_UPDATE --
+ *
+ *    This is a DMA transfer which copies from the Guest Framebuffer
+ *    (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which
+ *    intersect with the provided virtual rectangle.
+ *
+ *    This command does not support using arbitrary guest memory as a
+ *    data source- it only works with the pre-defined GFB memory.
+ *    This command also does not support signed virtual coordinates.
+ *    If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with
+ *    negative root x/y coordinates, the negative portion of those
+ *    screens will not be reachable by this command.
+ *
+ *    This command is not necessary when using framebuffer
+ *    traces. Traces are automatically enabled if the SVGA FIFO is
+ *    disabled, and you may explicitly enable/disable traces using
+ *    SVGA_REG_TRACES. With traces enabled, any write to the GFB will
+ *    automatically act as if a subsequent SVGA_CMD_UPDATE was issued.
+ *
+ *    Traces and SVGA_CMD_UPDATE are the only supported ways to render
+ *    pseudocolor screen updates. The newer Screen Object commands
+ *    only support true color formats.
+ *
+ * Availability:
+ *    Always available.
+ */
+
+typedef
+struct {
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+} SVGAFifoCmdUpdate;
+
+
+/*
+ * SVGA_CMD_RECT_COPY --
+ *
+ *    Perform a rectangular DMA transfer from one area of the GFB to
+ *    another, and copy the result to any screens which intersect it.
+ *
+ * Availability:
+ *    SVGA_CAP_RECT_COPY
+ */
+
+typedef
+struct {
+   uint32 srcX;
+   uint32 srcY;
+   uint32 destX;
+   uint32 destY;
+   uint32 width;
+   uint32 height;
+} SVGAFifoCmdRectCopy;
+
+
+/*
+ * SVGA_CMD_DEFINE_CURSOR --
+ *
+ *    Provide a new cursor image, as an AND/XOR mask.
+ *
+ *    The recommended way to position the cursor overlay is by using
+ *    the SVGA_FIFO_CURSOR_* registers, supported by the
+ *    SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
+ *
+ * Availability:
+ *    SVGA_CAP_CURSOR
+ */
+
+typedef
+struct {
+   uint32 id;             // Reserved, must be zero.
+   uint32 hotspotX;
+   uint32 hotspotY;
+   uint32 width;
+   uint32 height;
+   uint32 andMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   uint32 xorMaskDepth;   // Value must be 1 or equal to BITS_PER_PIXEL
+   /*
+    * Followed by scanline data for AND mask, then XOR mask.
+    * Each scanline is padded to a 32-bit boundary.
+   */
+} SVGAFifoCmdDefineCursor;
+
+
+/*
+ * SVGA_CMD_DEFINE_ALPHA_CURSOR --
+ *
+ *    Provide a new cursor image, in 32-bit BGRA format.
+ *
+ *    The recommended way to position the cursor overlay is by using
+ *    the SVGA_FIFO_CURSOR_* registers, supported by the
+ *    SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability.
+ *
+ * Availability:
+ *    SVGA_CAP_ALPHA_CURSOR
+ */
+
+typedef
+struct {
+   uint32 id;             // Reserved, must be zero.
+   uint32 hotspotX;
+   uint32 hotspotY;
+   uint32 width;
+   uint32 height;
+   /* Followed by scanline data */
+} SVGAFifoCmdDefineAlphaCursor;
+
+
+/*
+ * SVGA_CMD_UPDATE_VERBOSE --
+ *
+ *    Just like SVGA_CMD_UPDATE, but also provide a per-rectangle
+ *    'reason' value, an opaque cookie which is used by internal
+ *    debugging tools. Third party drivers should not use this
+ *    command.
+ *
+ * Availability:
+ *    SVGA_CAP_EXTENDED_FIFO
+ */
+
+typedef
+struct {
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+   uint32 reason;
+} SVGAFifoCmdUpdateVerbose;
+
+
+/*
+ * SVGA_CMD_FRONT_ROP_FILL --
+ *
+ *    This is a hint which tells the SVGA device that the driver has
+ *    just filled a rectangular region of the GFB with a solid
+ *    color. Instead of reading these pixels from the GFB, the device
+ *    can assume that they all equal 'color'. This is primarily used
+ *    for remote desktop protocols.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_ACCELFRONT
+ */
+
+#define  SVGA_ROP_COPY                    0x03
+
+typedef
+struct {
+   uint32 color;     // In the same format as the GFB
+   uint32 x;
+   uint32 y;
+   uint32 width;
+   uint32 height;
+   uint32 rop;       // Must be SVGA_ROP_COPY
+} SVGAFifoCmdFrontRopFill;
+
+
+/*
+ * SVGA_CMD_FENCE --
+ *
+ *    Insert a synchronization fence.  When the SVGA device reaches
+ *    this command, it will copy the 'fence' value into the
+ *    SVGA_FIFO_FENCE register. It will also compare the fence against
+ *    SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the
+ *    SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will
+ *    raise this interrupt.
+ *
+ * Availability:
+ *    SVGA_FIFO_FENCE for this command,
+ *    SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL.
+ */
+
+typedef
+struct {
+   uint32 fence;
+} SVGAFifoCmdFence;
+
+
+/*
+ * SVGA_CMD_ESCAPE --
+ *
+ *    Send an extended or vendor-specific variable length command.
+ *    This is used for video overlay, third party plugins, and
+ *    internal debugging tools. See svga_escape.h
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_ESCAPE
+ */
+
+typedef
+struct {
+   uint32 nsid;
+   uint32 size;
+   /* followed by 'size' bytes of data */
+} SVGAFifoCmdEscape;
+
+
+/*
+ * SVGA_CMD_DEFINE_SCREEN --
+ *
+ *    Define or redefine an SVGAScreenObject. See the description of
+ *    SVGAScreenObject above.  The video driver is responsible for
+ *    generating new screen IDs. They should be small positive
+ *    integers. The virtual device will have an implementation
+ *    specific upper limit on the number of screen IDs
+ *    supported. Drivers are responsible for recycling IDs. The first
+ *    valid ID is zero.
+ *
+ *    - Interaction with other registers:
+ *
+ *    For backwards compatibility, when the GFB mode registers (WIDTH,
+ *    HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
+ *    deletes all screens other than screen #0, and redefines screen
+ *    #0 according to the specified mode. Drivers that use
+ *    SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0.
+ *
+ *    If you use screen objects, do not use the legacy multi-mon
+ *    registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*).
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAScreenObject screen;   // Variable-length according to version
+} SVGAFifoCmdDefineScreen;
+
+
+/*
+ * SVGA_CMD_DESTROY_SCREEN --
+ *
+ *    Destroy an SVGAScreenObject. Its ID is immediately available for
+ *    re-use.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   uint32 screenId;
+} SVGAFifoCmdDestroyScreen;
+
+
+/*
+ * SVGA_CMD_DEFINE_GMRFB --
+ *
+ *    This command sets a piece of SVGA device state called the
+ *    Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a
+ *    piece of light-weight state which identifies the location and
+ *    format of an image in guest memory or in BAR1. The GMRFB has
+ *    an arbitrary size, and it doesn't need to match the geometry
+ *    of the GFB or any screen object.
+ *
+ *    The GMRFB can be redefined as often as you like. You could
+ *    always use the same GMRFB, you could redefine it before
+ *    rendering from a different guest screen, or you could even
+ *    redefine it before every blit.
+ *
+ *    There are multiple ways to use this command. The simplest way is
+ *    to use it to move the framebuffer either to elsewhere in the GFB
+ *    (BAR1) memory region, or to a user-defined GMR. This lets a
+ *    driver use a framebuffer allocated entirely out of normal system
+ *    memory, which we encourage.
+ *
+ *    Another way to use this command is to set up a ring buffer of
+ *    updates in GFB memory. If a driver wants to ensure that no
+ *    frames are skipped by the SVGA device, it is important that the
+ *    driver not modify the source data for a blit until the device is
+ *    done processing the command. One efficient way to accomplish
+ *    this is to use a ring of small DMA buffers. Each buffer is used
+ *    for one blit, then we move on to the next buffer in the
+ *    ring. The FENCE mechanism is used to protect each buffer from
+ *    re-use until the device is finished with that buffer's
+ *    corresponding blit.
+ *
+ *    This command does not affect the meaning of SVGA_CMD_UPDATE.
+ *    UPDATEs always occur from the legacy GFB memory area. This
+ *    command has no support for pseudocolor GMRFBs. Currently only
+ *    true-color 15, 16, and 24-bit depths are supported. Future
+ *    devices may expose capabilities for additional framebuffer
+ *    formats.
+ *
+ *    The default GMRFB value is undefined. Drivers must always send
+ *    this command at least once before performing any blit from the
+ *    GMRFB.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAGuestPtr        ptr;
+   uint32              bytesPerLine;
+   SVGAGMRImageFormat  format;
+} SVGAFifoCmdDefineGMRFB;
+
+
+/*
+ * SVGA_CMD_BLIT_GMRFB_TO_SCREEN --
+ *
+ *    This is a guest-to-host blit. It performs a DMA operation to
+ *    copy a rectangular region of pixels from the current GMRFB to
+ *    one or more Screen Objects.
+ *
+ *    The destination coordinate may be specified relative to a
+ *    screen's origin (if a screen ID is specified) or relative to the
+ *    virtual coordinate system's origin (if the screen ID is
+ *    SVGA_ID_INVALID). The actual destination may span zero or more
+ *    screens, in the case of a virtual destination rect or a rect
+ *    which extends off the edge of the specified screen.
+ *
+ *    This command writes to the screen's "base layer": the underlying
+ *    framebuffer which exists below any cursor or video overlays. No
+ *    action is necessary to explicitly hide or update any overlays
+ *    which exist on top of the updated region.
+ *
+ *    The SVGA device is guaranteed to finish reading from the GMRFB
+ *    by the time any subsequent FENCE commands are reached.
+ *
+ *    This command consumes an annotation. See the
+ *    SVGA_CMD_ANNOTATION_* commands for details.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  srcOrigin;
+   SVGASignedRect   destRect;
+   uint32           destScreenId;
+} SVGAFifoCmdBlitGMRFBToScreen;
+
+
+/*
+ * SVGA_CMD_BLIT_SCREEN_TO_GMRFB --
+ *
+ *    This is a host-to-guest blit. It performs a DMA operation to
+ *    copy a rectangular region of pixels from a single Screen Object
+ *    back to the current GMRFB.
+ *
+ *    Usage note: This command should be used rarely. It will
+ *    typically be inefficient, but it is necessary for some types of
+ *    synchronization between 3D (GPU) and 2D (CPU) rendering into
+ *    overlapping areas of a screen.
+ *
+ *    The source coordinate is specified relative to a screen's
+ *    origin. The provided screen ID must be valid. If any parameters
+ *    are invalid, the resulting pixel values are undefined.
+ *
+ *    This command reads the screen's "base layer". Overlays like
+ *    video and cursor are not included, but any data which was sent
+ *    using a blit-to-screen primitive will be available, no matter
+ *    whether the data's original source was the GMRFB or the 3D
+ *    acceleration hardware.
+ *
+ *    Note that our guest-to-host blits and host-to-guest blits aren't
+ *    symmetric in their current implementation. While the parameters
+ *    are identical, host-to-guest blits are a lot less featureful.
+ *    They do not support clipping: If the source parameters don't
+ *    fully fit within a screen, the blit fails. They must originate
+ *    from exactly one screen. Virtual coordinates are not directly
+ *    supported.
+ *
+ *    Host-to-guest blits do support the same set of GMRFB formats
+ *    offered by guest-to-host blits.
+ *
+ *    The SVGA device is guaranteed to finish writing to the GMRFB by
+ *    the time any subsequent FENCE commands are reached.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  destOrigin;
+   SVGASignedRect   srcRect;
+   uint32           srcScreenId;
+} SVGAFifoCmdBlitScreenToGMRFB;
+
+
+/*
+ * SVGA_CMD_ANNOTATION_FILL --
+ *
+ *    This is a blit annotation. This command stores a small piece of
+ *    device state which is consumed by the next blit-to-screen
+ *    command. The state is only cleared by commands which are
+ *    specifically documented as consuming an annotation. Other
+ *    commands (such as ESCAPEs for debugging) may intervene between
+ *    the annotation and its associated blit.
+ *
+ *    This annotation is a promise about the contents of the next
+ *    blit: The video driver is guaranteeing that all pixels in that
+ *    blit will have the same value, specified here as a color in
+ *    SVGAColorBGRX format.
+ *
+ *    The SVGA device can still render the blit correctly even if it
+ *    ignores this annotation, but the annotation may allow it to
+ *    perform the blit more efficiently, for example by ignoring the
+ *    source data and performing a fill in hardware.
+ *
+ *    This annotation is most important for performance when the
+ *    user's display is being remoted over a network connection.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGAColorBGRX  color;
+} SVGAFifoCmdAnnotationFill;
+
+
+/*
+ * SVGA_CMD_ANNOTATION_COPY --
+ *
+ *    This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more
+ *    information about annotations.
+ *
+ *    This annotation is a promise about the contents of the next
+ *    blit: The video driver is guaranteeing that all pixels in that
+ *    blit will have the same value as those which already exist at an
+ *    identically-sized region on the same or a different screen.
+ *
+ *    Note that the source pixels for the COPY in this annotation are
+ *    sampled before applying the anqnotation's associated blit. They
+ *    are allowed to overlap with the blit's destination pixels.
+ *
+ *    The copy source rectangle is specified the same way as the blit
+ *    destination: it can be a rectangle which spans zero or more
+ *    screens, specified relative to either a screen or to the virtual
+ *    coordinate system's origin. If the source rectangle includes
+ *    pixels which are not from exactly one screen, the results are
+ *    undefined.
+ *
+ * Availability:
+ *    SVGA_FIFO_CAP_SCREEN_OBJECT
+ */
+
+typedef
+struct {
+   SVGASignedPoint  srcOrigin;
+   uint32           srcScreenId;
+} SVGAFifoCmdAnnotationCopy;
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/svga_types.h b/drivers/gpu/drm/vmwgfx/svga_types.h
new file mode 100644
index 0000000..55836de
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/svga_types.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * Silly typedefs for the svga headers. Currently the headers are shared
+ * between all components that talk to svga. And as such the headers are
+ * are in a completely different style and use weird defines.
+ *
+ * This file lets all the ugly be prefixed with svga*.
+ */
+
+#ifndef _SVGA_TYPES_H_
+#define _SVGA_TYPES_H_
+
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint8_t uint8;
+typedef int32_t int32;
+typedef bool Bool;
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
new file mode 100644
index 0000000..d6f2d2b
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -0,0 +1,229 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_placement.h"
+
+static uint32_t vram_placement_flags = TTM_PL_FLAG_VRAM |
+	TTM_PL_FLAG_CACHED;
+
+static uint32_t vram_ne_placement_flags = TTM_PL_FLAG_VRAM |
+	TTM_PL_FLAG_CACHED |
+	TTM_PL_FLAG_NO_EVICT;
+
+static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM |
+	TTM_PL_FLAG_CACHED;
+
+struct ttm_placement vmw_vram_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &vram_placement_flags
+};
+
+struct ttm_placement vmw_vram_ne_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &vram_ne_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &vram_ne_placement_flags
+};
+
+struct ttm_placement vmw_sys_placement = {
+	.fpfn = 0,
+	.lpfn = 0,
+	.num_placement = 1,
+	.placement = &sys_placement_flags,
+	.num_busy_placement = 1,
+	.busy_placement = &sys_placement_flags
+};
+
+struct vmw_ttm_backend {
+	struct ttm_backend backend;
+};
+
+static int vmw_ttm_populate(struct ttm_backend *backend,
+			    unsigned long num_pages, struct page **pages,
+			    struct page *dummy_read_page)
+{
+	return 0;
+}
+
+static int vmw_ttm_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem)
+{
+	return 0;
+}
+
+static int vmw_ttm_unbind(struct ttm_backend *backend)
+{
+	return 0;
+}
+
+static void vmw_ttm_clear(struct ttm_backend *backend)
+{
+}
+
+static void vmw_ttm_destroy(struct ttm_backend *backend)
+{
+	struct vmw_ttm_backend *vmw_be =
+	    container_of(backend, struct vmw_ttm_backend, backend);
+
+	kfree(vmw_be);
+}
+
+static struct ttm_backend_func vmw_ttm_func = {
+	.populate = vmw_ttm_populate,
+	.clear = vmw_ttm_clear,
+	.bind = vmw_ttm_bind,
+	.unbind = vmw_ttm_unbind,
+	.destroy = vmw_ttm_destroy,
+};
+
+struct ttm_backend *vmw_ttm_backend_init(struct ttm_bo_device *bdev)
+{
+	struct vmw_ttm_backend *vmw_be;
+
+	vmw_be = kmalloc(sizeof(*vmw_be), GFP_KERNEL);
+	if (!vmw_be)
+		return NULL;
+
+	vmw_be->backend.func = &vmw_ttm_func;
+
+	return &vmw_be->backend;
+}
+
+int vmw_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
+{
+	return 0;
+}
+
+int vmw_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+		      struct ttm_mem_type_manager *man)
+{
+	struct vmw_private *dev_priv =
+	    container_of(bdev, struct vmw_private, bdev);
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		/* System memory */
+
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_VRAM:
+		/* "On-card" video ram */
+		man->gpu_offset = 0;
+		man->io_offset = dev_priv->vram_start;
+		man->io_size = dev_priv->vram_size;
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+		    TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->io_addr = NULL;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_WC;
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void vmw_evict_flags(struct ttm_buffer_object *bo,
+		     struct ttm_placement *placement)
+{
+	*placement = vmw_sys_placement;
+}
+
+/**
+ * FIXME: Proper access checks on buffers.
+ */
+
+static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp)
+{
+	return 0;
+}
+
+/**
+ * FIXME: We're using the old vmware polling method to sync.
+ * Do this with fences instead.
+ */
+
+static void *vmw_sync_obj_ref(void *sync_obj)
+{
+	return sync_obj;
+}
+
+static void vmw_sync_obj_unref(void **sync_obj)
+{
+	*sync_obj = NULL;
+}
+
+static int vmw_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+	mutex_unlock(&dev_priv->hw_mutex);
+	return 0;
+}
+
+static bool vmw_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+	uint32_t sequence = (unsigned long) sync_obj;
+
+	return vmw_fence_signaled(dev_priv, sequence);
+}
+
+static int vmw_sync_obj_wait(void *sync_obj, void *sync_arg,
+			     bool lazy, bool interruptible)
+{
+	struct vmw_private *dev_priv = (struct vmw_private *)sync_arg;
+	uint32_t sequence = (unsigned long) sync_obj;
+
+	return vmw_wait_fence(dev_priv, false, sequence, false, 3*HZ);
+}
+
+struct ttm_bo_driver vmw_bo_driver = {
+	.create_ttm_backend_entry = vmw_ttm_backend_init,
+	.invalidate_caches = vmw_invalidate_caches,
+	.init_mem_type = vmw_init_mem_type,
+	.evict_flags = vmw_evict_flags,
+	.move = NULL,
+	.verify_access = vmw_verify_access,
+	.sync_obj_signaled = vmw_sync_obj_signaled,
+	.sync_obj_wait = vmw_sync_obj_wait,
+	.sync_obj_flush = vmw_sync_obj_flush,
+	.sync_obj_unref = vmw_sync_obj_unref,
+	.sync_obj_ref = vmw_sync_obj_ref
+};
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
new file mode 100644
index 0000000..7b48bb3
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -0,0 +1,735 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_module.h"
+
+#define VMWGFX_DRIVER_NAME "vmwgfx"
+#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
+#define VMWGFX_CHIP_SVGAII 0
+#define VMW_FB_RESERVATION 0
+
+/**
+ * Fully encoded drm commands. Might move to vmw_drm.h
+ */
+
+#define DRM_IOCTL_VMW_GET_PARAM					\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GET_PARAM,		\
+		 struct drm_vmw_getparam_arg)
+#define DRM_IOCTL_VMW_ALLOC_DMABUF				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_ALLOC_DMABUF,	\
+		union drm_vmw_alloc_dmabuf_arg)
+#define DRM_IOCTL_VMW_UNREF_DMABUF				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_DMABUF,	\
+		struct drm_vmw_unref_dmabuf_arg)
+#define DRM_IOCTL_VMW_CURSOR_BYPASS				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_CURSOR_BYPASS,	\
+		 struct drm_vmw_cursor_bypass_arg)
+
+#define DRM_IOCTL_VMW_CONTROL_STREAM				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_CONTROL_STREAM,	\
+		 struct drm_vmw_control_stream_arg)
+#define DRM_IOCTL_VMW_CLAIM_STREAM				\
+	DRM_IOR(DRM_COMMAND_BASE + DRM_VMW_CLAIM_STREAM,	\
+		 struct drm_vmw_stream_arg)
+#define DRM_IOCTL_VMW_UNREF_STREAM				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_STREAM,	\
+		 struct drm_vmw_stream_arg)
+
+#define DRM_IOCTL_VMW_CREATE_CONTEXT				\
+	DRM_IOR(DRM_COMMAND_BASE + DRM_VMW_CREATE_CONTEXT,	\
+		struct drm_vmw_context_arg)
+#define DRM_IOCTL_VMW_UNREF_CONTEXT				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_CONTEXT,	\
+		struct drm_vmw_context_arg)
+#define DRM_IOCTL_VMW_CREATE_SURFACE				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_SURFACE,	\
+		 union drm_vmw_surface_create_arg)
+#define DRM_IOCTL_VMW_UNREF_SURFACE				\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UNREF_SURFACE,	\
+		 struct drm_vmw_surface_arg)
+#define DRM_IOCTL_VMW_REF_SURFACE				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_REF_SURFACE,	\
+		 union drm_vmw_surface_reference_arg)
+#define DRM_IOCTL_VMW_EXECBUF					\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_EXECBUF,		\
+		struct drm_vmw_execbuf_arg)
+#define DRM_IOCTL_VMW_FIFO_DEBUG				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FIFO_DEBUG,		\
+		 struct drm_vmw_fifo_debug_arg)
+#define DRM_IOCTL_VMW_FENCE_WAIT				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT,		\
+		 struct drm_vmw_fence_wait_arg)
+
+
+/**
+ * The core DRM version of this macro doesn't account for
+ * DRM_COMMAND_BASE.
+ */
+
+#define VMW_IOCTL_DEF(ioctl, func, flags) \
+	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+/**
+ * Ioctl definitions.
+ */
+
+static struct drm_ioctl_desc vmw_ioctls[] = {
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl, 0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS,
+		      vmw_kms_cursor_bypass_ioctl, 0),
+
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
+		      0),
+
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
+		      0),
+	VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
+		      0)
+};
+
+static struct pci_device_id vmw_pci_id_list[] = {
+	{0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},
+	{0, 0, 0}
+};
+
+static char *vmw_devname = "vmwgfx";
+
+static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
+static void vmw_master_init(struct vmw_master *);
+
+static void vmw_print_capabilities(uint32_t capabilities)
+{
+	DRM_INFO("Capabilities:\n");
+	if (capabilities & SVGA_CAP_RECT_COPY)
+		DRM_INFO("  Rect copy.\n");
+	if (capabilities & SVGA_CAP_CURSOR)
+		DRM_INFO("  Cursor.\n");
+	if (capabilities & SVGA_CAP_CURSOR_BYPASS)
+		DRM_INFO("  Cursor bypass.\n");
+	if (capabilities & SVGA_CAP_CURSOR_BYPASS_2)
+		DRM_INFO("  Cursor bypass 2.\n");
+	if (capabilities & SVGA_CAP_8BIT_EMULATION)
+		DRM_INFO("  8bit emulation.\n");
+	if (capabilities & SVGA_CAP_ALPHA_CURSOR)
+		DRM_INFO("  Alpha cursor.\n");
+	if (capabilities & SVGA_CAP_3D)
+		DRM_INFO("  3D.\n");
+	if (capabilities & SVGA_CAP_EXTENDED_FIFO)
+		DRM_INFO("  Extended Fifo.\n");
+	if (capabilities & SVGA_CAP_MULTIMON)
+		DRM_INFO("  Multimon.\n");
+	if (capabilities & SVGA_CAP_PITCHLOCK)
+		DRM_INFO("  Pitchlock.\n");
+	if (capabilities & SVGA_CAP_IRQMASK)
+		DRM_INFO("  Irq mask.\n");
+	if (capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)
+		DRM_INFO("  Display Topology.\n");
+	if (capabilities & SVGA_CAP_GMR)
+		DRM_INFO("  GMR.\n");
+	if (capabilities & SVGA_CAP_TRACES)
+		DRM_INFO("  Traces.\n");
+}
+
+static int vmw_request_device(struct vmw_private *dev_priv)
+{
+	int ret;
+
+	vmw_kms_save_vga(dev_priv);
+
+	ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Unable to initialize FIFO.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void vmw_release_device(struct vmw_private *dev_priv)
+{
+	vmw_fifo_release(dev_priv, &dev_priv->fifo);
+	vmw_kms_restore_vga(dev_priv);
+}
+
+
+static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+	struct vmw_private *dev_priv;
+	int ret;
+
+	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+	if (unlikely(dev_priv == NULL)) {
+		DRM_ERROR("Failed allocating a device private struct.\n");
+		return -ENOMEM;
+	}
+	memset(dev_priv, 0, sizeof(*dev_priv));
+
+	dev_priv->dev = dev;
+	dev_priv->vmw_chipset = chipset;
+	mutex_init(&dev_priv->hw_mutex);
+	mutex_init(&dev_priv->cmdbuf_mutex);
+	rwlock_init(&dev_priv->resource_lock);
+	idr_init(&dev_priv->context_idr);
+	idr_init(&dev_priv->surface_idr);
+	idr_init(&dev_priv->stream_idr);
+	ida_init(&dev_priv->gmr_ida);
+	mutex_init(&dev_priv->init_mutex);
+	init_waitqueue_head(&dev_priv->fence_queue);
+	init_waitqueue_head(&dev_priv->fifo_queue);
+	atomic_set(&dev_priv->fence_queue_waiters, 0);
+	atomic_set(&dev_priv->fifo_queue_waiters, 0);
+	INIT_LIST_HEAD(&dev_priv->gmr_lru);
+
+	dev_priv->io_start = pci_resource_start(dev->pdev, 0);
+	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
+	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
+
+	if (dev_priv->capabilities & SVGA_CAP_GMR) {
+		dev_priv->max_gmr_descriptors =
+			vmw_read(dev_priv,
+				 SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
+		dev_priv->max_gmr_ids =
+			vmw_read(dev_priv, SVGA_REG_GMR_MAX_IDS);
+	}
+
+	dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
+	dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE);
+	dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH);
+	dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT);
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	vmw_print_capabilities(dev_priv->capabilities);
+
+	if (dev_priv->capabilities & SVGA_CAP_GMR) {
+		DRM_INFO("Max GMR ids is %u\n",
+			 (unsigned)dev_priv->max_gmr_ids);
+		DRM_INFO("Max GMR descriptors is %u\n",
+			 (unsigned)dev_priv->max_gmr_descriptors);
+	}
+	DRM_INFO("VRAM at 0x%08x size is %u kiB\n",
+		 dev_priv->vram_start, dev_priv->vram_size / 1024);
+	DRM_INFO("MMIO at 0x%08x size is %u kiB\n",
+		 dev_priv->mmio_start, dev_priv->mmio_size / 1024);
+
+	ret = vmw_ttm_global_init(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_err0;
+
+
+	vmw_master_init(&dev_priv->fbdev_master);
+	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
+	dev_priv->active_master = &dev_priv->fbdev_master;
+
+
+	ret = ttm_bo_device_init(&dev_priv->bdev,
+				 dev_priv->bo_global_ref.ref.object,
+				 &vmw_bo_driver, VMWGFX_FILE_PAGE_OFFSET,
+				 false);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed initializing TTM buffer object driver.\n");
+		goto out_err1;
+	}
+
+	ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM,
+			     (dev_priv->vram_size >> PAGE_SHIFT));
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed initializing memory manager for VRAM.\n");
+		goto out_err2;
+	}
+
+	dev_priv->mmio_mtrr = drm_mtrr_add(dev_priv->mmio_start,
+					   dev_priv->mmio_size, DRM_MTRR_WC);
+
+	dev_priv->mmio_virt = ioremap_wc(dev_priv->mmio_start,
+					 dev_priv->mmio_size);
+
+	if (unlikely(dev_priv->mmio_virt == NULL)) {
+		ret = -ENOMEM;
+		DRM_ERROR("Failed mapping MMIO.\n");
+		goto out_err3;
+	}
+
+	dev_priv->tdev = ttm_object_device_init
+	    (dev_priv->mem_global_ref.object, 12);
+
+	if (unlikely(dev_priv->tdev == NULL)) {
+		DRM_ERROR("Unable to initialize TTM object management.\n");
+		ret = -ENOMEM;
+		goto out_err4;
+	}
+
+	dev->dev_private = dev_priv;
+
+	if (!dev->devname)
+		dev->devname = vmw_devname;
+
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
+		ret = drm_irq_install(dev);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed installing irq: %d\n", ret);
+			goto out_no_irq;
+		}
+	}
+
+	ret = pci_request_regions(dev->pdev, "vmwgfx probe");
+	dev_priv->stealth = (ret != 0);
+	if (dev_priv->stealth) {
+		/**
+		 * Request at least the mmio PCI resource.
+		 */
+
+		DRM_INFO("It appears like vesafb is loaded. "
+			 "Ignore above error if any. Entering stealth mode.\n");
+		ret = pci_request_region(dev->pdev, 2, "vmwgfx stealth probe");
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Failed reserving the SVGA MMIO resource.\n");
+			goto out_no_device;
+		}
+		vmw_kms_init(dev_priv);
+		vmw_overlay_init(dev_priv);
+	} else {
+		ret = vmw_request_device(dev_priv);
+		if (unlikely(ret != 0))
+			goto out_no_device;
+		vmw_kms_init(dev_priv);
+		vmw_overlay_init(dev_priv);
+		vmw_fb_init(dev_priv);
+	}
+
+	return 0;
+
+out_no_device:
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev->devname == vmw_devname)
+		dev->devname = NULL;
+out_no_irq:
+	ttm_object_device_release(&dev_priv->tdev);
+out_err4:
+	iounmap(dev_priv->mmio_virt);
+out_err3:
+	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
+		     dev_priv->mmio_size, DRM_MTRR_WC);
+	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+out_err2:
+	(void)ttm_bo_device_release(&dev_priv->bdev);
+out_err1:
+	vmw_ttm_global_release(dev_priv);
+out_err0:
+	ida_destroy(&dev_priv->gmr_ida);
+	idr_destroy(&dev_priv->surface_idr);
+	idr_destroy(&dev_priv->context_idr);
+	idr_destroy(&dev_priv->stream_idr);
+	kfree(dev_priv);
+	return ret;
+}
+
+static int vmw_driver_unload(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+
+	DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n");
+
+	if (!dev_priv->stealth) {
+		vmw_fb_close(dev_priv);
+		vmw_kms_close(dev_priv);
+		vmw_overlay_close(dev_priv);
+		vmw_release_device(dev_priv);
+		pci_release_regions(dev->pdev);
+	} else {
+		vmw_kms_close(dev_priv);
+		vmw_overlay_close(dev_priv);
+		pci_release_region(dev->pdev, 2);
+	}
+	if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
+		drm_irq_uninstall(dev_priv->dev);
+	if (dev->devname == vmw_devname)
+		dev->devname = NULL;
+	ttm_object_device_release(&dev_priv->tdev);
+	iounmap(dev_priv->mmio_virt);
+	drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start,
+		     dev_priv->mmio_size, DRM_MTRR_WC);
+	(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
+	(void)ttm_bo_device_release(&dev_priv->bdev);
+	vmw_ttm_global_release(dev_priv);
+	ida_destroy(&dev_priv->gmr_ida);
+	idr_destroy(&dev_priv->surface_idr);
+	idr_destroy(&dev_priv->context_idr);
+	idr_destroy(&dev_priv->stream_idr);
+
+	kfree(dev_priv);
+
+	return 0;
+}
+
+static void vmw_postclose(struct drm_device *dev,
+			 struct drm_file *file_priv)
+{
+	struct vmw_fpriv *vmw_fp;
+
+	vmw_fp = vmw_fpriv(file_priv);
+	ttm_object_file_release(&vmw_fp->tfile);
+	if (vmw_fp->locked_master)
+		drm_master_put(&vmw_fp->locked_master);
+	kfree(vmw_fp);
+}
+
+static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp;
+	int ret = -ENOMEM;
+
+	vmw_fp = kzalloc(sizeof(*vmw_fp), GFP_KERNEL);
+	if (unlikely(vmw_fp == NULL))
+		return ret;
+
+	vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
+	if (unlikely(vmw_fp->tfile == NULL))
+		goto out_no_tfile;
+
+	file_priv->driver_priv = vmw_fp;
+
+	if (unlikely(dev_priv->bdev.dev_mapping == NULL))
+		dev_priv->bdev.dev_mapping =
+			file_priv->filp->f_path.dentry->d_inode->i_mapping;
+
+	return 0;
+
+out_no_tfile:
+	kfree(vmw_fp);
+	return ret;
+}
+
+static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev = file_priv->minor->dev;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	long ret;
+
+	/*
+	 * The driver private ioctls and TTM ioctls should be
+	 * thread-safe.
+	 */
+
+	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
+	    && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+		struct drm_ioctl_desc *ioctl =
+		    &vmw_ioctls[nr - DRM_COMMAND_BASE];
+
+		if (unlikely(ioctl->cmd != cmd)) {
+			DRM_ERROR("Invalid command format, ioctl %d\n",
+				  nr - DRM_COMMAND_BASE);
+			return -EINVAL;
+		}
+		return drm_ioctl(filp->f_path.dentry->d_inode,
+				 filp, cmd, arg);
+	}
+
+	/*
+	 * Not all old drm ioctls are thread-safe.
+	 */
+
+	lock_kernel();
+	ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
+static int vmw_firstopen(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	dev_priv->is_opened = true;
+
+	return 0;
+}
+
+static void vmw_lastclose(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_crtc *crtc;
+	struct drm_mode_set set;
+	int ret;
+
+	/**
+	 * Do nothing on the lastclose call from drm_unload.
+	 */
+
+	if (!dev_priv->is_opened)
+		return;
+
+	dev_priv->is_opened = false;
+	set.x = 0;
+	set.y = 0;
+	set.fb = NULL;
+	set.mode = NULL;
+	set.connectors = NULL;
+	set.num_connectors = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		set.crtc = crtc;
+		ret = crtc->funcs->set_config(&set);
+		WARN_ON(ret != 0);
+	}
+
+}
+
+static void vmw_master_init(struct vmw_master *vmaster)
+{
+	ttm_lock_init(&vmaster->lock);
+}
+
+static int vmw_master_create(struct drm_device *dev,
+			     struct drm_master *master)
+{
+	struct vmw_master *vmaster;
+
+	DRM_INFO("Master create.\n");
+	vmaster = kzalloc(sizeof(*vmaster), GFP_KERNEL);
+	if (unlikely(vmaster == NULL))
+		return -ENOMEM;
+
+	ttm_lock_init(&vmaster->lock);
+	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+	master->driver_priv = vmaster;
+
+	return 0;
+}
+
+static void vmw_master_destroy(struct drm_device *dev,
+			       struct drm_master *master)
+{
+	struct vmw_master *vmaster = vmw_master(master);
+
+	DRM_INFO("Master destroy.\n");
+	master->driver_priv = NULL;
+	kfree(vmaster);
+}
+
+
+static int vmw_master_set(struct drm_device *dev,
+			  struct drm_file *file_priv,
+			  bool from_open)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct vmw_master *active = dev_priv->active_master;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret = 0;
+
+	DRM_INFO("Master set.\n");
+	if (dev_priv->stealth) {
+		ret = vmw_request_device(dev_priv);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+
+	if (active) {
+		BUG_ON(active != &dev_priv->fbdev_master);
+		ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
+		if (unlikely(ret != 0))
+			goto out_no_active_lock;
+
+		ttm_lock_set_kill(&active->lock, true, SIGTERM);
+		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Unable to clean VRAM on "
+				  "master drop.\n");
+		}
+
+		dev_priv->active_master = NULL;
+	}
+
+	ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
+	if (!from_open) {
+		ttm_vt_unlock(&vmaster->lock);
+		BUG_ON(vmw_fp->locked_master != file_priv->master);
+		drm_master_put(&vmw_fp->locked_master);
+	}
+
+	dev_priv->active_master = vmaster;
+
+	return 0;
+
+out_no_active_lock:
+	vmw_release_device(dev_priv);
+	return ret;
+}
+
+static void vmw_master_drop(struct drm_device *dev,
+			    struct drm_file *file_priv,
+			    bool from_release)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	DRM_INFO("Master drop.\n");
+
+	/**
+	 * Make sure the master doesn't disappear while we have
+	 * it locked.
+	 */
+
+	vmw_fp->locked_master = drm_master_get(file_priv->master);
+	ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
+
+	if (unlikely((ret != 0))) {
+		DRM_ERROR("Unable to lock TTM at VT switch.\n");
+		drm_master_put(&vmw_fp->locked_master);
+	}
+
+	ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);
+
+	if (dev_priv->stealth) {
+		ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
+		if (unlikely(ret != 0))
+			DRM_ERROR("Unable to clean VRAM on master drop.\n");
+		vmw_release_device(dev_priv);
+	}
+	dev_priv->active_master = &dev_priv->fbdev_master;
+	ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
+	ttm_vt_unlock(&dev_priv->fbdev_master.lock);
+
+	if (!dev_priv->stealth)
+		vmw_fb_on(dev_priv);
+}
+
+
+static void vmw_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_put_dev(dev);
+}
+
+static struct drm_driver driver = {
+	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
+	DRIVER_MODESET,
+	.load = vmw_driver_load,
+	.unload = vmw_driver_unload,
+	.firstopen = vmw_firstopen,
+	.lastclose = vmw_lastclose,
+	.irq_preinstall = vmw_irq_preinstall,
+	.irq_postinstall = vmw_irq_postinstall,
+	.irq_uninstall = vmw_irq_uninstall,
+	.irq_handler = vmw_irq_handler,
+	.reclaim_buffers_locked = NULL,
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.ioctls = vmw_ioctls,
+	.num_ioctls = DRM_ARRAY_SIZE(vmw_ioctls),
+	.dma_quiescent = NULL,	/*vmw_dma_quiescent, */
+	.master_create = vmw_master_create,
+	.master_destroy = vmw_master_destroy,
+	.master_set = vmw_master_set,
+	.master_drop = vmw_master_drop,
+	.open = vmw_driver_open,
+	.postclose = vmw_postclose,
+	.fops = {
+		 .owner = THIS_MODULE,
+		 .open = drm_open,
+		 .release = drm_release,
+		 .unlocked_ioctl = vmw_unlocked_ioctl,
+		 .mmap = vmw_mmap,
+		 .poll = drm_poll,
+		 .fasync = drm_fasync,
+#if defined(CONFIG_COMPAT)
+		 .compat_ioctl = drm_compat_ioctl,
+#endif
+		 },
+	.pci_driver = {
+		       .name = VMWGFX_DRIVER_NAME,
+		       .id_table = vmw_pci_id_list,
+		       .probe = vmw_probe,
+		       .remove = vmw_remove
+		       },
+	.name = VMWGFX_DRIVER_NAME,
+	.desc = VMWGFX_DRIVER_DESC,
+	.date = VMWGFX_DRIVER_DATE,
+	.major = VMWGFX_DRIVER_MAJOR,
+	.minor = VMWGFX_DRIVER_MINOR,
+	.patchlevel = VMWGFX_DRIVER_PATCHLEVEL
+};
+
+static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	return drm_get_dev(pdev, ent, &driver);
+}
+
+static int __init vmwgfx_init(void)
+{
+	int ret;
+	ret = drm_init(&driver);
+	if (ret)
+		DRM_ERROR("Failed initializing DRM.\n");
+	return ret;
+}
+
+static void __exit vmwgfx_exit(void)
+{
+	drm_exit(&driver);
+}
+
+module_init(vmwgfx_init);
+module_exit(vmwgfx_exit);
+
+MODULE_AUTHOR("VMware Inc. and others");
+MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
new file mode 100644
index 0000000..43546d0
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -0,0 +1,511 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _VMWGFX_DRV_H_
+#define _VMWGFX_DRV_H_
+
+#include "vmwgfx_reg.h"
+#include "drmP.h"
+#include "vmwgfx_drm.h"
+#include "drm_hashtab.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_lock.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "ttm/ttm_module.h"
+
+#define VMWGFX_DRIVER_DATE "20090724"
+#define VMWGFX_DRIVER_MAJOR 0
+#define VMWGFX_DRIVER_MINOR 1
+#define VMWGFX_DRIVER_PATCHLEVEL 2
+#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
+#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
+#define VMWGFX_MAX_RELOCATIONS 2048
+#define VMWGFX_MAX_GMRS 2048
+
+struct vmw_fpriv {
+	struct drm_master *locked_master;
+	struct ttm_object_file *tfile;
+};
+
+struct vmw_dma_buffer {
+	struct ttm_buffer_object base;
+	struct list_head validate_list;
+	struct list_head gmr_lru;
+	uint32_t gmr_id;
+	bool gmr_bound;
+	uint32_t cur_validate_node;
+	bool on_validate_list;
+};
+
+struct vmw_resource {
+	struct kref kref;
+	struct vmw_private *dev_priv;
+	struct idr *idr;
+	int id;
+	enum ttm_object_type res_type;
+	bool avail;
+	void (*hw_destroy) (struct vmw_resource *res);
+	void (*res_free) (struct vmw_resource *res);
+
+	/* TODO is a generic snooper needed? */
+#if 0
+	void (*snoop)(struct vmw_resource *res,
+		      struct ttm_object_file *tfile,
+		      SVGA3dCmdHeader *header);
+	void *snoop_priv;
+#endif
+};
+
+struct vmw_cursor_snooper {
+	struct drm_crtc *crtc;
+	size_t age;
+	uint32_t *image;
+};
+
+struct vmw_surface {
+	struct vmw_resource res;
+	uint32_t flags;
+	uint32_t format;
+	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
+	struct drm_vmw_size *sizes;
+	uint32_t num_sizes;
+
+	/* TODO so far just a extra pointer */
+	struct vmw_cursor_snooper snooper;
+};
+
+struct vmw_fifo_state {
+	unsigned long reserved_size;
+	__le32 *dynamic_buffer;
+	__le32 *static_buffer;
+	__le32 *last_buffer;
+	uint32_t last_data_size;
+	uint32_t last_buffer_size;
+	bool last_buffer_add;
+	unsigned long static_buffer_size;
+	bool using_bounce_buffer;
+	uint32_t capabilities;
+	struct rw_semaphore rwsem;
+};
+
+struct vmw_relocation {
+	SVGAGuestPtr *location;
+	uint32_t index;
+};
+
+struct vmw_sw_context{
+	struct ida bo_list;
+	uint32_t last_cid;
+	bool cid_valid;
+	uint32_t last_sid;
+	bool sid_valid;
+	struct ttm_object_file *tfile;
+	struct list_head validate_nodes;
+	struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
+	uint32_t cur_reloc;
+	struct ttm_validate_buffer val_bufs[VMWGFX_MAX_GMRS];
+	uint32_t cur_val_buf;
+};
+
+struct vmw_legacy_display;
+struct vmw_overlay;
+
+struct vmw_master {
+	struct ttm_lock lock;
+};
+
+struct vmw_private {
+	struct ttm_bo_device bdev;
+	struct ttm_bo_global_ref bo_global_ref;
+	struct ttm_global_reference mem_global_ref;
+
+	struct vmw_fifo_state fifo;
+
+	struct drm_device *dev;
+	unsigned long vmw_chipset;
+	unsigned int io_start;
+	uint32_t vram_start;
+	uint32_t vram_size;
+	uint32_t mmio_start;
+	uint32_t mmio_size;
+	uint32_t fb_max_width;
+	uint32_t fb_max_height;
+	__le32 __iomem *mmio_virt;
+	int mmio_mtrr;
+	uint32_t capabilities;
+	uint32_t max_gmr_descriptors;
+	uint32_t max_gmr_ids;
+	struct mutex hw_mutex;
+
+	/*
+	 * VGA registers.
+	 */
+
+	uint32_t vga_width;
+	uint32_t vga_height;
+	uint32_t vga_depth;
+	uint32_t vga_bpp;
+	uint32_t vga_pseudo;
+	uint32_t vga_red_mask;
+	uint32_t vga_blue_mask;
+	uint32_t vga_green_mask;
+
+	/*
+	 * Framebuffer info.
+	 */
+
+	void *fb_info;
+	struct vmw_legacy_display *ldu_priv;
+	struct vmw_overlay *overlay_priv;
+
+	/*
+	 * Context and surface management.
+	 */
+
+	rwlock_t resource_lock;
+	struct idr context_idr;
+	struct idr surface_idr;
+	struct idr stream_idr;
+
+	/*
+	 * Block lastclose from racing with firstopen.
+	 */
+
+	struct mutex init_mutex;
+
+	/*
+	 * A resource manager for kernel-only surfaces and
+	 * contexts.
+	 */
+
+	struct ttm_object_device *tdev;
+
+	/*
+	 * Fencing and IRQs.
+	 */
+
+	uint32_t fence_seq;
+	wait_queue_head_t fence_queue;
+	wait_queue_head_t fifo_queue;
+	atomic_t fence_queue_waiters;
+	atomic_t fifo_queue_waiters;
+	uint32_t last_read_sequence;
+	spinlock_t irq_lock;
+
+	/*
+	 * Device state
+	 */
+
+	uint32_t traces_state;
+	uint32_t enable_state;
+	uint32_t config_done_state;
+
+	/**
+	 * Execbuf
+	 */
+	/**
+	 * Protected by the cmdbuf mutex.
+	 */
+
+	struct vmw_sw_context ctx;
+	uint32_t val_seq;
+	struct mutex cmdbuf_mutex;
+
+	/**
+	 * GMR management. Protected by the lru spinlock.
+	 */
+
+	struct ida gmr_ida;
+	struct list_head gmr_lru;
+
+
+	/**
+	 * Operating mode.
+	 */
+
+	bool stealth;
+	bool is_opened;
+
+	/**
+	 * Master management.
+	 */
+
+	struct vmw_master *active_master;
+	struct vmw_master fbdev_master;
+};
+
+static inline struct vmw_private *vmw_priv(struct drm_device *dev)
+{
+	return (struct vmw_private *)dev->dev_private;
+}
+
+static inline struct vmw_fpriv *vmw_fpriv(struct drm_file *file_priv)
+{
+	return (struct vmw_fpriv *)file_priv->driver_priv;
+}
+
+static inline struct vmw_master *vmw_master(struct drm_master *master)
+{
+	return (struct vmw_master *) master->driver_priv;
+}
+
+static inline void vmw_write(struct vmw_private *dev_priv,
+			     unsigned int offset, uint32_t value)
+{
+	outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT);
+	outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT);
+}
+
+static inline uint32_t vmw_read(struct vmw_private *dev_priv,
+				unsigned int offset)
+{
+	uint32_t val;
+
+	outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT);
+	val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT);
+	return val;
+}
+
+/**
+ * GMR utilities - vmwgfx_gmr.c
+ */
+
+extern int vmw_gmr_bind(struct vmw_private *dev_priv,
+			struct ttm_buffer_object *bo);
+extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
+
+/**
+ * Resource utilities - vmwgfx_resource.c
+ */
+
+extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
+extern void vmw_resource_unreference(struct vmw_resource **p_res);
+extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
+extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+extern int vmw_context_check(struct vmw_private *dev_priv,
+			     struct ttm_object_file *tfile,
+			     int id);
+extern void vmw_surface_res_free(struct vmw_resource *res);
+extern int vmw_surface_init(struct vmw_private *dev_priv,
+			    struct vmw_surface *srf,
+			    void (*res_free) (struct vmw_resource *res));
+extern int vmw_user_surface_lookup(struct vmw_private *dev_priv,
+				   struct ttm_object_file *tfile,
+				   int sid, struct vmw_surface **out);
+extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv);
+extern int vmw_surface_check(struct vmw_private *dev_priv,
+			     struct ttm_object_file *tfile,
+			     int id);
+extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
+extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
+			   struct vmw_dma_buffer *vmw_bo,
+			   size_t size, struct ttm_placement *placement,
+			   bool interuptable,
+			   void (*bo_free) (struct ttm_buffer_object *bo));
+extern int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
+					 uint32_t cur_validate_node);
+extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
+extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
+				  uint32_t id, struct vmw_dma_buffer **out);
+extern uint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo);
+extern void vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id);
+extern int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id);
+extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				       struct vmw_dma_buffer *bo);
+extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
+				struct vmw_dma_buffer *bo);
+extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
+				  struct ttm_object_file *tfile,
+				  uint32_t *inout_id,
+				  struct vmw_resource **out);
+
+
+/**
+ * Misc Ioctl functionality - vmwgfx_ioctl.c
+ */
+
+extern int vmw_getparam_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+extern int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+
+/**
+ * Fifo utilities - vmwgfx_fifo.c
+ */
+
+extern int vmw_fifo_init(struct vmw_private *dev_priv,
+			 struct vmw_fifo_state *fifo);
+extern void vmw_fifo_release(struct vmw_private *dev_priv,
+			     struct vmw_fifo_state *fifo);
+extern void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes);
+extern void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes);
+extern int vmw_fifo_send_fence(struct vmw_private *dev_priv,
+			       uint32_t *sequence);
+extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason);
+extern int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/**
+ * TTM glue - vmwgfx_ttm_glue.c
+ */
+
+extern int vmw_ttm_global_init(struct vmw_private *dev_priv);
+extern void vmw_ttm_global_release(struct vmw_private *dev_priv);
+extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma);
+
+/**
+ * TTM buffer object driver - vmwgfx_buffer.c
+ */
+
+extern struct ttm_placement vmw_vram_placement;
+extern struct ttm_placement vmw_vram_ne_placement;
+extern struct ttm_placement vmw_sys_placement;
+extern struct ttm_bo_driver vmw_bo_driver;
+extern int vmw_dma_quiescent(struct drm_device *dev);
+
+/**
+ * Command submission - vmwgfx_execbuf.c
+ */
+
+extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+
+/**
+ * IRQs and wating - vmwgfx_irq.c
+ */
+
+extern irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS);
+extern int vmw_wait_fence(struct vmw_private *dev_priv, bool lazy,
+			  uint32_t sequence, bool interruptible,
+			  unsigned long timeout);
+extern void vmw_irq_preinstall(struct drm_device *dev);
+extern int vmw_irq_postinstall(struct drm_device *dev);
+extern void vmw_irq_uninstall(struct drm_device *dev);
+extern bool vmw_fence_signaled(struct vmw_private *dev_priv,
+			       uint32_t sequence);
+extern int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+extern int vmw_fallback_wait(struct vmw_private *dev_priv,
+			     bool lazy,
+			     bool fifo_idle,
+			     uint32_t sequence,
+			     bool interruptible,
+			     unsigned long timeout);
+
+/**
+ * Kernel framebuffer - vmwgfx_fb.c
+ */
+
+int vmw_fb_init(struct vmw_private *vmw_priv);
+int vmw_fb_close(struct vmw_private *dev_priv);
+int vmw_fb_off(struct vmw_private *vmw_priv);
+int vmw_fb_on(struct vmw_private *vmw_priv);
+
+/**
+ * Kernel modesetting - vmwgfx_kms.c
+ */
+
+int vmw_kms_init(struct vmw_private *dev_priv);
+int vmw_kms_close(struct vmw_private *dev_priv);
+int vmw_kms_save_vga(struct vmw_private *vmw_priv);
+int vmw_kms_restore_vga(struct vmw_private *vmw_priv);
+int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv);
+void vmw_kms_cursor_snoop(struct vmw_surface *srf,
+			  struct ttm_object_file *tfile,
+			  struct ttm_buffer_object *bo,
+			  SVGA3dCmdHeader *header);
+
+/**
+ * Overlay control - vmwgfx_overlay.c
+ */
+
+int vmw_overlay_init(struct vmw_private *dev_priv);
+int vmw_overlay_close(struct vmw_private *dev_priv);
+int vmw_overlay_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
+int vmw_overlay_stop_all(struct vmw_private *dev_priv);
+int vmw_overlay_resume_all(struct vmw_private *dev_priv);
+int vmw_overlay_pause_all(struct vmw_private *dev_priv);
+int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out);
+int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id);
+int vmw_overlay_num_overlays(struct vmw_private *dev_priv);
+int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv);
+
+/**
+ * Inline helper functions
+ */
+
+static inline void vmw_surface_unreference(struct vmw_surface **srf)
+{
+	struct vmw_surface *tmp_srf = *srf;
+	struct vmw_resource *res = &tmp_srf->res;
+	*srf = NULL;
+
+	vmw_resource_unreference(&res);
+}
+
+static inline struct vmw_surface *vmw_surface_reference(struct vmw_surface *srf)
+{
+	(void) vmw_resource_reference(&srf->res);
+	return srf;
+}
+
+static inline void vmw_dmabuf_unreference(struct vmw_dma_buffer **buf)
+{
+	struct vmw_dma_buffer *tmp_buf = *buf;
+	struct ttm_buffer_object *bo = &tmp_buf->base;
+	*buf = NULL;
+
+	ttm_bo_unref(&bo);
+}
+
+static inline struct vmw_dma_buffer *vmw_dmabuf_reference(struct vmw_dma_buffer *buf)
+{
+	if (ttm_bo_reference(&buf->base))
+		return buf;
+	return NULL;
+}
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
new file mode 100644
index 0000000..7a39f3e
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_reg.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_placement.h"
+
+static int vmw_cmd_invalid(struct vmw_private *dev_priv,
+			   struct vmw_sw_context *sw_context,
+			   SVGA3dCmdHeader *header)
+{
+	return capable(CAP_SYS_ADMIN) ? : -EINVAL;
+}
+
+static int vmw_cmd_ok(struct vmw_private *dev_priv,
+		      struct vmw_sw_context *sw_context,
+		      SVGA3dCmdHeader *header)
+{
+	return 0;
+}
+
+static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     SVGA3dCmdHeader *header)
+{
+	struct vmw_cid_cmd {
+		SVGA3dCmdHeader header;
+		__le32 cid;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_cid_cmd, header);
+	if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid))
+		return 0;
+
+	ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not find or use context %u\n",
+			  (unsigned) cmd->cid);
+		return ret;
+	}
+
+	sw_context->last_cid = cmd->cid;
+	sw_context->cid_valid = true;
+
+	return 0;
+}
+
+static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     uint32_t sid)
+{
+	if (unlikely((!sw_context->sid_valid || sid != sw_context->last_sid) &&
+		     sid != SVGA3D_INVALID_ID)) {
+		int ret = vmw_surface_check(dev_priv, sw_context->tfile, sid);
+
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("Could ot find or use surface %u\n",
+				  (unsigned) sid);
+			return ret;
+		}
+
+		sw_context->last_sid = sid;
+		sw_context->sid_valid = true;
+	}
+	return 0;
+}
+
+
+static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
+					   struct vmw_sw_context *sw_context,
+					   SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSetRenderTarget body;
+	} *cmd;
+	int ret;
+
+	ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		return ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.target.sid);
+}
+
+static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
+				      struct vmw_sw_context *sw_context,
+				      SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceCopy body;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
+	if (unlikely(ret != 0))
+		return ret;
+	return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
+}
+
+static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
+				     struct vmw_sw_context *sw_context,
+				     SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceStretchBlt body;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
+	if (unlikely(ret != 0))
+		return ret;
+	return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
+}
+
+static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
+					 struct vmw_sw_context *sw_context,
+					 SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdBlitSurfaceToScreen body;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.srcImage.sid);
+}
+
+static int vmw_cmd_present_check(struct vmw_private *dev_priv,
+				 struct vmw_sw_context *sw_context,
+				 SVGA3dCmdHeader *header)
+{
+	struct vmw_sid_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+	} *cmd;
+
+	cmd = container_of(header, struct vmw_sid_cmd, header);
+	return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.sid);
+}
+
+static int vmw_cmd_dma(struct vmw_private *dev_priv,
+		       struct vmw_sw_context *sw_context,
+		       SVGA3dCmdHeader *header)
+{
+	uint32_t handle;
+	struct vmw_dma_buffer *vmw_bo = NULL;
+	struct ttm_buffer_object *bo;
+	struct vmw_surface *srf = NULL;
+	struct vmw_dma_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceDMA dma;
+	} *cmd;
+	struct vmw_relocation *reloc;
+	int ret;
+	uint32_t cur_validate_node;
+	struct ttm_validate_buffer *val_buf;
+
+
+	cmd = container_of(header, struct vmw_dma_cmd, header);
+	ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->dma.host.sid);
+	if (unlikely(ret != 0))
+		return ret;
+
+	handle = cmd->dma.guest.ptr.gmrId;
+	ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not find or use GMR region.\n");
+		return -EINVAL;
+	}
+	bo = &vmw_bo->base;
+
+	if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
+		DRM_ERROR("Max number of DMA commands per submission"
+			  " exceeded\n");
+		ret = -EINVAL;
+		goto out_no_reloc;
+	}
+
+	reloc = &sw_context->relocs[sw_context->cur_reloc++];
+	reloc->location = &cmd->dma.guest.ptr;
+
+	cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf);
+	if (unlikely(cur_validate_node >= VMWGFX_MAX_GMRS)) {
+		DRM_ERROR("Max number of DMA buffers per submission"
+			  " exceeded.\n");
+		ret = -EINVAL;
+		goto out_no_reloc;
+	}
+
+	reloc->index = cur_validate_node;
+	if (unlikely(cur_validate_node == sw_context->cur_val_buf)) {
+		val_buf = &sw_context->val_bufs[cur_validate_node];
+		val_buf->bo = ttm_bo_reference(bo);
+		val_buf->new_sync_obj_arg = (void *) dev_priv;
+		list_add_tail(&val_buf->head, &sw_context->validate_nodes);
+		++sw_context->cur_val_buf;
+	}
+
+	ret = vmw_user_surface_lookup(dev_priv, sw_context->tfile,
+				      cmd->dma.host.sid, &srf);
+	if (ret) {
+		DRM_ERROR("could not find surface\n");
+		goto out_no_reloc;
+	}
+
+	vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
+	vmw_surface_unreference(&srf);
+
+out_no_reloc:
+	vmw_dmabuf_unreference(&vmw_bo);
+	return ret;
+}
+
+
+typedef int (*vmw_cmd_func) (struct vmw_private *,
+			     struct vmw_sw_context *,
+			     SVGA3dCmdHeader *);
+
+#define VMW_CMD_DEF(cmd, func) \
+	[cmd - SVGA_3D_CMD_BASE] = func
+
+static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DESTROY, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_COPY, &vmw_cmd_surface_copy_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_STRETCHBLT, &vmw_cmd_stretch_blt_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DMA, &vmw_cmd_dma),
+	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DEFINE, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_CONTEXT_DESTROY, &vmw_cmd_invalid),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETTRANSFORM, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETZRANGE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
+		    &vmw_cmd_set_render_target_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETVIEWPORT, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETCLIPPLANE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_CLEAR, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_cid_check),
+	VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
+	VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
+		    &vmw_cmd_blt_surf_screen_check)
+};
+
+static int vmw_cmd_check(struct vmw_private *dev_priv,
+			 struct vmw_sw_context *sw_context,
+			 void *buf, uint32_t *size)
+{
+	uint32_t cmd_id;
+	SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
+	int ret;
+
+	cmd_id = ((uint32_t *)buf)[0];
+	if (cmd_id == SVGA_CMD_UPDATE) {
+		*size = 5 << 2;
+		return 0;
+	}
+
+	cmd_id = le32_to_cpu(header->id);
+	*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);
+
+	cmd_id -= SVGA_3D_CMD_BASE;
+	if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
+		goto out_err;
+
+	ret = vmw_cmd_funcs[cmd_id](dev_priv, sw_context, header);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	return 0;
+out_err:
+	DRM_ERROR("Illegal / Invalid SVGA3D command: %d\n",
+		  cmd_id + SVGA_3D_CMD_BASE);
+	return -EINVAL;
+}
+
+static int vmw_cmd_check_all(struct vmw_private *dev_priv,
+			     struct vmw_sw_context *sw_context,
+			     void *buf, uint32_t size)
+{
+	int32_t cur_size = size;
+	int ret;
+
+	while (cur_size > 0) {
+		ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
+		if (unlikely(ret != 0))
+			return ret;
+		buf = (void *)((unsigned long) buf + size);
+		cur_size -= size;
+	}
+
+	if (unlikely(cur_size != 0)) {
+		DRM_ERROR("Command verifier out of sync.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vmw_free_relocations(struct vmw_sw_context *sw_context)
+{
+	sw_context->cur_reloc = 0;
+}
+
+static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
+{
+	uint32_t i;
+	struct vmw_relocation *reloc;
+	struct ttm_validate_buffer *validate;
+	struct ttm_buffer_object *bo;
+
+	for (i = 0; i < sw_context->cur_reloc; ++i) {
+		reloc = &sw_context->relocs[i];
+		validate = &sw_context->val_bufs[reloc->index];
+		bo = validate->bo;
+		reloc->location->offset += bo->offset;
+		reloc->location->gmrId = vmw_dmabuf_gmr(bo);
+	}
+	vmw_free_relocations(sw_context);
+}
+
+static void vmw_clear_validations(struct vmw_sw_context *sw_context)
+{
+	struct ttm_validate_buffer *entry, *next;
+
+	list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
+				 head) {
+		list_del(&entry->head);
+		vmw_dmabuf_validate_clear(entry->bo);
+		ttm_bo_unref(&entry->bo);
+		sw_context->cur_val_buf--;
+	}
+	BUG_ON(sw_context->cur_val_buf != 0);
+}
+
+static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
+				      struct ttm_buffer_object *bo)
+{
+	int ret;
+
+	if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL)
+		return 0;
+
+	ret = vmw_gmr_bind(dev_priv, bo);
+	if (likely(ret == 0 || ret == -ERESTART))
+		return ret;
+
+
+	ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false);
+	return ret;
+}
+
+
+static int vmw_validate_buffers(struct vmw_private *dev_priv,
+				struct vmw_sw_context *sw_context)
+{
+	struct ttm_validate_buffer *entry;
+	int ret;
+
+	list_for_each_entry(entry, &sw_context->validate_nodes, head) {
+		ret = vmw_validate_single_buffer(dev_priv, entry->bo);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	return 0;
+}
+
+int vmw_execbuf_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data;
+	struct drm_vmw_fence_rep fence_rep;
+	struct drm_vmw_fence_rep __user *user_fence_rep;
+	int ret;
+	void *user_cmd;
+	void *cmd;
+	uint32_t sequence;
+	struct vmw_sw_context *sw_context = &dev_priv->ctx;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+	if (unlikely(ret != 0)) {
+		ret = -ERESTART;
+		goto out_no_cmd_mutex;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, arg->command_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving fifo space for commands.\n");
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	user_cmd = (void __user *)(unsigned long)arg->commands;
+	ret = copy_from_user(cmd, user_cmd, arg->command_size);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed copying commands.\n");
+		goto out_commit;
+	}
+
+	sw_context->tfile = vmw_fpriv(file_priv)->tfile;
+	sw_context->cid_valid = false;
+	sw_context->sid_valid = false;
+	sw_context->cur_reloc = 0;
+	sw_context->cur_val_buf = 0;
+
+	INIT_LIST_HEAD(&sw_context->validate_nodes);
+
+	ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size);
+	if (unlikely(ret != 0))
+		goto out_err;
+	ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes,
+				     dev_priv->val_seq++);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	ret = vmw_validate_buffers(dev_priv, sw_context);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	vmw_apply_relocations(sw_context);
+	vmw_fifo_commit(dev_priv, arg->command_size);
+
+	ret = vmw_fifo_send_fence(dev_priv, &sequence);
+
+	ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
+				    (void *)(unsigned long) sequence);
+	vmw_clear_validations(sw_context);
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+
+	/*
+	 * This error is harmless, because if fence submission fails,
+	 * vmw_fifo_send_fence will sync.
+	 */
+
+	if (ret != 0)
+		DRM_ERROR("Fence submission error. Syncing.\n");
+
+	fence_rep.error = ret;
+	fence_rep.fence_seq = (uint64_t) sequence;
+
+	user_fence_rep = (struct drm_vmw_fence_rep __user *)
+	    (unsigned long)arg->fence_rep;
+
+	/*
+	 * copy_to_user errors will be detected by user space not
+	 * seeing fence_rep::error filled in.
+	 */
+
+	ret = copy_to_user(user_fence_rep, &fence_rep, sizeof(fence_rep));
+
+	vmw_kms_cursor_post_execbuf(dev_priv);
+	ttm_read_unlock(&vmaster->lock);
+	return 0;
+out_err:
+	vmw_free_relocations(sw_context);
+	ttm_eu_backoff_reservation(&sw_context->validate_nodes);
+	vmw_clear_validations(sw_context);
+out_commit:
+	vmw_fifo_commit(dev_priv, 0);
+out_unlock:
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+out_no_cmd_mutex:
+	ttm_read_unlock(&vmaster->lock);
+	return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
new file mode 100644
index 0000000..641dde7
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -0,0 +1,742 @@
+/**************************************************************************
+ *
+ * Copyright © 2007 David Airlie
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+#include "ttm/ttm_placement.h"
+
+#define VMW_DIRTY_DELAY (HZ / 30)
+
+struct vmw_fb_par {
+	struct vmw_private *vmw_priv;
+
+	void *vmalloc;
+
+	struct vmw_dma_buffer *vmw_bo;
+	struct ttm_bo_kmap_obj map;
+
+	u32 pseudo_palette[17];
+
+	unsigned depth;
+	unsigned bpp;
+
+	unsigned max_width;
+	unsigned max_height;
+
+	void *bo_ptr;
+	unsigned bo_size;
+	bool bo_iowrite;
+
+	struct {
+		spinlock_t lock;
+		bool active;
+		unsigned x1;
+		unsigned y1;
+		unsigned x2;
+		unsigned y2;
+	} dirty;
+};
+
+static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	struct vmw_fb_par *par = info->par;
+	u32 *pal = par->pseudo_palette;
+
+	if (regno > 15) {
+		DRM_ERROR("Bad regno %u.\n", regno);
+		return 1;
+	}
+
+	switch (par->depth) {
+	case 24:
+	case 32:
+		pal[regno] = ((red & 0xff00) << 8) |
+			      (green & 0xff00) |
+			     ((blue  & 0xff00) >> 8);
+		break;
+	default:
+		DRM_ERROR("Bad depth %u, bpp %u.\n", par->depth, par->bpp);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int vmw_fb_check_var(struct fb_var_screeninfo *var,
+			    struct fb_info *info)
+{
+	int depth = var->bits_per_pixel;
+	struct vmw_fb_par *par = info->par;
+	struct vmw_private *vmw_priv = par->vmw_priv;
+
+	switch (var->bits_per_pixel) {
+	case 32:
+		depth = (var->transp.length > 0) ? 32 : 24;
+		break;
+	default:
+		DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	switch (depth) {
+	case 24:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 0;
+		var->transp.offset = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		var->transp.length = 8;
+		var->transp.offset = 24;
+		break;
+	default:
+		DRM_ERROR("Bad depth %u.\n", depth);
+		return -EINVAL;
+	}
+
+	/* without multimon its hard to resize */
+	if (!(vmw_priv->capabilities & SVGA_CAP_MULTIMON) &&
+	    (var->xres != par->max_width ||
+	     var->yres != par->max_height)) {
+		DRM_ERROR("Tried to resize, but we don't have multimon\n");
+		return -EINVAL;
+	}
+
+	if (var->xres > par->max_width ||
+	    var->yres > par->max_height) {
+		DRM_ERROR("Requested geom can not fit in framebuffer\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vmw_fb_set_par(struct fb_info *info)
+{
+	struct vmw_fb_par *par = info->par;
+	struct vmw_private *vmw_priv = par->vmw_priv;
+
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		vmw_write(vmw_priv, SVGA_REG_ENABLE, 1);
+		vmw_write(vmw_priv, SVGA_REG_WIDTH, par->max_width);
+		vmw_write(vmw_priv, SVGA_REG_HEIGHT, par->max_height);
+		vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, par->bpp);
+		vmw_write(vmw_priv, SVGA_REG_DEPTH, par->depth);
+		vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+		vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+		vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+
+		/* TODO check if pitch and offset changes */
+
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, info->var.xoffset);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, info->var.yoffset);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, info->var.xres);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, info->var.yres);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	} else {
+		vmw_write(vmw_priv, SVGA_REG_WIDTH, info->var.xres);
+		vmw_write(vmw_priv, SVGA_REG_HEIGHT, info->var.yres);
+
+		/* TODO check if pitch and offset changes */
+	}
+
+	return 0;
+}
+
+static int vmw_fb_pan_display(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	return 0;
+}
+
+static int vmw_fb_blank(int blank, struct fb_info *info)
+{
+	return 0;
+}
+
+/*
+ * Dirty code
+ */
+
+static void vmw_fb_dirty_flush(struct vmw_fb_par *par)
+{
+	struct vmw_private *vmw_priv = par->vmw_priv;
+	struct fb_info *info = vmw_priv->fb_info;
+	int stride = (info->fix.line_length / 4);
+	int *src = (int *)info->screen_base;
+	__le32 __iomem *vram_mem = par->bo_ptr;
+	unsigned long flags;
+	unsigned x, y, w, h;
+	int i, k;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdUpdate body;
+	} *cmd;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	if (!par->dirty.active) {
+		spin_unlock_irqrestore(&par->dirty.lock, flags);
+		return;
+	}
+	x = par->dirty.x1;
+	y = par->dirty.y1;
+	w = min(par->dirty.x2, info->var.xres) - x;
+	h = min(par->dirty.y2, info->var.yres) - y;
+	par->dirty.x1 = par->dirty.x2 = 0;
+	par->dirty.y1 = par->dirty.y2 = 0;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+	for (i = y * stride; i < info->fix.smem_len / 4; i += stride) {
+		for (k = i+x; k < i+x+w && k < info->fix.smem_len / 4; k++)
+			iowrite32(src[k], vram_mem + k);
+	}
+
+#if 0
+	DRM_INFO("%s, (%u, %u) (%ux%u)\n", __func__, x, y, w, h);
+#endif
+
+	cmd = vmw_fifo_reserve(vmw_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return;
+	}
+
+	cmd->header = cpu_to_le32(SVGA_CMD_UPDATE);
+	cmd->body.x = cpu_to_le32(x);
+	cmd->body.y = cpu_to_le32(y);
+	cmd->body.width = cpu_to_le32(w);
+	cmd->body.height = cpu_to_le32(h);
+	vmw_fifo_commit(vmw_priv, sizeof(*cmd));
+}
+
+static void vmw_fb_dirty_mark(struct vmw_fb_par *par,
+			      unsigned x1, unsigned y1,
+			      unsigned width, unsigned height)
+{
+	struct fb_info *info = par->vmw_priv->fb_info;
+	unsigned long flags;
+	unsigned x2 = x1 + width;
+	unsigned y2 = y1 + height;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	if (par->dirty.x1 == par->dirty.x2) {
+		par->dirty.x1 = x1;
+		par->dirty.y1 = y1;
+		par->dirty.x2 = x2;
+		par->dirty.y2 = y2;
+		/* if we are active start the dirty work
+		 * we share the work with the defio system */
+		if (par->dirty.active)
+			schedule_delayed_work(&info->deferred_work, VMW_DIRTY_DELAY);
+	} else {
+		if (x1 < par->dirty.x1)
+			par->dirty.x1 = x1;
+		if (y1 < par->dirty.y1)
+			par->dirty.y1 = y1;
+		if (x2 > par->dirty.x2)
+			par->dirty.x2 = x2;
+		if (y2 > par->dirty.y2)
+			par->dirty.y2 = y2;
+	}
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+}
+
+static void vmw_deferred_io(struct fb_info *info,
+			    struct list_head *pagelist)
+{
+	struct vmw_fb_par *par = info->par;
+	unsigned long start, end, min, max;
+	unsigned long flags;
+	struct page *page;
+	int y1, y2;
+
+	min = ULONG_MAX;
+	max = 0;
+	list_for_each_entry(page, pagelist, lru) {
+		start = page->index << PAGE_SHIFT;
+		end = start + PAGE_SIZE - 1;
+		min = min(min, start);
+		max = max(max, end);
+	}
+
+	if (min < max) {
+		y1 = min / info->fix.line_length;
+		y2 = (max / info->fix.line_length) + 1;
+
+		spin_lock_irqsave(&par->dirty.lock, flags);
+		par->dirty.x1 = 0;
+		par->dirty.y1 = y1;
+		par->dirty.x2 = info->var.xres;
+		par->dirty.y2 = y2;
+		spin_unlock_irqrestore(&par->dirty.lock, flags);
+	}
+
+	vmw_fb_dirty_flush(par);
+};
+
+struct fb_deferred_io vmw_defio = {
+	.delay		= VMW_DIRTY_DELAY,
+	.deferred_io	= vmw_deferred_io,
+};
+
+/*
+ * Draw code
+ */
+
+static void vmw_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	cfb_fillrect(info, rect);
+	vmw_fb_dirty_mark(info->par, rect->dx, rect->dy,
+			  rect->width, rect->height);
+}
+
+static void vmw_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	cfb_copyarea(info, region);
+	vmw_fb_dirty_mark(info->par, region->dx, region->dy,
+			  region->width, region->height);
+}
+
+static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	cfb_imageblit(info, image);
+	vmw_fb_dirty_mark(info->par, image->dx, image->dy,
+			  image->width, image->height);
+}
+
+/*
+ * Bring up code
+ */
+
+static struct fb_ops vmw_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = vmw_fb_check_var,
+	.fb_set_par = vmw_fb_set_par,
+	.fb_setcolreg = vmw_fb_setcolreg,
+	.fb_fillrect = vmw_fb_fillrect,
+	.fb_copyarea = vmw_fb_copyarea,
+	.fb_imageblit = vmw_fb_imageblit,
+	.fb_pan_display = vmw_fb_pan_display,
+	.fb_blank = vmw_fb_blank,
+};
+
+static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
+			    size_t size, struct vmw_dma_buffer **out)
+{
+	struct vmw_dma_buffer *vmw_bo;
+	struct ttm_placement ne_placement = vmw_vram_ne_placement;
+	int ret;
+
+	ne_placement.lpfn = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	/* interuptable? */
+	ret = ttm_write_lock(&vmw_priv->fbdev_master.lock, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	vmw_bo = kmalloc(sizeof(*vmw_bo), GFP_KERNEL);
+	if (!vmw_bo)
+		goto err_unlock;
+
+	ret = vmw_dmabuf_init(vmw_priv, vmw_bo, size,
+			      &ne_placement,
+			      false,
+			      &vmw_dmabuf_bo_free);
+	if (unlikely(ret != 0))
+		goto err_unlock; /* init frees the buffer on failure */
+
+	*out = vmw_bo;
+
+	ttm_write_unlock(&vmw_priv->fbdev_master.lock);
+
+	return 0;
+
+err_unlock:
+	ttm_write_unlock(&vmw_priv->fbdev_master.lock);
+	return ret;
+}
+
+int vmw_fb_init(struct vmw_private *vmw_priv)
+{
+	struct device *device = &vmw_priv->dev->pdev->dev;
+	struct vmw_fb_par *par;
+	struct fb_info *info;
+	unsigned initial_width, initial_height;
+	unsigned fb_width, fb_height;
+	unsigned fb_bbp, fb_depth, fb_offset, fb_pitch, fb_size;
+	int ret;
+
+	initial_width = 800;
+	initial_height = 600;
+
+	fb_bbp = 32;
+	fb_depth = 24;
+
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
+		fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
+	} else {
+		fb_width = min(vmw_priv->fb_max_width, initial_width);
+		fb_height = min(vmw_priv->fb_max_height, initial_height);
+	}
+
+	initial_width = min(fb_width, initial_width);
+	initial_height = min(fb_height, initial_height);
+
+	vmw_write(vmw_priv, SVGA_REG_WIDTH, fb_width);
+	vmw_write(vmw_priv, SVGA_REG_HEIGHT, fb_height);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, fb_bbp);
+	vmw_write(vmw_priv, SVGA_REG_DEPTH, fb_depth);
+	vmw_write(vmw_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+
+	fb_size = vmw_read(vmw_priv, SVGA_REG_FB_SIZE);
+	fb_offset = vmw_read(vmw_priv, SVGA_REG_FB_OFFSET);
+	fb_pitch = vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE);
+
+	DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_WIDTH));
+	DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_MAX_HEIGHT));
+	DRM_DEBUG("width  %u\n", vmw_read(vmw_priv, SVGA_REG_WIDTH));
+	DRM_DEBUG("height %u\n", vmw_read(vmw_priv, SVGA_REG_HEIGHT));
+	DRM_DEBUG("bpp    %u\n", vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL));
+	DRM_DEBUG("depth  %u\n", vmw_read(vmw_priv, SVGA_REG_DEPTH));
+	DRM_DEBUG("bpl    %u\n", vmw_read(vmw_priv, SVGA_REG_BYTES_PER_LINE));
+	DRM_DEBUG("r mask %08x\n", vmw_read(vmw_priv, SVGA_REG_RED_MASK));
+	DRM_DEBUG("g mask %08x\n", vmw_read(vmw_priv, SVGA_REG_GREEN_MASK));
+	DRM_DEBUG("b mask %08x\n", vmw_read(vmw_priv, SVGA_REG_BLUE_MASK));
+	DRM_DEBUG("fb_offset 0x%08x\n", fb_offset);
+	DRM_DEBUG("fb_pitch  %u\n", fb_pitch);
+	DRM_DEBUG("fb_size   %u kiB\n", fb_size / 1024);
+
+	info = framebuffer_alloc(sizeof(*par), device);
+	if (!info)
+		return -ENOMEM;
+
+	/*
+	 * Par
+	 */
+	vmw_priv->fb_info = info;
+	par = info->par;
+	par->vmw_priv = vmw_priv;
+	par->depth = fb_depth;
+	par->bpp = fb_bbp;
+	par->vmalloc = NULL;
+	par->max_width = fb_width;
+	par->max_height = fb_height;
+
+	/*
+	 * Create buffers and alloc memory
+	 */
+	par->vmalloc = vmalloc(fb_size);
+	if (unlikely(par->vmalloc == NULL)) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	ret = vmw_fb_create_bo(vmw_priv, fb_size, &par->vmw_bo);
+	if (unlikely(ret != 0))
+		goto err_free;
+
+	ret = ttm_bo_kmap(&par->vmw_bo->base,
+			  0,
+			  par->vmw_bo->base.num_pages,
+			  &par->map);
+	if (unlikely(ret != 0))
+		goto err_unref;
+	par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
+	par->bo_size = fb_size;
+
+	/*
+	 * Fixed and var
+	 */
+	strcpy(info->fix.id, "svgadrmfb");
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = FB_VISUAL_TRUECOLOR;
+	info->fix.type_aux = 0;
+	info->fix.xpanstep = 1; /* doing it in hw */
+	info->fix.ypanstep = 1; /* doing it in hw */
+	info->fix.ywrapstep = 0;
+	info->fix.accel = FB_ACCEL_NONE;
+	info->fix.line_length = fb_pitch;
+
+	info->fix.smem_start = 0;
+	info->fix.smem_len = fb_size;
+
+	info->fix.mmio_start = 0;
+	info->fix.mmio_len = 0;
+
+	info->pseudo_palette = par->pseudo_palette;
+	info->screen_base = par->vmalloc;
+	info->screen_size = fb_size;
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &vmw_fb_ops;
+
+	/* 24 depth per default */
+	info->var.red.offset = 16;
+	info->var.green.offset = 8;
+	info->var.blue.offset = 0;
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
+	info->var.transp.offset = 0;
+	info->var.transp.length = 0;
+
+	info->var.xres_virtual = fb_width;
+	info->var.yres_virtual = fb_height;
+	info->var.bits_per_pixel = par->bpp;
+	info->var.xoffset = 0;
+	info->var.yoffset = 0;
+	info->var.activate = FB_ACTIVATE_NOW;
+	info->var.height = -1;
+	info->var.width = -1;
+
+	info->var.xres = initial_width;
+	info->var.yres = initial_height;
+
+#if 0
+	info->pixmap.size = 64*1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+#else
+	info->pixmap.size = 0;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+#endif
+
+	/*
+	 * Dirty & Deferred IO
+	 */
+	par->dirty.x1 = par->dirty.x2 = 0;
+	par->dirty.y1 = par->dirty.y1 = 0;
+	par->dirty.active = true;
+	spin_lock_init(&par->dirty.lock);
+	info->fbdefio = &vmw_defio;
+	fb_deferred_io_init(info);
+
+	ret = register_framebuffer(info);
+	if (unlikely(ret != 0))
+		goto err_defio;
+
+	return 0;
+
+err_defio:
+	fb_deferred_io_cleanup(info);
+	ttm_bo_kunmap(&par->map);
+err_unref:
+	ttm_bo_unref((struct ttm_buffer_object **)&par->vmw_bo);
+err_free:
+	vfree(par->vmalloc);
+	framebuffer_release(info);
+	vmw_priv->fb_info = NULL;
+
+	return ret;
+}
+
+int vmw_fb_close(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	struct ttm_buffer_object *bo;
+
+	if (!vmw_priv->fb_info)
+		return 0;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+	bo = &par->vmw_bo->base;
+	par->vmw_bo = NULL;
+
+	/* ??? order */
+	fb_deferred_io_cleanup(info);
+	unregister_framebuffer(info);
+
+	ttm_bo_kunmap(&par->map);
+	ttm_bo_unref(&bo);
+
+	vfree(par->vmalloc);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv,
+			 struct vmw_dma_buffer *vmw_bo)
+{
+	struct ttm_buffer_object *bo = &vmw_bo->base;
+	int ret = 0;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false);
+	ttm_bo_unreserve(bo);
+
+	return ret;
+}
+
+int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv,
+				struct vmw_dma_buffer *vmw_bo)
+{
+	struct ttm_buffer_object *bo = &vmw_bo->base;
+	struct ttm_placement ne_placement = vmw_vram_ne_placement;
+	int ret = 0;
+
+	ne_placement.lpfn = bo->num_pages;
+
+	/* interuptable? */
+	ret = ttm_write_lock(&vmw_priv->active_master->lock, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_reserve(bo, false, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err_unlock;
+
+	if (vmw_bo->gmr_bound) {
+		vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id);
+		spin_lock(&bo->glob->lru_lock);
+		ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id);
+		spin_unlock(&bo->glob->lru_lock);
+		vmw_bo->gmr_bound = NULL;
+	}
+
+	ret = ttm_bo_validate(bo, &ne_placement, false, false);
+	ttm_bo_unreserve(bo);
+err_unlock:
+	ttm_write_unlock(&vmw_priv->active_master->lock);
+
+	return ret;
+}
+
+int vmw_fb_off(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	unsigned long flags;
+
+	if (!vmw_priv->fb_info)
+		return -EINVAL;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	par->dirty.active = false;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+	flush_scheduled_work();
+
+	par->bo_ptr = NULL;
+	ttm_bo_kunmap(&par->map);
+
+	vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo);
+
+	return 0;
+}
+
+int vmw_fb_on(struct vmw_private *vmw_priv)
+{
+	struct fb_info *info;
+	struct vmw_fb_par *par;
+	unsigned long flags;
+	bool dummy;
+	int ret;
+
+	if (!vmw_priv->fb_info)
+		return -EINVAL;
+
+	info = vmw_priv->fb_info;
+	par = info->par;
+
+	/* we are already active */
+	if (par->bo_ptr != NULL)
+		return 0;
+
+	/* Make sure that all overlays are stoped when we take over */
+	vmw_overlay_stop_all(vmw_priv);
+
+	ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("could not move buffer to start of VRAM\n");
+		goto err_no_buffer;
+	}
+
+	ret = ttm_bo_kmap(&par->vmw_bo->base,
+			  0,
+			  par->vmw_bo->base.num_pages,
+			  &par->map);
+	BUG_ON(ret != 0);
+	par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &dummy);
+
+	spin_lock_irqsave(&par->dirty.lock, flags);
+	par->dirty.active = true;
+	spin_unlock_irqrestore(&par->dirty.lock, flags);
+
+err_no_buffer:
+	vmw_fb_set_par(info);
+
+	vmw_fb_dirty_mark(par, 0, 0, info->var.xres, info->var.yres);
+
+	/* If there already was stuff dirty we wont
+	 * schedule a new work, so lets do it now */
+	schedule_delayed_work(&info->deferred_work, 0);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
new file mode 100644
index 0000000..76b0693
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
@@ -0,0 +1,521 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "drmP.h"
+#include "ttm/ttm_placement.h"
+
+int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max;
+	uint32_t min;
+	uint32_t dummy;
+	int ret;
+
+	fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
+	fifo->static_buffer = vmalloc(fifo->static_buffer_size);
+	if (unlikely(fifo->static_buffer == NULL))
+		return -ENOMEM;
+
+	fifo->last_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
+	fifo->last_data_size = 0;
+	fifo->last_buffer_add = false;
+	fifo->last_buffer = vmalloc(fifo->last_buffer_size);
+	if (unlikely(fifo->last_buffer == NULL)) {
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	fifo->dynamic_buffer = NULL;
+	fifo->reserved_size = 0;
+	fifo->using_bounce_buffer = false;
+
+	init_rwsem(&fifo->rwsem);
+
+	/*
+	 * Allow mapping the first page read-only to user-space.
+	 */
+
+	DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
+	DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
+	DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
+
+	mutex_lock(&dev_priv->hw_mutex);
+	dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
+	dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
+	vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+
+	min = 4;
+	if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
+		min = vmw_read(dev_priv, SVGA_REG_MEM_REGS);
+	min <<= 2;
+
+	if (min < PAGE_SIZE)
+		min = PAGE_SIZE;
+
+	iowrite32(min, fifo_mem + SVGA_FIFO_MIN);
+	iowrite32(dev_priv->mmio_size, fifo_mem + SVGA_FIFO_MAX);
+	wmb();
+	iowrite32(min,  fifo_mem + SVGA_FIFO_NEXT_CMD);
+	iowrite32(min,  fifo_mem + SVGA_FIFO_STOP);
+	iowrite32(0, fifo_mem + SVGA_FIFO_BUSY);
+	mb();
+
+	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	min = ioread32(fifo_mem  + SVGA_FIFO_MIN);
+	fifo->capabilities = ioread32(fifo_mem + SVGA_FIFO_CAPABILITIES);
+
+	DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
+		 (unsigned int) max,
+		 (unsigned int) min,
+		 (unsigned int) fifo->capabilities);
+
+	dev_priv->fence_seq = (uint32_t) -100;
+	dev_priv->last_read_sequence = (uint32_t) -100;
+	iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE);
+
+	return vmw_fifo_send_fence(dev_priv, &dummy);
+out_err:
+	vfree(fifo->static_buffer);
+	fifo->static_buffer = NULL;
+	return ret;
+}
+
+void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) {
+		iowrite32(1, fifo_mem + SVGA_FIFO_BUSY);
+		vmw_write(dev_priv, SVGA_REG_SYNC, reason);
+	}
+
+	mutex_unlock(&dev_priv->hw_mutex);
+}
+
+void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
+		vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+
+	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+
+	vmw_write(dev_priv, SVGA_REG_CONFIG_DONE,
+		  dev_priv->config_done_state);
+	vmw_write(dev_priv, SVGA_REG_ENABLE,
+		  dev_priv->enable_state);
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (likely(fifo->last_buffer != NULL)) {
+		vfree(fifo->last_buffer);
+		fifo->last_buffer = NULL;
+	}
+
+	if (likely(fifo->static_buffer != NULL)) {
+		vfree(fifo->static_buffer);
+		fifo->static_buffer = NULL;
+	}
+
+	if (likely(fifo->dynamic_buffer != NULL)) {
+		vfree(fifo->dynamic_buffer);
+		fifo->dynamic_buffer = NULL;
+	}
+}
+
+static bool vmw_fifo_is_full(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+
+	return ((max - next_cmd) + (stop - min) <= bytes);
+}
+
+static int vmw_fifo_wait_noirq(struct vmw_private *dev_priv,
+			       uint32_t bytes, bool interruptible,
+			       unsigned long timeout)
+{
+	int ret = 0;
+	unsigned long end_jiffies = jiffies + timeout;
+	DEFINE_WAIT(__wait);
+
+	DRM_INFO("Fifo wait noirq.\n");
+
+	for (;;) {
+		prepare_to_wait(&dev_priv->fifo_queue, &__wait,
+				(interruptible) ?
+				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		if (!vmw_fifo_is_full(dev_priv, bytes))
+			break;
+		if (time_after_eq(jiffies, end_jiffies)) {
+			ret = -EBUSY;
+			DRM_ERROR("SVGA device lockup.\n");
+			break;
+		}
+		schedule_timeout(1);
+		if (interruptible && signal_pending(current)) {
+			ret = -ERESTART;
+			break;
+		}
+	}
+	finish_wait(&dev_priv->fifo_queue, &__wait);
+	wake_up_all(&dev_priv->fifo_queue);
+	DRM_INFO("Fifo noirq exit.\n");
+	return ret;
+}
+
+static int vmw_fifo_wait(struct vmw_private *dev_priv,
+			 uint32_t bytes, bool interruptible,
+			 unsigned long timeout)
+{
+	long ret = 1L;
+	unsigned long irq_flags;
+
+	if (likely(!vmw_fifo_is_full(dev_priv, bytes)))
+		return 0;
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_FIFOFULL);
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return vmw_fifo_wait_noirq(dev_priv, bytes,
+					   interruptible, timeout);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_FIFO_PROGRESS,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
+			  SVGA_IRQFLAG_FIFO_PROGRESS);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+		    (dev_priv->fifo_queue,
+		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+	else
+		ret = wait_event_timeout
+		    (dev_priv->fifo_queue,
+		     !vmw_fifo_is_full(dev_priv, bytes), timeout);
+
+	if (unlikely(ret == -ERESTARTSYS))
+		ret = -ERESTART;
+	else if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
+			  ~SVGA_IRQFLAG_FIFO_PROGRESS);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ret;
+}
+
+void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t max;
+	uint32_t min;
+	uint32_t next_cmd;
+	uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
+	int ret;
+
+	down_write(&fifo_state->rwsem);
+	max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+
+	if (unlikely(bytes >= (max - min)))
+		goto out_err;
+
+	BUG_ON(fifo_state->reserved_size != 0);
+	BUG_ON(fifo_state->dynamic_buffer != NULL);
+
+	fifo_state->reserved_size = bytes;
+
+	while (1) {
+		uint32_t stop = ioread32(fifo_mem + SVGA_FIFO_STOP);
+		bool need_bounce = false;
+		bool reserve_in_place = false;
+
+		if (next_cmd >= stop) {
+			if (likely((next_cmd + bytes < max ||
+				    (next_cmd + bytes == max && stop > min))))
+				reserve_in_place = true;
+
+			else if (vmw_fifo_is_full(dev_priv, bytes)) {
+				ret = vmw_fifo_wait(dev_priv, bytes,
+						    false, 3 * HZ);
+				if (unlikely(ret != 0))
+					goto out_err;
+			} else
+				need_bounce = true;
+
+		} else {
+
+			if (likely((next_cmd + bytes < stop)))
+				reserve_in_place = true;
+			else {
+				ret = vmw_fifo_wait(dev_priv, bytes,
+						    false, 3 * HZ);
+				if (unlikely(ret != 0))
+					goto out_err;
+			}
+		}
+
+		if (reserve_in_place) {
+			if (reserveable || bytes <= sizeof(uint32_t)) {
+				fifo_state->using_bounce_buffer = false;
+
+				if (reserveable)
+					iowrite32(bytes, fifo_mem +
+						  SVGA_FIFO_RESERVED);
+				return fifo_mem + (next_cmd >> 2);
+			} else {
+				need_bounce = true;
+			}
+		}
+
+		if (need_bounce) {
+			fifo_state->using_bounce_buffer = true;
+			if (bytes < fifo_state->static_buffer_size)
+				return fifo_state->static_buffer;
+			else {
+				fifo_state->dynamic_buffer = vmalloc(bytes);
+				return fifo_state->dynamic_buffer;
+			}
+		}
+	}
+out_err:
+	fifo_state->reserved_size = 0;
+	up_write(&fifo_state->rwsem);
+	return NULL;
+}
+
+static void vmw_fifo_res_copy(struct vmw_fifo_state *fifo_state,
+			      __le32 __iomem *fifo_mem,
+			      uint32_t next_cmd,
+			      uint32_t max, uint32_t min, uint32_t bytes)
+{
+	uint32_t chunk_size = max - next_cmd;
+	uint32_t rest;
+	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
+	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
+
+	if (bytes < chunk_size)
+		chunk_size = bytes;
+
+	iowrite32(bytes, fifo_mem + SVGA_FIFO_RESERVED);
+	mb();
+	memcpy_toio(fifo_mem + (next_cmd >> 2), buffer, chunk_size);
+	rest = bytes - chunk_size;
+	if (rest)
+		memcpy_toio(fifo_mem + (min >> 2), buffer + (chunk_size >> 2),
+			    rest);
+}
+
+static void vmw_fifo_slow_copy(struct vmw_fifo_state *fifo_state,
+			       __le32 __iomem *fifo_mem,
+			       uint32_t next_cmd,
+			       uint32_t max, uint32_t min, uint32_t bytes)
+{
+	uint32_t *buffer = (fifo_state->dynamic_buffer != NULL) ?
+	    fifo_state->dynamic_buffer : fifo_state->static_buffer;
+
+	while (bytes > 0) {
+		iowrite32(*buffer++, fifo_mem + (next_cmd >> 2));
+		next_cmd += sizeof(uint32_t);
+		if (unlikely(next_cmd == max))
+			next_cmd = min;
+		mb();
+		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+		mb();
+		bytes -= sizeof(uint32_t);
+	}
+}
+
+void vmw_fifo_commit(struct vmw_private *dev_priv, uint32_t bytes)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t next_cmd = ioread32(fifo_mem + SVGA_FIFO_NEXT_CMD);
+	uint32_t max = ioread32(fifo_mem + SVGA_FIFO_MAX);
+	uint32_t min = ioread32(fifo_mem + SVGA_FIFO_MIN);
+	bool reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE;
+
+	BUG_ON((bytes & 3) != 0);
+	BUG_ON(bytes > fifo_state->reserved_size);
+
+	fifo_state->reserved_size = 0;
+
+	if (fifo_state->using_bounce_buffer) {
+		if (reserveable)
+			vmw_fifo_res_copy(fifo_state, fifo_mem,
+					  next_cmd, max, min, bytes);
+		else
+			vmw_fifo_slow_copy(fifo_state, fifo_mem,
+					   next_cmd, max, min, bytes);
+
+		if (fifo_state->dynamic_buffer) {
+			vfree(fifo_state->dynamic_buffer);
+			fifo_state->dynamic_buffer = NULL;
+		}
+
+	}
+
+	if (fifo_state->using_bounce_buffer || reserveable) {
+		next_cmd += bytes;
+		if (next_cmd >= max)
+			next_cmd -= max - min;
+		mb();
+		iowrite32(next_cmd, fifo_mem + SVGA_FIFO_NEXT_CMD);
+	}
+
+	if (reserveable)
+		iowrite32(0, fifo_mem + SVGA_FIFO_RESERVED);
+	mb();
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+	up_write(&fifo_state->rwsem);
+}
+
+int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *sequence)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	struct svga_fifo_cmd_fence *cmd_fence;
+	void *fm;
+	int ret = 0;
+	uint32_t bytes = sizeof(__le32) + sizeof(*cmd_fence);
+
+	fm = vmw_fifo_reserve(dev_priv, bytes);
+	if (unlikely(fm == NULL)) {
+		down_write(&fifo_state->rwsem);
+		*sequence = dev_priv->fence_seq;
+		up_write(&fifo_state->rwsem);
+		ret = -ENOMEM;
+		(void)vmw_fallback_wait(dev_priv, false, true, *sequence,
+					false, 3*HZ);
+		goto out_err;
+	}
+
+	do {
+		*sequence = dev_priv->fence_seq++;
+	} while (*sequence == 0);
+
+	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE)) {
+
+		/*
+		 * Don't request hardware to send a fence. The
+		 * waiting code in vmwgfx_irq.c will emulate this.
+		 */
+
+		vmw_fifo_commit(dev_priv, 0);
+		return 0;
+	}
+
+	*(__le32 *) fm = cpu_to_le32(SVGA_CMD_FENCE);
+	cmd_fence = (struct svga_fifo_cmd_fence *)
+	    ((unsigned long)fm + sizeof(__le32));
+
+	iowrite32(*sequence, &cmd_fence->fence);
+	fifo_state->last_buffer_add = true;
+	vmw_fifo_commit(dev_priv, bytes);
+	fifo_state->last_buffer_add = false;
+
+out_err:
+	return ret;
+}
+
+/**
+ * Map the first page of the FIFO read-only to user-space.
+ */
+
+static int vmw_fifo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int ret;
+	unsigned long address = (unsigned long)vmf->virtual_address;
+
+	if (address != vma->vm_start)
+		return VM_FAULT_SIGBUS;
+
+	ret = vm_insert_pfn(vma, address, vma->vm_pgoff);
+	if (likely(ret == -EBUSY || ret == 0))
+		return VM_FAULT_NOPAGE;
+	else if (ret == -ENOMEM)
+		return VM_FAULT_OOM;
+
+	return VM_FAULT_SIGBUS;
+}
+
+static struct vm_operations_struct vmw_fifo_vm_ops = {
+	.fault = vmw_fifo_vm_fault,
+	.open = NULL,
+	.close = NULL
+};
+
+int vmw_fifo_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct vmw_private *dev_priv;
+
+	file_priv = (struct drm_file *)filp->private_data;
+	dev_priv = vmw_priv(file_priv->minor->dev);
+
+	if (vma->vm_pgoff != (dev_priv->mmio_start >> PAGE_SHIFT) ||
+	    (vma->vm_end - vma->vm_start) != PAGE_SIZE)
+		return -EINVAL;
+
+	vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
+	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_SHARED;
+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+	vma->vm_page_prot = ttm_io_prot(TTM_PL_FLAG_UNCACHED,
+					vma->vm_page_prot);
+	vma->vm_ops = &vmw_fifo_vm_ops;
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
new file mode 100644
index 0000000..5f8908a
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
@@ -0,0 +1,213 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "drmP.h"
+#include "ttm/ttm_bo_driver.h"
+
+/**
+ * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
+ * the number of used descriptors.
+ */
+
+static int vmw_gmr_build_descriptors(struct list_head *desc_pages,
+				     struct page *pages[],
+				     unsigned long num_pages)
+{
+	struct page *page, *next;
+	struct svga_guest_mem_descriptor *page_virtual = NULL;
+	struct svga_guest_mem_descriptor *desc_virtual = NULL;
+	unsigned int desc_per_page;
+	unsigned long prev_pfn;
+	unsigned long pfn;
+	int ret;
+
+	desc_per_page = PAGE_SIZE /
+	    sizeof(struct svga_guest_mem_descriptor) - 1;
+
+	while (likely(num_pages != 0)) {
+		page = alloc_page(__GFP_HIGHMEM);
+		if (unlikely(page == NULL)) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
+
+		list_add_tail(&page->lru, desc_pages);
+
+		/*
+		 * Point previous page terminating descriptor to this
+		 * page before unmapping it.
+		 */
+
+		if (likely(page_virtual != NULL)) {
+			desc_virtual->ppn = page_to_pfn(page);
+			kunmap_atomic(page_virtual, KM_USER0);
+		}
+
+		page_virtual = kmap_atomic(page, KM_USER0);
+		desc_virtual = page_virtual - 1;
+		prev_pfn = ~(0UL);
+
+		while (likely(num_pages != 0)) {
+			pfn = page_to_pfn(*pages);
+
+			if (pfn != prev_pfn + 1) {
+
+				if (desc_virtual - page_virtual ==
+				    desc_per_page - 1)
+					break;
+
+				(++desc_virtual)->ppn = cpu_to_le32(pfn);
+				desc_virtual->num_pages = cpu_to_le32(1);
+			} else {
+				uint32_t tmp =
+				    le32_to_cpu(desc_virtual->num_pages);
+				desc_virtual->num_pages = cpu_to_le32(tmp + 1);
+			}
+			prev_pfn = pfn;
+			--num_pages;
+			++pages;
+		}
+
+		(++desc_virtual)->ppn = cpu_to_le32(0);
+		desc_virtual->num_pages = cpu_to_le32(0);
+	}
+
+	if (likely(page_virtual != NULL))
+		kunmap_atomic(page_virtual, KM_USER0);
+
+	return 0;
+out_err:
+	list_for_each_entry_safe(page, next, desc_pages, lru) {
+		list_del_init(&page->lru);
+		__free_page(page);
+	}
+	return ret;
+}
+
+static inline void vmw_gmr_free_descriptors(struct list_head *desc_pages)
+{
+	struct page *page, *next;
+
+	list_for_each_entry_safe(page, next, desc_pages, lru) {
+		list_del_init(&page->lru);
+		__free_page(page);
+	}
+}
+
+static void vmw_gmr_fire_descriptors(struct vmw_private *dev_priv,
+				     int gmr_id, struct list_head *desc_pages)
+{
+	struct page *page;
+
+	if (unlikely(list_empty(desc_pages)))
+		return;
+
+	page = list_entry(desc_pages->next, struct page, lru);
+
+	mutex_lock(&dev_priv->hw_mutex);
+
+	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
+	wmb();
+	vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, page_to_pfn(page));
+	mb();
+
+	mutex_unlock(&dev_priv->hw_mutex);
+
+}
+
+/**
+ * FIXME: Adjust to the ttm lowmem / highmem storage to minimize
+ * the number of used descriptors.
+ */
+
+static unsigned long vmw_gmr_count_descriptors(struct page *pages[],
+					       unsigned long num_pages)
+{
+	unsigned long prev_pfn = ~(0UL);
+	unsigned long pfn;
+	unsigned long descriptors = 0;
+
+	while (num_pages--) {
+		pfn = page_to_pfn(*pages++);
+		if (prev_pfn + 1 != pfn)
+			++descriptors;
+		prev_pfn = pfn;
+	}
+
+	return descriptors;
+}
+
+int vmw_gmr_bind(struct vmw_private *dev_priv,
+		 struct ttm_buffer_object *bo)
+{
+	struct ttm_tt *ttm = bo->ttm;
+	unsigned long descriptors;
+	int ret;
+	uint32_t id;
+	struct list_head desc_pages;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_GMR))
+		return -EINVAL;
+
+	ret = ttm_tt_populate(ttm);
+	if (unlikely(ret != 0))
+		return ret;
+
+	descriptors = vmw_gmr_count_descriptors(ttm->pages, ttm->num_pages);
+	if (unlikely(descriptors > dev_priv->max_gmr_descriptors))
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&desc_pages);
+	ret = vmw_gmr_build_descriptors(&desc_pages, ttm->pages,
+					ttm->num_pages);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = vmw_gmr_id_alloc(dev_priv, &id);
+	if (unlikely(ret != 0))
+		goto out_no_id;
+
+	vmw_gmr_fire_descriptors(dev_priv, id, &desc_pages);
+	vmw_gmr_free_descriptors(&desc_pages);
+	vmw_dmabuf_set_gmr(bo, id);
+	return 0;
+
+out_no_id:
+	vmw_gmr_free_descriptors(&desc_pages);
+	return ret;
+}
+
+void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
+{
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id);
+	wmb();
+	vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0);
+	mb();
+	mutex_unlock(&dev_priv->hw_mutex);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
new file mode 100644
index 0000000..5fa6a4e
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_drm.h"
+
+int vmw_getparam_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct drm_vmw_getparam_arg *param =
+	    (struct drm_vmw_getparam_arg *)data;
+
+	switch (param->param) {
+	case DRM_VMW_PARAM_NUM_STREAMS:
+		param->value = vmw_overlay_num_overlays(dev_priv);
+		break;
+	case DRM_VMW_PARAM_NUM_FREE_STREAMS:
+		param->value = vmw_overlay_num_free_overlays(dev_priv);
+		break;
+	case DRM_VMW_PARAM_3D:
+		param->value = dev_priv->capabilities & SVGA_CAP_3D ? 1 : 0;
+		break;
+	case DRM_VMW_PARAM_FIFO_OFFSET:
+		param->value = dev_priv->mmio_start;
+		break;
+	default:
+		DRM_ERROR("Illegal vmwgfx get param request: %d\n",
+			  param->param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int vmw_fifo_debug_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+	struct drm_vmw_fifo_debug_arg *arg =
+	    (struct drm_vmw_fifo_debug_arg *)data;
+	__le32 __user *buffer = (__le32 __user *)
+	    (unsigned long)arg->debug_buffer;
+
+	if (unlikely(fifo_state->last_buffer == NULL))
+		return -EINVAL;
+
+	if (arg->debug_buffer_size < fifo_state->last_data_size) {
+		arg->used_size = arg->debug_buffer_size;
+		arg->did_not_fit = 1;
+	} else {
+		arg->used_size = fifo_state->last_data_size;
+		arg->did_not_fit = 0;
+	}
+	return copy_to_user(buffer, fifo_state->last_buffer, arg->used_size);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
new file mode 100644
index 0000000..9e0f030
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c
@@ -0,0 +1,295 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+#define VMW_FENCE_WRAP (1 << 24)
+
+irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *)arg;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	spin_lock(&dev_priv->irq_lock);
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	spin_unlock(&dev_priv->irq_lock);
+
+	if (status & SVGA_IRQFLAG_ANY_FENCE)
+		wake_up_all(&dev_priv->fence_queue);
+	if (status & SVGA_IRQFLAG_FIFO_PROGRESS)
+		wake_up_all(&dev_priv->fifo_queue);
+
+	if (likely(status)) {
+		outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t sequence)
+{
+	uint32_t busy;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	busy = vmw_read(dev_priv, SVGA_REG_BUSY);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return (busy == 0);
+}
+
+
+bool vmw_fence_signaled(struct vmw_private *dev_priv,
+			uint32_t sequence)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	struct vmw_fifo_state *fifo_state;
+	bool ret;
+
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return true;
+
+	dev_priv->last_read_sequence = ioread32(fifo_mem + SVGA_FIFO_FENCE);
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return true;
+
+	fifo_state = &dev_priv->fifo;
+	if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
+	    vmw_fifo_idle(dev_priv, sequence))
+		return true;
+
+	/**
+	 * Below is to signal stale fences that have wrapped.
+	 * First, block fence submission.
+	 */
+
+	down_read(&fifo_state->rwsem);
+
+	/**
+	 * Then check if the sequence is higher than what we've actually
+	 * emitted. Then the fence is stale and signaled.
+	 */
+
+	ret = ((dev_priv->fence_seq - sequence) > VMW_FENCE_WRAP);
+	up_read(&fifo_state->rwsem);
+
+	return ret;
+}
+
+int vmw_fallback_wait(struct vmw_private *dev_priv,
+		      bool lazy,
+		      bool fifo_idle,
+		      uint32_t sequence,
+		      bool interruptible,
+		      unsigned long timeout)
+{
+	struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
+
+	uint32_t count = 0;
+	uint32_t signal_seq;
+	int ret;
+	unsigned long end_jiffies = jiffies + timeout;
+	bool (*wait_condition)(struct vmw_private *, uint32_t);
+	DEFINE_WAIT(__wait);
+
+	wait_condition = (fifo_idle) ? &vmw_fifo_idle :
+		&vmw_fence_signaled;
+
+	/**
+	 * Block command submission while waiting for idle.
+	 */
+
+	if (fifo_idle)
+		down_read(&fifo_state->rwsem);
+	signal_seq = dev_priv->fence_seq;
+	ret = 0;
+
+	for (;;) {
+		prepare_to_wait(&dev_priv->fence_queue, &__wait,
+				(interruptible) ?
+				TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		if (wait_condition(dev_priv, sequence))
+			break;
+		if (time_after_eq(jiffies, end_jiffies)) {
+			DRM_ERROR("SVGA device lockup.\n");
+			break;
+		}
+		if (lazy)
+			schedule_timeout(1);
+		else if ((++count & 0x0F) == 0) {
+			/**
+			 * FIXME: Use schedule_hr_timeout here for
+			 * newer kernels and lower CPU utilization.
+			 */
+
+			__set_current_state(TASK_RUNNING);
+			schedule();
+			__set_current_state((interruptible) ?
+					    TASK_INTERRUPTIBLE :
+					    TASK_UNINTERRUPTIBLE);
+		}
+		if (interruptible && signal_pending(current)) {
+			ret = -ERESTART;
+			break;
+		}
+	}
+	finish_wait(&dev_priv->fence_queue, &__wait);
+	if (ret == 0 && fifo_idle) {
+		__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+		iowrite32(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
+	}
+	wake_up_all(&dev_priv->fence_queue);
+	if (fifo_idle)
+		up_read(&fifo_state->rwsem);
+
+	return ret;
+}
+
+int vmw_wait_fence(struct vmw_private *dev_priv,
+		   bool lazy, uint32_t sequence,
+		   bool interruptible, unsigned long timeout)
+{
+	long ret;
+	unsigned long irq_flags;
+	struct vmw_fifo_state *fifo = &dev_priv->fifo;
+
+	if (likely(dev_priv->last_read_sequence - sequence < VMW_FENCE_WRAP))
+		return 0;
+
+	if (likely(vmw_fence_signaled(dev_priv, sequence)))
+		return 0;
+
+	vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
+
+	if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE))
+		return vmw_fallback_wait(dev_priv, lazy, true, sequence,
+					 interruptible, timeout);
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return vmw_fallback_wait(dev_priv, lazy, false, sequence,
+					 interruptible, timeout);
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_add_return(1, &dev_priv->fence_queue_waiters) > 0) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		outl(SVGA_IRQFLAG_ANY_FENCE,
+		     dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) |
+			  SVGA_IRQFLAG_ANY_FENCE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	if (interruptible)
+		ret = wait_event_interruptible_timeout
+		    (dev_priv->fence_queue,
+		     vmw_fence_signaled(dev_priv, sequence),
+		     timeout);
+	else
+		ret = wait_event_timeout
+		    (dev_priv->fence_queue,
+		     vmw_fence_signaled(dev_priv, sequence),
+		     timeout);
+
+	if (unlikely(ret == -ERESTARTSYS))
+		ret = -ERESTART;
+	else if (unlikely(ret == 0))
+		ret = -EBUSY;
+	else if (likely(ret > 0))
+		ret = 0;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	if (atomic_dec_and_test(&dev_priv->fence_queue_waiters)) {
+		spin_lock_irqsave(&dev_priv->irq_lock, irq_flags);
+		vmw_write(dev_priv, SVGA_REG_IRQMASK,
+			  vmw_read(dev_priv, SVGA_REG_IRQMASK) &
+			  ~SVGA_IRQFLAG_ANY_FENCE);
+		spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags);
+	}
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	return ret;
+}
+
+void vmw_irq_preinstall(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return;
+
+	spin_lock_init(&dev_priv->irq_lock);
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+}
+
+int vmw_irq_postinstall(struct drm_device *dev)
+{
+	return 0;
+}
+
+void vmw_irq_uninstall(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	uint32_t status;
+
+	if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
+		return;
+
+	mutex_lock(&dev_priv->hw_mutex);
+	vmw_write(dev_priv, SVGA_REG_IRQMASK, 0);
+	mutex_unlock(&dev_priv->hw_mutex);
+
+	status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+	outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
+}
+
+#define VMW_FENCE_WAIT_TIMEOUT 3*HZ;
+
+int vmw_fence_wait_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	struct drm_vmw_fence_wait_arg *arg =
+	    (struct drm_vmw_fence_wait_arg *)data;
+	unsigned long timeout;
+
+	if (!arg->cookie_valid) {
+		arg->cookie_valid = 1;
+		arg->kernel_cookie = jiffies + VMW_FENCE_WAIT_TIMEOUT;
+	}
+
+	timeout = jiffies;
+	if (time_after_eq(timeout, (unsigned long)arg->kernel_cookie))
+		return -EBUSY;
+
+	timeout = (unsigned long)arg->kernel_cookie - timeout;
+	return vmw_wait_fence(vmw_priv(dev), true, arg->sequence, true, timeout);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
new file mode 100644
index 0000000..e9403be
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -0,0 +1,872 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_kms.h"
+
+/* Might need a hrtimer here? */
+#define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1)
+
+
+void vmw_display_unit_cleanup(struct vmw_display_unit *du)
+{
+	if (du->cursor_surface)
+		vmw_surface_unreference(&du->cursor_surface);
+	if (du->cursor_dmabuf)
+		vmw_dmabuf_unreference(&du->cursor_dmabuf);
+	drm_crtc_cleanup(&du->crtc);
+	drm_encoder_cleanup(&du->encoder);
+	drm_connector_cleanup(&du->connector);
+}
+
+/*
+ * Display Unit Cursor functions
+ */
+
+int vmw_cursor_update_image(struct vmw_private *dev_priv,
+			    u32 *image, u32 width, u32 height,
+			    u32 hotspotX, u32 hotspotY)
+{
+	struct {
+		u32 cmd;
+		SVGAFifoCmdDefineAlphaCursor cursor;
+	} *cmd;
+	u32 image_size = width * height * 4;
+	u32 cmd_size = sizeof(*cmd) + image_size;
+
+	if (!image)
+		return -EINVAL;
+
+	cmd = vmw_fifo_reserve(dev_priv, cmd_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+
+	memcpy(&cmd[1], image, image_size);
+
+	cmd->cmd = cpu_to_le32(SVGA_CMD_DEFINE_ALPHA_CURSOR);
+	cmd->cursor.id = cpu_to_le32(0);
+	cmd->cursor.width = cpu_to_le32(width);
+	cmd->cursor.height = cpu_to_le32(height);
+	cmd->cursor.hotspotX = cpu_to_le32(hotspotX);
+	cmd->cursor.hotspotY = cpu_to_le32(hotspotY);
+
+	vmw_fifo_commit(dev_priv, cmd_size);
+
+	return 0;
+}
+
+void vmw_cursor_update_position(struct vmw_private *dev_priv,
+				bool show, int x, int y)
+{
+	__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
+	uint32_t count;
+
+	iowrite32(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
+	iowrite32(x, fifo_mem + SVGA_FIFO_CURSOR_X);
+	iowrite32(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
+	count = ioread32(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+	iowrite32(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+}
+
+int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+			   uint32_t handle, uint32_t width, uint32_t height)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	struct vmw_surface *surface = NULL;
+	struct vmw_dma_buffer *dmabuf = NULL;
+	int ret;
+
+	if (handle) {
+		ret = vmw_user_surface_lookup(dev_priv, tfile,
+					      handle, &surface);
+		if (!ret) {
+			if (!surface->snooper.image) {
+				DRM_ERROR("surface not suitable for cursor\n");
+				return -EINVAL;
+			}
+		} else {
+			ret = vmw_user_dmabuf_lookup(tfile,
+						     handle, &dmabuf);
+			if (ret) {
+				DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* takedown old cursor */
+	if (du->cursor_surface) {
+		du->cursor_surface->snooper.crtc = NULL;
+		vmw_surface_unreference(&du->cursor_surface);
+	}
+	if (du->cursor_dmabuf)
+		vmw_dmabuf_unreference(&du->cursor_dmabuf);
+
+	/* setup new image */
+	if (surface) {
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_surface = surface;
+
+		du->cursor_surface->snooper.crtc = crtc;
+		du->cursor_age = du->cursor_surface->snooper.age;
+		vmw_cursor_update_image(dev_priv, surface->snooper.image,
+					64, 64, du->hotspot_x, du->hotspot_y);
+	} else if (dmabuf) {
+		struct ttm_bo_kmap_obj map;
+		unsigned long kmap_offset;
+		unsigned long kmap_num;
+		void *virtual;
+		bool dummy;
+
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_dmabuf = dmabuf;
+
+		kmap_offset = 0;
+		kmap_num = (64*64*4) >> PAGE_SHIFT;
+
+		ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0);
+		if (unlikely(ret != 0)) {
+			DRM_ERROR("reserve failed\n");
+			return -EINVAL;
+		}
+
+		ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map);
+		if (unlikely(ret != 0))
+			goto err_unreserve;
+
+		virtual = ttm_kmap_obj_virtual(&map, &dummy);
+		vmw_cursor_update_image(dev_priv, virtual, 64, 64,
+					du->hotspot_x, du->hotspot_y);
+
+		ttm_bo_kunmap(&map);
+err_unreserve:
+		ttm_bo_unreserve(&dmabuf->base);
+
+	} else {
+		vmw_cursor_update_position(dev_priv, false, 0, 0);
+		return 0;
+	}
+
+	vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y);
+
+	return 0;
+}
+
+int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
+
+	du->cursor_x = x + crtc->x;
+	du->cursor_y = y + crtc->y;
+
+	vmw_cursor_update_position(dev_priv, shown,
+				   du->cursor_x, du->cursor_y);
+
+	return 0;
+}
+
+void vmw_kms_cursor_snoop(struct vmw_surface *srf,
+			  struct ttm_object_file *tfile,
+			  struct ttm_buffer_object *bo,
+			  SVGA3dCmdHeader *header)
+{
+	struct ttm_bo_kmap_obj map;
+	unsigned long kmap_offset;
+	unsigned long kmap_num;
+	SVGA3dCopyBox *box;
+	unsigned box_count;
+	void *virtual;
+	bool dummy;
+	struct vmw_dma_cmd {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdSurfaceDMA dma;
+	} *cmd;
+	int ret;
+
+	cmd = container_of(header, struct vmw_dma_cmd, header);
+
+	/* No snooper installed */
+	if (!srf->snooper.image)
+		return;
+
+	if (cmd->dma.host.face != 0 || cmd->dma.host.mipmap != 0) {
+		DRM_ERROR("face and mipmap for cursors should never != 0\n");
+		return;
+	}
+
+	if (cmd->header.size < 64) {
+		DRM_ERROR("at least one full copy box must be given\n");
+		return;
+	}
+
+	box = (SVGA3dCopyBox *)&cmd[1];
+	box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
+			sizeof(SVGA3dCopyBox);
+
+	if (cmd->dma.guest.pitch != (64 * 4) ||
+	    cmd->dma.guest.ptr.offset % PAGE_SIZE ||
+	    box->x != 0    || box->y != 0    || box->z != 0    ||
+	    box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
+	    box->w != 64   || box->h != 64   || box->d != 1    ||
+	    box_count != 1) {
+		/* TODO handle none page aligned offsets */
+		/* TODO handle partial uploads and pitch != 256 */
+		/* TODO handle more then one copy (size != 64) */
+		DRM_ERROR("lazy programer, cant handle wierd stuff\n");
+		return;
+	}
+
+	kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
+	kmap_num = (64*64*4) >> PAGE_SHIFT;
+
+	ret = ttm_bo_reserve(bo, true, false, false, 0);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("reserve failed\n");
+		return;
+	}
+
+	ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map);
+	if (unlikely(ret != 0))
+		goto err_unreserve;
+
+	virtual = ttm_kmap_obj_virtual(&map, &dummy);
+
+	memcpy(srf->snooper.image, virtual, 64*64*4);
+	srf->snooper.age++;
+
+	/* we can't call this function from this function since execbuf has
+	 * reserved fifo space.
+	 *
+	 * if (srf->snooper.crtc)
+	 *	vmw_ldu_crtc_cursor_update_image(dev_priv,
+	 *					 srf->snooper.image, 64, 64,
+	 *					 du->hotspot_x, du->hotspot_y);
+	 */
+
+	ttm_bo_kunmap(&map);
+err_unreserve:
+	ttm_bo_unreserve(bo);
+}
+
+void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_display_unit *du;
+	struct drm_crtc *crtc;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		du = vmw_crtc_to_du(crtc);
+		if (!du->cursor_surface ||
+		    du->cursor_age == du->cursor_surface->snooper.age)
+			continue;
+
+		du->cursor_age = du->cursor_surface->snooper.age;
+		vmw_cursor_update_image(dev_priv,
+					du->cursor_surface->snooper.image,
+					64, 64, du->hotspot_x, du->hotspot_y);
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+/*
+ * Generic framebuffer code
+ */
+
+int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
+				  struct drm_file *file_priv,
+				  unsigned int *handle)
+{
+	if (handle)
+		handle = 0;
+
+	return 0;
+}
+
+/*
+ * Surface framebuffer code
+ */
+
+#define vmw_framebuffer_to_vfbs(x) \
+	container_of(x, struct vmw_framebuffer_surface, base.base)
+
+struct vmw_framebuffer_surface {
+	struct vmw_framebuffer base;
+	struct vmw_surface *surface;
+	struct delayed_work d_work;
+	struct mutex work_lock;
+	bool present_fs;
+};
+
+void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer)
+{
+	struct vmw_framebuffer_surface *vfb =
+		vmw_framebuffer_to_vfbs(framebuffer);
+
+	cancel_delayed_work_sync(&vfb->d_work);
+	drm_framebuffer_cleanup(framebuffer);
+	vmw_surface_unreference(&vfb->surface);
+
+	kfree(framebuffer);
+}
+
+static void vmw_framebuffer_present_fs_callback(struct work_struct *work)
+{
+	struct delayed_work *d_work =
+		container_of(work, struct delayed_work, work);
+	struct vmw_framebuffer_surface *vfbs =
+		container_of(d_work, struct vmw_framebuffer_surface, d_work);
+	struct vmw_surface *surf = vfbs->surface;
+	struct drm_framebuffer *framebuffer = &vfbs->base.base;
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+		SVGA3dCopyRect cr;
+	} *cmd;
+
+	mutex_lock(&vfbs->work_lock);
+	if (!vfbs->present_fs)
+		goto out_unlock;
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL))
+		goto out_resched;
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr));
+	cmd->body.sid = cpu_to_le32(surf->res.id);
+	cmd->cr.x = cpu_to_le32(0);
+	cmd->cr.y = cpu_to_le32(0);
+	cmd->cr.srcx = cmd->cr.x;
+	cmd->cr.srcy = cmd->cr.y;
+	cmd->cr.w = cpu_to_le32(framebuffer->width);
+	cmd->cr.h = cpu_to_le32(framebuffer->height);
+	vfbs->present_fs = false;
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+out_resched:
+	/**
+	 * Will not re-add if already pending.
+	 */
+	schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
+out_unlock:
+	mutex_unlock(&vfbs->work_lock);
+}
+
+
+int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
+				  unsigned flags, unsigned color,
+				  struct drm_clip_rect *clips,
+				  unsigned num_clips)
+{
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct vmw_framebuffer_surface *vfbs =
+		vmw_framebuffer_to_vfbs(framebuffer);
+	struct vmw_surface *surf = vfbs->surface;
+	struct drm_clip_rect norect;
+	SVGA3dCopyRect *cr;
+	int i, inc = 1;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdPresent body;
+		SVGA3dCopyRect cr;
+	} *cmd;
+
+	if (!num_clips ||
+	    !(dev_priv->fifo.capabilities &
+	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
+		int ret;
+
+		mutex_lock(&vfbs->work_lock);
+		vfbs->present_fs = true;
+		ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE);
+		mutex_unlock(&vfbs->work_lock);
+		if (ret) {
+			/**
+			 * No work pending, Force immediate present.
+			 */
+			vmw_framebuffer_present_fs_callback(&vfbs->d_work.work);
+		}
+		return 0;
+	}
+
+	if (!num_clips) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		inc = 2; /* skip source rects */
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr));
+	cmd->body.sid = cpu_to_le32(surf->res.id);
+
+	for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) {
+		cr->x = cpu_to_le16(clips->x1);
+		cr->y = cpu_to_le16(clips->y1);
+		cr->srcx = cr->x;
+		cr->srcy = cr->y;
+		cr->w = cpu_to_le16(clips->x2 - clips->x1);
+		cr->h = cpu_to_le16(clips->y2 - clips->y1);
+	}
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr));
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs vmw_framebuffer_surface_funcs = {
+	.destroy = vmw_framebuffer_surface_destroy,
+	.dirty = vmw_framebuffer_surface_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
+				    struct vmw_surface *surface,
+				    struct vmw_framebuffer **out,
+				    unsigned width, unsigned height)
+
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_framebuffer_surface *vfbs;
+	int ret;
+
+	vfbs = kzalloc(sizeof(*vfbs), GFP_KERNEL);
+	if (!vfbs) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+
+	ret = drm_framebuffer_init(dev, &vfbs->base.base,
+				   &vmw_framebuffer_surface_funcs);
+	if (ret)
+		goto out_err2;
+
+	if (!vmw_surface_reference(surface)) {
+		DRM_ERROR("failed to reference surface %p\n", surface);
+		goto out_err3;
+	}
+
+	/* XXX get the first 3 from the surface info */
+	vfbs->base.base.bits_per_pixel = 32;
+	vfbs->base.base.pitch = width * 32 / 4;
+	vfbs->base.base.depth = 24;
+	vfbs->base.base.width = width;
+	vfbs->base.base.height = height;
+	vfbs->base.pin = NULL;
+	vfbs->base.unpin = NULL;
+	vfbs->surface = surface;
+	mutex_init(&vfbs->work_lock);
+	INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback);
+	*out = &vfbs->base;
+
+	return 0;
+
+out_err3:
+	drm_framebuffer_cleanup(&vfbs->base.base);
+out_err2:
+	kfree(vfbs);
+out_err1:
+	return ret;
+}
+
+/*
+ * Dmabuf framebuffer code
+ */
+
+#define vmw_framebuffer_to_vfbd(x) \
+	container_of(x, struct vmw_framebuffer_dmabuf, base.base)
+
+struct vmw_framebuffer_dmabuf {
+	struct vmw_framebuffer base;
+	struct vmw_dma_buffer *buffer;
+};
+
+void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer)
+{
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(framebuffer);
+
+	drm_framebuffer_cleanup(framebuffer);
+	vmw_dmabuf_unreference(&vfbd->buffer);
+
+	kfree(vfbd);
+}
+
+int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
+				 unsigned flags, unsigned color,
+				 struct drm_clip_rect *clips,
+				 unsigned num_clips)
+{
+	struct vmw_private *dev_priv = vmw_priv(framebuffer->dev);
+	struct drm_clip_rect norect;
+	struct {
+		uint32_t header;
+		SVGAFifoCmdUpdate body;
+	} *cmd;
+	int i, increment = 1;
+
+	if (!num_clips ||
+	    !(dev_priv->fifo.capabilities &
+	      SVGA_FIFO_CAP_SCREEN_OBJECT)) {
+		num_clips = 1;
+		clips = &norect;
+		norect.x1 = norect.y1 = 0;
+		norect.x2 = framebuffer->width;
+		norect.y2 = framebuffer->height;
+	} else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) {
+		num_clips /= 2;
+		increment = 2;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < num_clips; i++, clips += increment) {
+		cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE);
+		cmd[i].body.x = cpu_to_le32(clips[i].x1);
+		cmd[i].body.y = cpu_to_le32(clips[i].y1);
+		cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1);
+		cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1);
+	}
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips);
+
+	return 0;
+}
+
+static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = {
+	.destroy = vmw_framebuffer_dmabuf_destroy,
+	.dirty = vmw_framebuffer_dmabuf_dirty,
+	.create_handle = vmw_framebuffer_create_handle,
+};
+
+static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb)
+{
+	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+	int ret;
+
+	vmw_overlay_pause_all(dev_priv);
+
+	ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer);
+
+	if (dev_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
+		vmw_write(dev_priv, SVGA_REG_WIDTH, vfb->base.width);
+		vmw_write(dev_priv, SVGA_REG_HEIGHT, vfb->base.height);
+		vmw_write(dev_priv, SVGA_REG_BITS_PER_PIXEL, vfb->base.bits_per_pixel);
+		vmw_write(dev_priv, SVGA_REG_DEPTH, vfb->base.depth);
+		vmw_write(dev_priv, SVGA_REG_RED_MASK, 0x00ff0000);
+		vmw_write(dev_priv, SVGA_REG_GREEN_MASK, 0x0000ff00);
+		vmw_write(dev_priv, SVGA_REG_BLUE_MASK, 0x000000ff);
+	} else
+		WARN_ON(true);
+
+	vmw_overlay_resume_all(dev_priv);
+
+	return 0;
+}
+
+static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb)
+{
+	struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+	struct vmw_framebuffer_dmabuf *vfbd =
+		vmw_framebuffer_to_vfbd(&vfb->base);
+
+	if (!vfbd->buffer) {
+		WARN_ON(!vfbd->buffer);
+		return 0;
+	}
+
+	return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer);
+}
+
+int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
+				   struct vmw_dma_buffer *dmabuf,
+				   struct vmw_framebuffer **out,
+				   unsigned width, unsigned height)
+
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct vmw_framebuffer_dmabuf *vfbd;
+	int ret;
+
+	vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL);
+	if (!vfbd) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+
+	ret = drm_framebuffer_init(dev, &vfbd->base.base,
+				   &vmw_framebuffer_dmabuf_funcs);
+	if (ret)
+		goto out_err2;
+
+	if (!vmw_dmabuf_reference(dmabuf)) {
+		DRM_ERROR("failed to reference dmabuf %p\n", dmabuf);
+		goto out_err3;
+	}
+
+	/* XXX get the first 3 from the surface info */
+	vfbd->base.base.bits_per_pixel = 32;
+	vfbd->base.base.pitch = width * 32 / 4;
+	vfbd->base.base.depth = 24;
+	vfbd->base.base.width = width;
+	vfbd->base.base.height = height;
+	vfbd->base.pin = vmw_framebuffer_dmabuf_pin;
+	vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin;
+	vfbd->buffer = dmabuf;
+	*out = &vfbd->base;
+
+	return 0;
+
+out_err3:
+	drm_framebuffer_cleanup(&vfbd->base.base);
+out_err2:
+	kfree(vfbd);
+out_err1:
+	return ret;
+}
+
+/*
+ * Generic Kernel modesetting functions
+ */
+
+static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
+						 struct drm_file *file_priv,
+						 struct drm_mode_fb_cmd *mode_cmd)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_framebuffer *vfb = NULL;
+	struct vmw_surface *surface = NULL;
+	struct vmw_dma_buffer *bo = NULL;
+	int ret;
+
+	ret = vmw_user_surface_lookup(dev_priv, tfile,
+				      mode_cmd->handle, &surface);
+	if (ret)
+		goto try_dmabuf;
+
+	ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb,
+					      mode_cmd->width, mode_cmd->height);
+
+	/* vmw_user_surface_lookup takes one ref so does new_fb */
+	vmw_surface_unreference(&surface);
+
+	if (ret) {
+		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		return NULL;
+	}
+	return &vfb->base;
+
+try_dmabuf:
+	DRM_INFO("%s: trying buffer\n", __func__);
+
+	ret = vmw_user_dmabuf_lookup(tfile, mode_cmd->handle, &bo);
+	if (ret) {
+		DRM_ERROR("failed to find buffer: %i\n", ret);
+		return NULL;
+	}
+
+	ret = vmw_kms_new_framebuffer_dmabuf(dev_priv, bo, &vfb,
+					     mode_cmd->width, mode_cmd->height);
+
+	/* vmw_user_dmabuf_lookup takes one ref so does new_fb */
+	vmw_dmabuf_unreference(&bo);
+
+	if (ret) {
+		DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret);
+		return NULL;
+	}
+
+	return &vfb->base;
+}
+
+static int vmw_kms_fb_changed(struct drm_device *dev)
+{
+	return 0;
+}
+
+static struct drm_mode_config_funcs vmw_kms_funcs = {
+	.fb_create = vmw_kms_fb_create,
+	.fb_changed = vmw_kms_fb_changed,
+};
+
+int vmw_kms_init(struct vmw_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	int ret;
+
+	drm_mode_config_init(dev);
+	dev->mode_config.funcs = &vmw_kms_funcs;
+	dev->mode_config.min_width = 640;
+	dev->mode_config.min_height = 480;
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	ret = vmw_kms_init_legacy_display_system(dev_priv);
+
+	return 0;
+}
+
+int vmw_kms_close(struct vmw_private *dev_priv)
+{
+	/*
+	 * Docs says we should take the lock before calling this function
+	 * but since it destroys encoders and our destructor calls
+	 * drm_encoder_cleanup which takes the lock we deadlock.
+	 */
+	drm_mode_config_cleanup(dev_priv->dev);
+	vmw_kms_close_legacy_display_system(dev_priv);
+	return 0;
+}
+
+int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct drm_vmw_cursor_bypass_arg *arg = data;
+	struct vmw_display_unit *du;
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	int ret = 0;
+
+
+	mutex_lock(&dev->mode_config.mutex);
+	if (arg->flags & DRM_VMW_CURSOR_BYPASS_ALL) {
+
+		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+			du = vmw_crtc_to_du(crtc);
+			du->hotspot_x = arg->xhot;
+			du->hotspot_y = arg->yhot;
+		}
+
+		mutex_unlock(&dev->mode_config.mutex);
+		return 0;
+	}
+
+	obj = drm_mode_object_find(dev, arg->crtc_id, DRM_MODE_OBJECT_CRTC);
+	if (!obj) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	crtc = obj_to_crtc(obj);
+	du = vmw_crtc_to_du(crtc);
+
+	du->hotspot_x = arg->xhot;
+	du->hotspot_y = arg->yhot;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return ret;
+}
+
+int vmw_kms_save_vga(struct vmw_private *vmw_priv)
+{
+	/*
+	 * setup a single multimon monitor with the size
+	 * of 0x0, this stops the UI from resizing when we
+	 * change the framebuffer size
+	 */
+	if (vmw_priv->capabilities & SVGA_CAP_MULTIMON) {
+		vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 1);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_IS_PRIMARY, true);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	}
+
+	vmw_priv->vga_width = vmw_read(vmw_priv, SVGA_REG_WIDTH);
+	vmw_priv->vga_height = vmw_read(vmw_priv, SVGA_REG_HEIGHT);
+	vmw_priv->vga_bpp = vmw_read(vmw_priv, SVGA_REG_BITS_PER_PIXEL);
+	vmw_priv->vga_depth = vmw_read(vmw_priv, SVGA_REG_DEPTH);
+	vmw_priv->vga_pseudo = vmw_read(vmw_priv, SVGA_REG_PSEUDOCOLOR);
+	vmw_priv->vga_red_mask = vmw_read(vmw_priv, SVGA_REG_RED_MASK);
+	vmw_priv->vga_green_mask = vmw_read(vmw_priv, SVGA_REG_GREEN_MASK);
+	vmw_priv->vga_blue_mask = vmw_read(vmw_priv, SVGA_REG_BLUE_MASK);
+
+	return 0;
+}
+
+int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
+{
+	vmw_write(vmw_priv, SVGA_REG_WIDTH, vmw_priv->vga_width);
+	vmw_write(vmw_priv, SVGA_REG_HEIGHT, vmw_priv->vga_height);
+	vmw_write(vmw_priv, SVGA_REG_BITS_PER_PIXEL, vmw_priv->vga_bpp);
+	vmw_write(vmw_priv, SVGA_REG_DEPTH, vmw_priv->vga_depth);
+	vmw_write(vmw_priv, SVGA_REG_PSEUDOCOLOR, vmw_priv->vga_pseudo);
+	vmw_write(vmw_priv, SVGA_REG_RED_MASK, vmw_priv->vga_red_mask);
+	vmw_write(vmw_priv, SVGA_REG_GREEN_MASK, vmw_priv->vga_green_mask);
+	vmw_write(vmw_priv, SVGA_REG_BLUE_MASK, vmw_priv->vga_blue_mask);
+
+	/* TODO check for multimon */
+	vmw_write(vmw_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
new file mode 100644
index 0000000..8b95249
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef VMWGFX_KMS_H_
+#define VMWGFX_KMS_H_
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+
+#define vmw_framebuffer_to_vfb(x) \
+	container_of(x, struct vmw_framebuffer, base)
+
+/**
+ * Base class for framebuffers
+ *
+ * @pin is called the when ever a crtc uses this framebuffer
+ * @unpin is called
+ */
+struct vmw_framebuffer {
+	struct drm_framebuffer base;
+	int (*pin)(struct vmw_framebuffer *fb);
+	int (*unpin)(struct vmw_framebuffer *fb);
+};
+
+
+#define vmw_crtc_to_du(x) \
+	container_of(x, struct vmw_display_unit, crtc)
+
+/*
+ * Basic cursor manipulation
+ */
+int vmw_cursor_update_image(struct vmw_private *dev_priv,
+			    u32 *image, u32 width, u32 height,
+			    u32 hotspotX, u32 hotspotY);
+void vmw_cursor_update_position(struct vmw_private *dev_priv,
+				bool show, int x, int y);
+
+/**
+ * Base class display unit.
+ *
+ * Since the SVGA hw doesn't have a concept of a crtc, encoder or connector
+ * so the display unit is all of them at the same time. This is true for both
+ * legacy multimon and screen objects.
+ */
+struct vmw_display_unit {
+	struct drm_crtc crtc;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+
+	struct vmw_surface *cursor_surface;
+	struct vmw_dma_buffer *cursor_dmabuf;
+	size_t cursor_age;
+
+	int cursor_x;
+	int cursor_y;
+
+	int hotspot_x;
+	int hotspot_y;
+
+	unsigned unit;
+};
+
+/*
+ * Shared display unit functions - vmwgfx_kms.c
+ */
+void vmw_display_unit_cleanup(struct vmw_display_unit *du);
+int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
+			   uint32_t handle, uint32_t width, uint32_t height);
+int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+
+/*
+ * Legacy display unit functions - vmwgfx_ldu.h
+ */
+int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
+int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
new file mode 100644
index 0000000..9089159
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -0,0 +1,516 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_kms.h"
+
+#define vmw_crtc_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.crtc)
+#define vmw_encoder_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.encoder)
+#define vmw_connector_to_ldu(x) \
+	container_of(x, struct vmw_legacy_display_unit, base.connector)
+
+struct vmw_legacy_display {
+	struct list_head active;
+
+	unsigned num_active;
+
+	struct vmw_framebuffer *fb;
+};
+
+/**
+ * Display unit using the legacy register interface.
+ */
+struct vmw_legacy_display_unit {
+	struct vmw_display_unit base;
+
+	struct list_head active;
+
+	unsigned unit;
+};
+
+static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu)
+{
+	list_del_init(&ldu->active);
+	vmw_display_unit_cleanup(&ldu->base);
+	kfree(ldu);
+}
+
+
+/*
+ * Legacy Display Unit CRTC functions
+ */
+
+static void vmw_ldu_crtc_save(struct drm_crtc *crtc)
+{
+}
+
+static void vmw_ldu_crtc_restore(struct drm_crtc *crtc)
+{
+}
+
+static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc,
+				   u16 *r, u16 *g, u16 *b,
+				   uint32_t size)
+{
+}
+
+static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc)
+{
+	vmw_ldu_destroy(vmw_crtc_to_ldu(crtc));
+}
+
+static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
+{
+	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
+	struct vmw_legacy_display_unit *entry;
+	struct drm_crtc *crtc;
+	int i = 0;
+
+	/* to stop the screen from changing size on resize */
+	vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, 0);
+	for (i = 0; i < lds->num_active; i++) {
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, 0);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+	}
+
+	/* Now set the mode */
+	vmw_write(dev_priv, SVGA_REG_NUM_GUEST_DISPLAYS, lds->num_active);
+	i = 0;
+	list_for_each_entry(entry, &lds->active, active) {
+		crtc = &entry->base.crtc;
+
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_IS_PRIMARY, !i);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_X, crtc->x);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_POSITION_Y, crtc->y);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_WIDTH, crtc->mode.hdisplay);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_HEIGHT, crtc->mode.vdisplay);
+		vmw_write(dev_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
+
+		i++;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
+			      struct vmw_legacy_display_unit *ldu)
+{
+	struct vmw_legacy_display *ld = vmw_priv->ldu_priv;
+	if (list_empty(&ldu->active))
+		return 0;
+
+	list_del_init(&ldu->active);
+	if (--(ld->num_active) == 0) {
+		BUG_ON(!ld->fb);
+		if (ld->fb->unpin)
+			ld->fb->unpin(ld->fb);
+		ld->fb = NULL;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
+			      struct vmw_legacy_display_unit *ldu,
+			      struct vmw_framebuffer *vfb)
+{
+	struct vmw_legacy_display *ld = vmw_priv->ldu_priv;
+	struct vmw_legacy_display_unit *entry;
+	struct list_head *at;
+
+	if (!list_empty(&ldu->active))
+		return 0;
+
+	at = &ld->active;
+	list_for_each_entry(entry, &ld->active, active) {
+		if (entry->unit > ldu->unit)
+			break;
+
+		at = &entry->active;
+	}
+
+	list_add(&ldu->active, at);
+	if (ld->num_active++ == 0) {
+		BUG_ON(ld->fb);
+		if (vfb->pin)
+			vfb->pin(vfb);
+		ld->fb = vfb;
+	}
+
+	return 0;
+}
+
+static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_legacy_display_unit *ldu;
+	struct drm_connector *connector;
+	struct drm_display_mode *mode;
+	struct drm_encoder *encoder;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+	struct drm_crtc *crtc;
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	/* get the ldu */
+	crtc = set->crtc;
+	ldu = vmw_crtc_to_ldu(crtc);
+	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (set->num_connectors > 1) {
+		DRM_ERROR("to many connectors\n");
+		return -EINVAL;
+	}
+
+	if (set->num_connectors == 1 &&
+	    set->connectors[0] != &ldu->base.connector) {
+		DRM_ERROR("connector doesn't match %p %p\n",
+			set->connectors[0], &ldu->base.connector);
+		return -EINVAL;
+	}
+
+	/* ldu only supports one fb active at the time */
+	if (dev_priv->ldu_priv->fb && vfb &&
+	    dev_priv->ldu_priv->fb != vfb) {
+		DRM_ERROR("Multiple framebuffers not supported\n");
+		return -EINVAL;
+	}
+
+	/* since they always map one to one these are safe */
+	connector = &ldu->base.connector;
+	encoder = &ldu->base.encoder;
+
+	/* should we turn the crtc off? */
+	if (set->num_connectors == 0 || !set->mode || !set->fb) {
+
+		connector->encoder = NULL;
+		encoder->crtc = NULL;
+		crtc->fb = NULL;
+
+		vmw_ldu_del_active(dev_priv, ldu);
+
+		vmw_ldu_commit_list(dev_priv);
+
+		return 0;
+	}
+
+
+	/* we now know we want to set a mode */
+	mode = set->mode;
+	fb = set->fb;
+
+	if (set->x + mode->hdisplay > fb->width ||
+	    set->y + mode->vdisplay > fb->height) {
+		DRM_ERROR("set outside of framebuffer\n");
+		return -EINVAL;
+	}
+
+	vmw_fb_off(dev_priv);
+
+	crtc->fb = fb;
+	encoder->crtc = crtc;
+	connector->encoder = encoder;
+	crtc->x = set->x;
+	crtc->y = set->y;
+	crtc->mode = *mode;
+
+	vmw_ldu_add_active(dev_priv, ldu, vfb);
+
+	vmw_ldu_commit_list(dev_priv);
+
+	return 0;
+}
+
+static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
+	.save = vmw_ldu_crtc_save,
+	.restore = vmw_ldu_crtc_restore,
+	.cursor_set = vmw_du_crtc_cursor_set,
+	.cursor_move = vmw_du_crtc_cursor_move,
+	.gamma_set = vmw_ldu_crtc_gamma_set,
+	.destroy = vmw_ldu_crtc_destroy,
+	.set_config = vmw_ldu_crtc_set_config,
+};
+
+/*
+ * Legacy Display Unit encoder functions
+ */
+
+static void vmw_ldu_encoder_destroy(struct drm_encoder *encoder)
+{
+	vmw_ldu_destroy(vmw_encoder_to_ldu(encoder));
+}
+
+static struct drm_encoder_funcs vmw_legacy_encoder_funcs = {
+	.destroy = vmw_ldu_encoder_destroy,
+};
+
+/*
+ * Legacy Display Unit connector functions
+ */
+
+static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode)
+{
+}
+
+static void vmw_ldu_connector_save(struct drm_connector *connector)
+{
+}
+
+static void vmw_ldu_connector_restore(struct drm_connector *connector)
+{
+}
+
+static enum drm_connector_status
+	vmw_ldu_connector_detect(struct drm_connector *connector)
+{
+	/* XXX vmwctrl should control connection status */
+	if (vmw_connector_to_ldu(connector)->base.unit == 0)
+		return connector_status_connected;
+	return connector_status_disconnected;
+}
+
+static struct drm_display_mode vmw_ldu_connector_builtin[] = {
+	/* 640x480@60Hz */
+	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
+		   752, 800, 0, 480, 489, 492, 525, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 800x600@60Hz */
+	{ DRM_MODE("800x600",
+		   DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+		   40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
+		   0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1024x768@60Hz */
+	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
+		   1184, 1344, 0, 768, 771, 777, 806, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1152x864@75Hz */
+	{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
+		   1344, 1600, 0, 864, 865, 868, 900, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x768@60Hz */
+	{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
+		   1472, 1664, 0, 768, 771, 778, 798, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x800@60Hz */
+	{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
+		   1480, 1680, 0, 800, 803, 809, 831, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
+	/* 1280x960@60Hz */
+	{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
+		   1488, 1800, 0, 960, 961, 964, 1000, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1280x1024@60Hz */
+	{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
+		   1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1360x768@60Hz */
+	{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
+		   1536, 1792, 0, 768, 771, 777, 795, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x1050@60Hz */
+	{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
+		   1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1440x900@60Hz */
+	{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
+		   1672, 1904, 0, 900, 903, 909, 934, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1600x1200@60Hz */
+	{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
+		   1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1680x1050@60Hz */
+	{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
+		   1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1792x1344@60Hz */
+	{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
+		   2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1853x1392@60Hz */
+	{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
+		   2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1200@60Hz */
+	{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
+		   2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 1920x1440@60Hz */
+	{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
+		   2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* 2560x1600@60Hz */
+	{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
+		   3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
+		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
+	/* Terminate */
+	{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
+};
+
+static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
+					uint32_t max_width, uint32_t max_height)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode = NULL;
+	int i;
+
+	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
+		if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
+		    vmw_ldu_connector_builtin[i].vdisplay > max_height)
+			continue;
+
+		mode = drm_mode_duplicate(dev, &vmw_ldu_connector_builtin[i]);
+		if (!mode)
+			return 0;
+		mode->vrefresh = drm_mode_vrefresh(mode);
+
+		drm_mode_probed_add(connector, mode);
+	}
+
+	drm_mode_connector_list_update(connector);
+
+	return 1;
+}
+
+static int vmw_ldu_connector_set_property(struct drm_connector *connector,
+					  struct drm_property *property,
+					  uint64_t val)
+{
+	return 0;
+}
+
+static void vmw_ldu_connector_destroy(struct drm_connector *connector)
+{
+	vmw_ldu_destroy(vmw_connector_to_ldu(connector));
+}
+
+static struct drm_connector_funcs vmw_legacy_connector_funcs = {
+	.dpms = vmw_ldu_connector_dpms,
+	.save = vmw_ldu_connector_save,
+	.restore = vmw_ldu_connector_restore,
+	.detect = vmw_ldu_connector_detect,
+	.fill_modes = vmw_ldu_connector_fill_modes,
+	.set_property = vmw_ldu_connector_set_property,
+	.destroy = vmw_ldu_connector_destroy,
+};
+
+static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
+{
+	struct vmw_legacy_display_unit *ldu;
+	struct drm_device *dev = dev_priv->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
+
+	ldu = kzalloc(sizeof(*ldu), GFP_KERNEL);
+	if (!ldu)
+		return -ENOMEM;
+
+	ldu->unit = unit;
+	crtc = &ldu->base.crtc;
+	encoder = &ldu->base.encoder;
+	connector = &ldu->base.connector;
+
+	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+			   DRM_MODE_CONNECTOR_LVDS);
+	/* Initial status */
+	if (unit == 0)
+		connector->status = connector_status_connected;
+	else
+		connector->status = connector_status_disconnected;
+
+	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
+			 DRM_MODE_ENCODER_LVDS);
+	drm_mode_connector_attach_encoder(connector, encoder);
+	encoder->possible_crtcs = (1 << unit);
+	encoder->possible_clones = 0;
+
+	INIT_LIST_HEAD(&ldu->active);
+
+	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
+
+	drm_connector_attach_property(connector,
+				      dev->mode_config.dirty_info_property,
+				      1);
+
+	return 0;
+}
+
+int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv)
+{
+	if (dev_priv->ldu_priv) {
+		DRM_INFO("ldu system already on\n");
+		return -EINVAL;
+	}
+
+	dev_priv->ldu_priv = kmalloc(GFP_KERNEL, sizeof(*dev_priv->ldu_priv));
+
+	if (!dev_priv->ldu_priv)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev_priv->ldu_priv->active);
+	dev_priv->ldu_priv->num_active = 0;
+	dev_priv->ldu_priv->fb = NULL;
+
+	drm_mode_create_dirty_info_property(dev_priv->dev);
+
+	vmw_ldu_init(dev_priv, 0);
+	vmw_ldu_init(dev_priv, 1);
+	vmw_ldu_init(dev_priv, 2);
+	vmw_ldu_init(dev_priv, 3);
+	vmw_ldu_init(dev_priv, 4);
+	vmw_ldu_init(dev_priv, 5);
+	vmw_ldu_init(dev_priv, 6);
+	vmw_ldu_init(dev_priv, 7);
+
+	return 0;
+}
+
+int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
+{
+	if (!dev_priv->ldu_priv)
+		return -ENOSYS;
+
+	BUG_ON(!list_empty(&dev_priv->ldu_priv->active));
+
+	kfree(dev_priv->ldu_priv);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
new file mode 100644
index 0000000..bb6e6a0
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -0,0 +1,634 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+#include "ttm/ttm_placement.h"
+
+#include "svga_overlay.h"
+#include "svga_escape.h"
+
+#define VMW_MAX_NUM_STREAMS 1
+
+struct vmw_stream {
+	struct vmw_dma_buffer *buf;
+	bool claimed;
+	bool paused;
+	struct drm_vmw_control_stream_arg saved;
+};
+
+/**
+ * Overlay control
+ */
+struct vmw_overlay {
+	/*
+	 * Each stream is a single overlay. In Xv these are called ports.
+	 */
+	struct mutex mutex;
+	struct vmw_stream stream[VMW_MAX_NUM_STREAMS];
+};
+
+static inline struct vmw_overlay *vmw_overlay(struct drm_device *dev)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	return dev_priv ? dev_priv->overlay_priv : NULL;
+}
+
+struct vmw_escape_header {
+	uint32_t cmd;
+	SVGAFifoCmdEscape body;
+};
+
+struct vmw_escape_video_flush {
+	struct vmw_escape_header escape;
+	SVGAEscapeVideoFlush flush;
+};
+
+static inline void fill_escape(struct vmw_escape_header *header,
+			       uint32_t size)
+{
+	header->cmd = SVGA_CMD_ESCAPE;
+	header->body.nsid = SVGA_ESCAPE_NSID_VMWARE;
+	header->body.size = size;
+}
+
+static inline void fill_flush(struct vmw_escape_video_flush *cmd,
+			      uint32_t stream_id)
+{
+	fill_escape(&cmd->escape, sizeof(cmd->flush));
+	cmd->flush.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_FLUSH;
+	cmd->flush.streamId = stream_id;
+}
+
+/**
+ * Pin or unpin a buffer in vram.
+ *
+ * @dev_priv:  Driver private.
+ * @buf:  DMA buffer to pin or unpin.
+ * @pin:  Pin buffer in vram if true.
+ * @interruptible:  Use interruptible wait.
+ *
+ * Takes the current masters ttm lock in read.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv,
+				  struct vmw_dma_buffer *buf,
+				  bool pin, bool interruptible)
+{
+	struct ttm_buffer_object *bo = &buf->base;
+	struct ttm_bo_global *glob = bo->glob;
+	struct ttm_placement *overlay_placement = &vmw_vram_placement;
+	int ret;
+
+	ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
+	if (unlikely(ret != 0))
+		goto err;
+
+	if (buf->gmr_bound) {
+		vmw_gmr_unbind(dev_priv, buf->gmr_id);
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, buf->gmr_id);
+		spin_unlock(&glob->lru_lock);
+		buf->gmr_bound = NULL;
+	}
+
+	if (pin)
+		overlay_placement = &vmw_vram_ne_placement;
+
+	ret = ttm_bo_validate(bo, overlay_placement, interruptible, false);
+
+	ttm_bo_unreserve(bo);
+
+err:
+	ttm_read_unlock(&dev_priv->active_master->lock);
+
+	return ret;
+}
+
+/**
+ * Send put command to hw.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_overlay_send_put(struct vmw_private *dev_priv,
+				struct vmw_dma_buffer *buf,
+				struct drm_vmw_control_stream_arg *arg,
+				bool interruptible)
+{
+	struct {
+		struct vmw_escape_header escape;
+		struct {
+			struct {
+				uint32_t cmdType;
+				uint32_t streamId;
+			} header;
+			struct {
+				uint32_t registerId;
+				uint32_t value;
+			} items[SVGA_VIDEO_PITCH_3 + 1];
+		} body;
+		struct vmw_escape_video_flush flush;
+	} *cmds;
+	uint32_t offset;
+	int i, ret;
+
+	for (;;) {
+		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
+		if (cmds)
+			break;
+
+		ret = vmw_fallback_wait(dev_priv, false, true, 0,
+					interruptible, 3*HZ);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	fill_escape(&cmds->escape, sizeof(cmds->body));
+	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->body.header.streamId = arg->stream_id;
+
+	for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++)
+		cmds->body.items[i].registerId = i;
+
+	offset = buf->base.offset + arg->offset;
+
+	cmds->body.items[SVGA_VIDEO_ENABLED].value     = true;
+	cmds->body.items[SVGA_VIDEO_FLAGS].value       = arg->flags;
+	cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset;
+	cmds->body.items[SVGA_VIDEO_FORMAT].value      = arg->format;
+	cmds->body.items[SVGA_VIDEO_COLORKEY].value    = arg->color_key;
+	cmds->body.items[SVGA_VIDEO_SIZE].value        = arg->size;
+	cmds->body.items[SVGA_VIDEO_WIDTH].value       = arg->width;
+	cmds->body.items[SVGA_VIDEO_HEIGHT].value      = arg->height;
+	cmds->body.items[SVGA_VIDEO_SRC_X].value       = arg->src.x;
+	cmds->body.items[SVGA_VIDEO_SRC_Y].value       = arg->src.y;
+	cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value   = arg->src.w;
+	cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value  = arg->src.h;
+	cmds->body.items[SVGA_VIDEO_DST_X].value       = arg->dst.x;
+	cmds->body.items[SVGA_VIDEO_DST_Y].value       = arg->dst.y;
+	cmds->body.items[SVGA_VIDEO_DST_WIDTH].value   = arg->dst.w;
+	cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value  = arg->dst.h;
+	cmds->body.items[SVGA_VIDEO_PITCH_1].value     = arg->pitch[0];
+	cmds->body.items[SVGA_VIDEO_PITCH_2].value     = arg->pitch[1];
+	cmds->body.items[SVGA_VIDEO_PITCH_3].value     = arg->pitch[2];
+
+	fill_flush(&cmds->flush, arg->stream_id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+
+	return 0;
+}
+
+/**
+ * Send stop command to hw.
+ *
+ * Returns
+ * -ERESTARTSYS if interrupted by a signal.
+ */
+static int vmw_overlay_send_stop(struct vmw_private *dev_priv,
+				 uint32_t stream_id,
+				 bool interruptible)
+{
+	struct {
+		struct vmw_escape_header escape;
+		SVGAEscapeVideoSetRegs body;
+		struct vmw_escape_video_flush flush;
+	} *cmds;
+	int ret;
+
+	for (;;) {
+		cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds));
+		if (cmds)
+			break;
+
+		ret = vmw_fallback_wait(dev_priv, false, true, 0,
+					interruptible, 3*HZ);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	fill_escape(&cmds->escape, sizeof(cmds->body));
+	cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS;
+	cmds->body.header.streamId = stream_id;
+	cmds->body.items[0].registerId = SVGA_VIDEO_ENABLED;
+	cmds->body.items[0].value = false;
+	fill_flush(&cmds->flush, stream_id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmds));
+
+	return 0;
+}
+
+/**
+ * Stop or pause a stream.
+ *
+ * If the stream is paused the no evict flag is removed from the buffer
+ * but left in vram. This allows for instance mode_set to evict it
+ * should it need to.
+ *
+ * The caller must hold the overlay lock.
+ *
+ * @stream_id which stream to stop/pause.
+ * @pause true to pause, false to stop completely.
+ */
+static int vmw_overlay_stop(struct vmw_private *dev_priv,
+			    uint32_t stream_id, bool pause,
+			    bool interruptible)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct vmw_stream *stream = &overlay->stream[stream_id];
+	int ret;
+
+	/* no buffer attached the stream is completely stopped */
+	if (!stream->buf)
+		return 0;
+
+	/* If the stream is paused this is already done */
+	if (!stream->paused) {
+		ret = vmw_overlay_send_stop(dev_priv, stream_id,
+					    interruptible);
+		if (ret)
+			return ret;
+
+		/* We just remove the NO_EVICT flag so no -ENOMEM */
+		ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false,
+					     interruptible);
+		if (interruptible && ret == -ERESTARTSYS)
+			return ret;
+		else
+			BUG_ON(ret != 0);
+	}
+
+	if (!pause) {
+		vmw_dmabuf_unreference(&stream->buf);
+		stream->paused = false;
+	} else {
+		stream->paused = true;
+	}
+
+	return 0;
+}
+
+/**
+ * Update a stream and send any put or stop fifo commands needed.
+ *
+ * The caller must hold the overlay lock.
+ *
+ * Returns
+ * -ENOMEM if buffer doesn't fit in vram.
+ * -ERESTARTSYS if interrupted.
+ */
+static int vmw_overlay_update_stream(struct vmw_private *dev_priv,
+				     struct vmw_dma_buffer *buf,
+				     struct drm_vmw_control_stream_arg *arg,
+				     bool interruptible)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct vmw_stream *stream = &overlay->stream[arg->stream_id];
+	int ret = 0;
+
+	if (!buf)
+		return -EINVAL;
+
+	DRM_DEBUG("   %s: old %p, new %p, %spaused\n", __func__,
+		  stream->buf, buf, stream->paused ? "" : "not ");
+
+	if (stream->buf != buf) {
+		ret = vmw_overlay_stop(dev_priv, arg->stream_id,
+				       false, interruptible);
+		if (ret)
+			return ret;
+	} else if (!stream->paused) {
+		/* If the buffers match and not paused then just send
+		 * the put command, no need to do anything else.
+		 */
+		ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible);
+		if (ret == 0)
+			stream->saved = *arg;
+		else
+			BUG_ON(!interruptible);
+
+		return ret;
+	}
+
+	/* We don't start the old stream if we are interrupted.
+	 * Might return -ENOMEM if it can't fit the buffer in vram.
+	 */
+	ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible);
+	if (ret)
+		return ret;
+
+	ret = vmw_overlay_send_put(dev_priv, buf, arg, interruptible);
+	if (ret) {
+		/* This one needs to happen no matter what. We only remove
+		 * the NO_EVICT flag so this is safe from -ENOMEM.
+		 */
+		BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0);
+		return ret;
+	}
+
+	if (stream->buf != buf)
+		stream->buf = vmw_dmabuf_reference(buf);
+	stream->saved = *arg;
+
+	return 0;
+}
+
+/**
+ * Stop all streams.
+ *
+ * Used by the fb code when starting.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_stop_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		struct vmw_stream *stream = &overlay->stream[i];
+		if (!stream->buf)
+			continue;
+
+		ret = vmw_overlay_stop(dev_priv, i, false, false);
+		WARN_ON(ret != 0);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+/**
+ * Try to resume all paused streams.
+ *
+ * Used by the kms code after moving a new scanout buffer to vram.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_resume_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		struct vmw_stream *stream = &overlay->stream[i];
+		if (!stream->paused)
+			continue;
+
+		ret = vmw_overlay_update_stream(dev_priv, stream->buf,
+						&stream->saved, false);
+		if (ret != 0)
+			DRM_INFO("%s: *warning* failed to resume stream %i\n",
+				 __func__, i);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+/**
+ * Pauses all active streams.
+ *
+ * Used by the kms code when moving a new scanout buffer to vram.
+ *
+ * Takes the overlay lock.
+ */
+int vmw_overlay_pause_all(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, ret;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		if (overlay->stream[i].paused)
+			DRM_INFO("%s: *warning* stream %i already paused\n",
+				 __func__, i);
+		ret = vmw_overlay_stop(dev_priv, i, true, false);
+		WARN_ON(ret != 0);
+	}
+
+	mutex_unlock(&overlay->mutex);
+
+	return 0;
+}
+
+int vmw_overlay_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv)
+{
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	struct drm_vmw_control_stream_arg *arg =
+	    (struct drm_vmw_control_stream_arg *)data;
+	struct vmw_dma_buffer *buf;
+	struct vmw_resource *res;
+	int ret;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	ret = vmw_user_stream_lookup(dev_priv, tfile, &arg->stream_id, &res);
+	if (ret)
+		return ret;
+
+	mutex_lock(&overlay->mutex);
+
+	if (!arg->enabled) {
+		ret = vmw_overlay_stop(dev_priv, arg->stream_id, false, true);
+		goto out_unlock;
+	}
+
+	ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf);
+	if (ret)
+		goto out_unlock;
+
+	ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
+
+	vmw_dmabuf_unreference(&buf);
+
+out_unlock:
+	mutex_unlock(&overlay->mutex);
+	vmw_resource_unreference(&res);
+
+	return ret;
+}
+
+int vmw_overlay_num_overlays(struct vmw_private *dev_priv)
+{
+	if (!dev_priv->overlay_priv)
+		return 0;
+
+	return VMW_MAX_NUM_STREAMS;
+}
+
+int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i, k;
+
+	if (!overlay)
+		return 0;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0, k = 0; i < VMW_MAX_NUM_STREAMS; i++)
+		if (!overlay->stream[i].claimed)
+			k++;
+
+	mutex_unlock(&overlay->mutex);
+
+	return k;
+}
+
+int vmw_overlay_claim(struct vmw_private *dev_priv, uint32_t *out)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	int i;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	mutex_lock(&overlay->mutex);
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+
+		if (overlay->stream[i].claimed)
+			continue;
+
+		overlay->stream[i].claimed = true;
+		*out = i;
+		mutex_unlock(&overlay->mutex);
+		return 0;
+	}
+
+	mutex_unlock(&overlay->mutex);
+	return -ESRCH;
+}
+
+int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+
+	BUG_ON(stream_id >= VMW_MAX_NUM_STREAMS);
+
+	if (!overlay)
+		return -ENOSYS;
+
+	mutex_lock(&overlay->mutex);
+
+	WARN_ON(!overlay->stream[stream_id].claimed);
+	vmw_overlay_stop(dev_priv, stream_id, false, false);
+	overlay->stream[stream_id].claimed = false;
+
+	mutex_unlock(&overlay->mutex);
+	return 0;
+}
+
+int vmw_overlay_init(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay;
+	int i;
+
+	if (dev_priv->overlay_priv)
+		return -EINVAL;
+
+	if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_VIDEO) &&
+	     (dev_priv->fifo.capabilities & SVGA_FIFO_CAP_ESCAPE)) {
+		DRM_INFO("hardware doesn't support overlays\n");
+		return -ENOSYS;
+	}
+
+	overlay = kmalloc(GFP_KERNEL, sizeof(*overlay));
+	if (!overlay)
+		return -ENOMEM;
+
+	memset(overlay, 0, sizeof(*overlay));
+	mutex_init(&overlay->mutex);
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		overlay->stream[i].buf = NULL;
+		overlay->stream[i].paused = false;
+		overlay->stream[i].claimed = false;
+	}
+
+	dev_priv->overlay_priv = overlay;
+
+	return 0;
+}
+
+int vmw_overlay_close(struct vmw_private *dev_priv)
+{
+	struct vmw_overlay *overlay = dev_priv->overlay_priv;
+	bool forgotten_buffer = false;
+	int i;
+
+	if (!overlay)
+		return -ENOSYS;
+
+	for (i = 0; i < VMW_MAX_NUM_STREAMS; i++) {
+		if (overlay->stream[i].buf) {
+			forgotten_buffer = true;
+			vmw_overlay_stop(dev_priv, i, false, false);
+		}
+	}
+
+	WARN_ON(forgotten_buffer);
+
+	dev_priv->overlay_priv = NULL;
+	kfree(overlay);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_reg.h b/drivers/gpu/drm/vmwgfx/vmwgfx_reg.h
new file mode 100644
index 0000000..9d0dd3a
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_reg.h
@@ -0,0 +1,57 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/**
+ * This file contains virtual hardware defines for kernel space.
+ */
+
+#ifndef _VMWGFX_REG_H_
+#define _VMWGFX_REG_H_
+
+#include <linux/types.h>
+
+#define VMWGFX_INDEX_PORT     0x0
+#define VMWGFX_VALUE_PORT     0x1
+#define VMWGFX_IRQSTATUS_PORT 0x8
+
+struct svga_guest_mem_descriptor {
+	__le32 ppn;
+	__le32 num_pages;
+};
+
+struct svga_fifo_cmd_fence {
+	__le32 fence;
+};
+
+#define SVGA_SYNC_GENERIC         1
+#define SVGA_SYNC_FIFOFULL        2
+
+#include "svga_types.h"
+
+#include "svga3d_reg.h"
+
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
new file mode 100644
index 0000000..a1ceed0
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -0,0 +1,1192 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "vmwgfx_drv.h"
+#include "vmwgfx_drm.h"
+#include "ttm/ttm_object.h"
+#include "ttm/ttm_placement.h"
+#include "drmP.h"
+
+#define VMW_RES_CONTEXT ttm_driver_type0
+#define VMW_RES_SURFACE ttm_driver_type1
+#define VMW_RES_STREAM ttm_driver_type2
+
+struct vmw_user_context {
+	struct ttm_base_object base;
+	struct vmw_resource res;
+};
+
+struct vmw_user_surface {
+	struct ttm_base_object base;
+	struct vmw_surface srf;
+};
+
+struct vmw_user_dma_buffer {
+	struct ttm_base_object base;
+	struct vmw_dma_buffer dma;
+};
+
+struct vmw_bo_user_rep {
+	uint32_t handle;
+	uint64_t map_handle;
+};
+
+struct vmw_stream {
+	struct vmw_resource res;
+	uint32_t stream_id;
+};
+
+struct vmw_user_stream {
+	struct ttm_base_object base;
+	struct vmw_stream stream;
+};
+
+static inline struct vmw_dma_buffer *
+vmw_dma_buffer(struct ttm_buffer_object *bo)
+{
+	return container_of(bo, struct vmw_dma_buffer, base);
+}
+
+static inline struct vmw_user_dma_buffer *
+vmw_user_dma_buffer(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	return container_of(vmw_bo, struct vmw_user_dma_buffer, dma);
+}
+
+struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
+{
+	kref_get(&res->kref);
+	return res;
+}
+
+static void vmw_resource_release(struct kref *kref)
+{
+	struct vmw_resource *res =
+	    container_of(kref, struct vmw_resource, kref);
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	idr_remove(res->idr, res->id);
+	write_unlock(&dev_priv->resource_lock);
+
+	if (likely(res->hw_destroy != NULL))
+		res->hw_destroy(res);
+
+	if (res->res_free != NULL)
+		res->res_free(res);
+	else
+		kfree(res);
+
+	write_lock(&dev_priv->resource_lock);
+}
+
+void vmw_resource_unreference(struct vmw_resource **p_res)
+{
+	struct vmw_resource *res = *p_res;
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	*p_res = NULL;
+	write_lock(&dev_priv->resource_lock);
+	kref_put(&res->kref, vmw_resource_release);
+	write_unlock(&dev_priv->resource_lock);
+}
+
+static int vmw_resource_init(struct vmw_private *dev_priv,
+			     struct vmw_resource *res,
+			     struct idr *idr,
+			     enum ttm_object_type obj_type,
+			     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+
+	kref_init(&res->kref);
+	res->hw_destroy = NULL;
+	res->res_free = res_free;
+	res->res_type = obj_type;
+	res->idr = idr;
+	res->avail = false;
+	res->dev_priv = dev_priv;
+
+	do {
+		if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
+			return -ENOMEM;
+
+		write_lock(&dev_priv->resource_lock);
+		ret = idr_get_new_above(idr, res, 1, &res->id);
+		write_unlock(&dev_priv->resource_lock);
+
+	} while (ret == -EAGAIN);
+
+	return ret;
+}
+
+/**
+ * vmw_resource_activate
+ *
+ * @res:        Pointer to the newly created resource
+ * @hw_destroy: Destroy function. NULL if none.
+ *
+ * Activate a resource after the hardware has been made aware of it.
+ * Set tye destroy function to @destroy. Typically this frees the
+ * resource and destroys the hardware resources associated with it.
+ * Activate basically means that the function vmw_resource_lookup will
+ * find it.
+ */
+
+static void vmw_resource_activate(struct vmw_resource *res,
+				  void (*hw_destroy) (struct vmw_resource *))
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+
+	write_lock(&dev_priv->resource_lock);
+	res->avail = true;
+	res->hw_destroy = hw_destroy;
+	write_unlock(&dev_priv->resource_lock);
+}
+
+struct vmw_resource *vmw_resource_lookup(struct vmw_private *dev_priv,
+					 struct idr *idr, int id)
+{
+	struct vmw_resource *res;
+
+	read_lock(&dev_priv->resource_lock);
+	res = idr_find(idr, id);
+	if (res && res->avail)
+		kref_get(&res->kref);
+	else
+		res = NULL;
+	read_unlock(&dev_priv->resource_lock);
+
+	if (unlikely(res == NULL))
+		return NULL;
+
+	return res;
+}
+
+/**
+ * Context management:
+ */
+
+static void vmw_hw_context_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDestroyContext body;
+	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "destruction.\n");
+		return;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DESTROY);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+}
+
+static int vmw_context_init(struct vmw_private *dev_priv,
+			    struct vmw_resource *res,
+			    void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDefineContext body;
+	} *cmd;
+
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr,
+				VMW_RES_CONTEXT, res_free);
+
+	if (unlikely(ret != 0)) {
+		if (res_free == NULL)
+			kfree(res);
+		else
+			res_free(res);
+		return ret;
+	}
+
+	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_CONTEXT_DEFINE);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.cid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+	vmw_resource_activate(res, vmw_hw_context_destroy);
+	return 0;
+}
+
+struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
+{
+	struct vmw_resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
+	int ret;
+
+	if (unlikely(res == NULL))
+		return NULL;
+
+	ret = vmw_context_init(dev_priv, res, NULL);
+	return (ret == 0) ? res : NULL;
+}
+
+/**
+ * User-space context management:
+ */
+
+static void vmw_user_context_free(struct vmw_resource *res)
+{
+	struct vmw_user_context *ctx =
+	    container_of(res, struct vmw_user_context, res);
+
+	kfree(ctx);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_context_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_context *ctx =
+	    container_of(base, struct vmw_user_context, base);
+	struct vmw_resource *res = &ctx->res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_resource *res;
+	struct vmw_user_context *ctx;
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret = 0;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_context_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ctx = container_of(res, struct vmw_user_context, res);
+	if (ctx->base.tfile != tfile && !ctx->base.shareable) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE);
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_context_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+
+	if (unlikely(ctx == NULL))
+		return -ENOMEM;
+
+	res = &ctx->res;
+	ctx->base.shareable = false;
+	ctx->base.tfile = NULL;
+
+	ret = vmw_context_init(dev_priv, res, vmw_user_context_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(&ctx->res);
+	ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
+				   &vmw_user_context_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		goto out_err;
+	}
+
+	arg->cid = res->id;
+out_err:
+	vmw_resource_unreference(&res);
+	return ret;
+
+}
+
+int vmw_context_check(struct vmw_private *dev_priv,
+		      struct ttm_object_file *tfile,
+		      int id)
+{
+	struct vmw_resource *res;
+	int ret = 0;
+
+	read_lock(&dev_priv->resource_lock);
+	res = idr_find(&dev_priv->context_idr, id);
+	if (res && res->avail) {
+		struct vmw_user_context *ctx =
+			container_of(res, struct vmw_user_context, res);
+		if (ctx->base.tfile != tfile && !ctx->base.shareable)
+			ret = -EPERM;
+	} else
+		ret = -EINVAL;
+	read_unlock(&dev_priv->resource_lock);
+
+	return ret;
+}
+
+
+/**
+ * Surface management.
+ */
+
+static void vmw_hw_surface_destroy(struct vmw_resource *res)
+{
+
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDestroySurface body;
+	} *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
+
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Failed reserving FIFO space for surface "
+			  "destruction.\n");
+		return;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY);
+	cmd->header.size = cpu_to_le32(sizeof(cmd->body));
+	cmd->body.sid = cpu_to_le32(res->id);
+
+	vmw_fifo_commit(dev_priv, sizeof(*cmd));
+}
+
+void vmw_surface_res_free(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+
+	kfree(srf->sizes);
+	kfree(srf->snooper.image);
+	kfree(srf);
+}
+
+int vmw_surface_init(struct vmw_private *dev_priv,
+		     struct vmw_surface *srf,
+		     void (*res_free) (struct vmw_resource *res))
+{
+	int ret;
+	struct {
+		SVGA3dCmdHeader header;
+		SVGA3dCmdDefineSurface body;
+	} *cmd;
+	SVGA3dSize *cmd_size;
+	struct vmw_resource *res = &srf->res;
+	struct drm_vmw_size *src_size;
+	size_t submit_size;
+	uint32_t cmd_len;
+	int i;
+
+	BUG_ON(res_free == NULL);
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr,
+				VMW_RES_SURFACE, res_free);
+
+	if (unlikely(ret != 0)) {
+		res_free(res);
+		return ret;
+	}
+
+	submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize);
+	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
+
+	cmd = vmw_fifo_reserve(dev_priv, submit_size);
+	if (unlikely(cmd == NULL)) {
+		DRM_ERROR("Fifo reserve failed for create surface.\n");
+		vmw_resource_unreference(&res);
+		return -ENOMEM;
+	}
+
+	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE);
+	cmd->header.size = cpu_to_le32(cmd_len);
+	cmd->body.sid = cpu_to_le32(res->id);
+	cmd->body.surfaceFlags = cpu_to_le32(srf->flags);
+	cmd->body.format = cpu_to_le32(srf->format);
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
+		cmd->body.face[i].numMipLevels =
+		    cpu_to_le32(srf->mip_levels[i]);
+	}
+
+	cmd += 1;
+	cmd_size = (SVGA3dSize *) cmd;
+	src_size = srf->sizes;
+
+	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
+		cmd_size->width = cpu_to_le32(src_size->width);
+		cmd_size->height = cpu_to_le32(src_size->height);
+		cmd_size->depth = cpu_to_le32(src_size->depth);
+	}
+
+	vmw_fifo_commit(dev_priv, submit_size);
+	vmw_resource_activate(res, vmw_hw_surface_destroy);
+	return 0;
+}
+
+static void vmw_user_surface_free(struct vmw_resource *res)
+{
+	struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
+	struct vmw_user_surface *user_srf =
+	    container_of(srf, struct vmw_user_surface, srf);
+
+	kfree(srf->sizes);
+	kfree(srf->snooper.image);
+	kfree(user_srf);
+}
+
+int vmw_user_surface_lookup(struct vmw_private *dev_priv,
+			    struct ttm_object_file *tfile,
+			    int sid, struct vmw_surface **out)
+{
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, sid);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_surface_free)
+		return -EINVAL;
+
+	srf = container_of(res, struct vmw_surface, res);
+	user_srf = container_of(srf, struct vmw_user_surface, srf);
+	if (user_srf->base.tfile != tfile && !user_srf->base.shareable)
+		return -EPERM;
+
+	*out = srf;
+	return 0;
+}
+
+static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_surface *user_srf =
+	    container_of(base, struct vmw_user_surface, base);
+	struct vmw_resource *res = &user_srf->srf.res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret = 0;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, arg->sid);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_surface_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	srf = container_of(res, struct vmw_surface, res);
+	user_srf = container_of(srf, struct vmw_user_surface, srf);
+	if (user_srf->base.tfile != tfile && !user_srf->base.shareable) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	ttm_ref_object_base_unref(tfile, user_srf->base.hash.key,
+				  TTM_REF_USAGE);
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_surface *user_srf =
+	    kmalloc(sizeof(*user_srf), GFP_KERNEL);
+	struct vmw_surface *srf;
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	union drm_vmw_surface_create_arg *arg =
+	    (union drm_vmw_surface_create_arg *)data;
+	struct drm_vmw_surface_create_req *req = &arg->req;
+	struct drm_vmw_surface_arg *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct drm_vmw_size __user *user_sizes;
+	int ret;
+	int i;
+
+	if (unlikely(user_srf == NULL))
+		return -ENOMEM;
+
+	srf = &user_srf->srf;
+	res = &srf->res;
+
+	srf->flags = req->flags;
+	srf->format = req->format;
+	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
+	srf->num_sizes = 0;
+	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
+		srf->num_sizes += srf->mip_levels[i];
+
+	if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES *
+	    DRM_VMW_MAX_MIP_LEVELS) {
+		ret = -EINVAL;
+		goto out_err0;
+	}
+
+	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
+	if (unlikely(srf->sizes == NULL)) {
+		ret = -ENOMEM;
+		goto out_err0;
+	}
+
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    req->size_addr;
+
+	ret = copy_from_user(srf->sizes, user_sizes,
+			     srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	user_srf->base.shareable = false;
+	user_srf->base.tfile = NULL;
+
+	/**
+	 * From this point, the generic resource management functions
+	 * destroy the object on failure.
+	 */
+
+	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(&srf->res);
+	ret = ttm_base_object_init(tfile, &user_srf->base,
+				   req->shareable, VMW_RES_SURFACE,
+				   &vmw_user_surface_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		vmw_resource_unreference(&res);
+		return ret;
+	}
+
+	if (srf->flags & (1 << 9) &&
+	    srf->num_sizes == 1 &&
+	    srf->sizes[0].width == 64 &&
+	    srf->sizes[0].height == 64 &&
+	    srf->format == SVGA3D_A8R8G8B8) {
+
+		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
+		/* clear the image */
+		if (srf->snooper.image)
+			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
+		else
+			DRM_ERROR("Failed to allocate cursor_image\n");
+
+	} else {
+		srf->snooper.image = NULL;
+	}
+	srf->snooper.crtc = NULL;
+
+	rep->sid = res->id;
+	vmw_resource_unreference(&res);
+	return 0;
+out_err1:
+	kfree(srf->sizes);
+out_err0:
+	kfree(user_srf);
+	return ret;
+}
+
+int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	union drm_vmw_surface_reference_arg *arg =
+	    (union drm_vmw_surface_reference_arg *)data;
+	struct drm_vmw_surface_arg *req = &arg->req;
+	struct drm_vmw_surface_create_req *rep = &arg->rep;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	struct vmw_resource *res;
+	struct vmw_surface *srf;
+	struct vmw_user_surface *user_srf;
+	struct drm_vmw_size __user *user_sizes;
+	int ret;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, req->sid);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_surface_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	srf = container_of(res, struct vmw_surface, res);
+	user_srf = container_of(srf, struct vmw_user_surface, srf);
+	if (user_srf->base.tfile != tfile && !user_srf->base.shareable) {
+		DRM_ERROR("Tried to reference none shareable surface\n");
+		ret = -EPERM;
+		goto out;
+	}
+
+	ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Could not add a reference to a surface.\n");
+		goto out;
+	}
+
+	rep->flags = srf->flags;
+	rep->format = srf->format;
+	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
+	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
+	    rep->size_addr;
+
+	if (user_sizes)
+		ret = copy_to_user(user_sizes, srf->sizes,
+				   srf->num_sizes * sizeof(*srf->sizes));
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("copy_to_user failed %p %u\n",
+			  user_sizes, srf->num_sizes);
+		/**
+		 * FIXME: Unreference surface here?
+		 */
+		goto out;
+	}
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_surface_check(struct vmw_private *dev_priv,
+		      struct ttm_object_file *tfile,
+		      int id)
+{
+	struct vmw_resource *res;
+	int ret = 0;
+
+	read_lock(&dev_priv->resource_lock);
+	res = idr_find(&dev_priv->surface_idr, id);
+	if (res && res->avail) {
+		struct vmw_surface *srf =
+			container_of(res, struct vmw_surface, res);
+		struct vmw_user_surface *usrf =
+			container_of(srf, struct vmw_user_surface, srf);
+
+		if (usrf->base.tfile != tfile && !usrf->base.shareable)
+			ret = -EPERM;
+	} else
+		ret = -EINVAL;
+	read_unlock(&dev_priv->resource_lock);
+
+	return ret;
+}
+
+/**
+ * Buffer management.
+ */
+
+static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob,
+				  unsigned long num_pages)
+{
+	static size_t bo_user_size = ~0;
+
+	size_t page_array_size =
+	    (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
+
+	if (unlikely(bo_user_size == ~0)) {
+		bo_user_size = glob->ttm_bo_extra_size +
+		    ttm_round_pot(sizeof(struct vmw_dma_buffer));
+	}
+
+	return bo_user_size + page_array_size;
+}
+
+void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	struct ttm_bo_global *glob = bo->glob;
+	struct vmw_private *dev_priv =
+		container_of(bo->bdev, struct vmw_private, bdev);
+
+	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
+	if (vmw_bo->gmr_bound) {
+		vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
+		spin_unlock(&glob->lru_lock);
+	}
+	kfree(vmw_bo);
+}
+
+int vmw_dmabuf_init(struct vmw_private *dev_priv,
+		    struct vmw_dma_buffer *vmw_bo,
+		    size_t size, struct ttm_placement *placement,
+		    bool interruptible,
+		    void (*bo_free) (struct ttm_buffer_object *bo))
+{
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	size_t acc_size;
+	int ret;
+
+	BUG_ON(!bo_free);
+
+	acc_size =
+	    vmw_dmabuf_acc_size(bdev->glob,
+				(size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+	if (unlikely(ret != 0)) {
+		/* we must free the bo here as
+		 * ttm_buffer_object_init does so as well */
+		bo_free(&vmw_bo->base);
+		return ret;
+	}
+
+	memset(vmw_bo, 0, sizeof(*vmw_bo));
+
+	INIT_LIST_HEAD(&vmw_bo->gmr_lru);
+	INIT_LIST_HEAD(&vmw_bo->validate_list);
+	vmw_bo->gmr_id = 0;
+	vmw_bo->gmr_bound = false;
+
+	ret = ttm_bo_init(bdev, &vmw_bo->base, size,
+			  ttm_bo_type_device, placement,
+			  0, 0, interruptible,
+			  NULL, acc_size, bo_free);
+	return ret;
+}
+
+static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
+	struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma;
+	struct ttm_bo_global *glob = bo->glob;
+	struct vmw_private *dev_priv =
+		container_of(bo->bdev, struct vmw_private, bdev);
+
+	ttm_mem_global_free(glob->mem_glob, bo->acc_size);
+	if (vmw_bo->gmr_bound) {
+		vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id);
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id);
+		spin_unlock(&glob->lru_lock);
+	}
+	kfree(vmw_user_bo);
+}
+
+static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_base_object *base = *p_base;
+	struct ttm_buffer_object *bo;
+
+	*p_base = NULL;
+
+	if (unlikely(base == NULL))
+		return;
+
+	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
+	bo = &vmw_user_bo->dma.base;
+	ttm_bo_unref(&bo);
+}
+
+int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	union drm_vmw_alloc_dmabuf_arg *arg =
+	    (union drm_vmw_alloc_dmabuf_arg *)data;
+	struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
+	struct drm_vmw_dmabuf_rep *rep = &arg->rep;
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_buffer_object *tmp;
+	struct vmw_master *vmaster = vmw_master(file_priv->master);
+	int ret;
+
+	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
+	if (unlikely(vmw_user_bo == NULL))
+		return -ENOMEM;
+
+	ret = ttm_read_lock(&vmaster->lock, true);
+	if (unlikely(ret != 0)) {
+		kfree(vmw_user_bo);
+		return ret;
+	}
+
+	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size,
+			      &vmw_vram_placement, true,
+			      &vmw_user_dmabuf_destroy);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
+	ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
+				   &vmw_user_bo->base,
+				   false,
+				   ttm_buffer_type,
+				   &vmw_user_dmabuf_release, NULL);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unref(&tmp);
+	} else {
+		rep->handle = vmw_user_bo->base.hash.key;
+		rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
+		rep->cur_gmr_id = vmw_user_bo->base.hash.key;
+		rep->cur_gmr_offset = 0;
+	}
+	ttm_bo_unref(&tmp);
+
+	ttm_read_unlock(&vmaster->lock);
+
+	return 0;
+}
+
+int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_vmw_unref_dmabuf_arg *arg =
+	    (struct drm_vmw_unref_dmabuf_arg *)data;
+
+	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+					 arg->handle,
+					 TTM_REF_USAGE);
+}
+
+uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
+				  uint32_t cur_validate_node)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+
+	if (likely(vmw_bo->on_validate_list))
+		return vmw_bo->cur_validate_node;
+
+	vmw_bo->cur_validate_node = cur_validate_node;
+	vmw_bo->on_validate_list = true;
+
+	return cur_validate_node;
+}
+
+void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+
+	vmw_bo->on_validate_list = false;
+}
+
+uint32_t vmw_dmabuf_gmr(struct ttm_buffer_object *bo)
+{
+	struct vmw_dma_buffer *vmw_bo;
+
+	if (bo->mem.mem_type == TTM_PL_VRAM)
+		return SVGA_GMR_FRAMEBUFFER;
+
+	vmw_bo = vmw_dma_buffer(bo);
+
+	return (vmw_bo->gmr_bound) ? vmw_bo->gmr_id : SVGA_GMR_NULL;
+}
+
+void vmw_dmabuf_set_gmr(struct ttm_buffer_object *bo, uint32_t id)
+{
+	struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
+	vmw_bo->gmr_bound = true;
+	vmw_bo->gmr_id = id;
+}
+
+int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
+			   uint32_t handle, struct vmw_dma_buffer **out)
+{
+	struct vmw_user_dma_buffer *vmw_user_bo;
+	struct ttm_base_object *base;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return -ESRCH;
+	}
+
+	if (unlikely(base->object_type != ttm_buffer_type)) {
+		ttm_base_object_unref(&base);
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return -EINVAL;
+	}
+
+	vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base);
+	(void)ttm_bo_reference(&vmw_user_bo->dma.base);
+	ttm_base_object_unref(&base);
+	*out = &vmw_user_bo->dma;
+
+	return 0;
+}
+
+/**
+ * TODO: Implement a gmr id eviction mechanism. Currently we just fail
+ * when we're out of ids, causing GMR space to be allocated
+ * out of VRAM.
+ */
+
+int vmw_gmr_id_alloc(struct vmw_private *dev_priv, uint32_t *p_id)
+{
+	struct ttm_bo_global *glob = dev_priv->bdev.glob;
+	int id;
+	int ret;
+
+	do {
+		if (unlikely(ida_pre_get(&dev_priv->gmr_ida, GFP_KERNEL) == 0))
+			return -ENOMEM;
+
+		spin_lock(&glob->lru_lock);
+		ret = ida_get_new(&dev_priv->gmr_ida, &id);
+		spin_unlock(&glob->lru_lock);
+	} while (ret == -EAGAIN);
+
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (unlikely(id >= dev_priv->max_gmr_ids)) {
+		spin_lock(&glob->lru_lock);
+		ida_remove(&dev_priv->gmr_ida, id);
+		spin_unlock(&glob->lru_lock);
+		return -EBUSY;
+	}
+
+	*p_id = (uint32_t) id;
+	return 0;
+}
+
+/*
+ * Stream managment
+ */
+
+static void vmw_stream_destroy(struct vmw_resource *res)
+{
+	struct vmw_private *dev_priv = res->dev_priv;
+	struct vmw_stream *stream;
+	int ret;
+
+	DRM_INFO("%s: unref\n", __func__);
+	stream = container_of(res, struct vmw_stream, res);
+
+	ret = vmw_overlay_unref(dev_priv, stream->stream_id);
+	WARN_ON(ret != 0);
+}
+
+static int vmw_stream_init(struct vmw_private *dev_priv,
+			   struct vmw_stream *stream,
+			   void (*res_free) (struct vmw_resource *res))
+{
+	struct vmw_resource *res = &stream->res;
+	int ret;
+
+	ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr,
+				VMW_RES_STREAM, res_free);
+
+	if (unlikely(ret != 0)) {
+		if (res_free == NULL)
+			kfree(stream);
+		else
+			res_free(&stream->res);
+		return ret;
+	}
+
+	ret = vmw_overlay_claim(dev_priv, &stream->stream_id);
+	if (ret) {
+		vmw_resource_unreference(&res);
+		return ret;
+	}
+
+	DRM_INFO("%s: claimed\n", __func__);
+
+	vmw_resource_activate(&stream->res, vmw_stream_destroy);
+	return 0;
+}
+
+/**
+ * User-space context management:
+ */
+
+static void vmw_user_stream_free(struct vmw_resource *res)
+{
+	struct vmw_user_stream *stream =
+	    container_of(res, struct vmw_user_stream, stream.res);
+
+	kfree(stream);
+}
+
+/**
+ * This function is called when user space has no more references on the
+ * base object. It releases the base-object's reference on the resource object.
+ */
+
+static void vmw_user_stream_base_release(struct ttm_base_object **p_base)
+{
+	struct ttm_base_object *base = *p_base;
+	struct vmw_user_stream *stream =
+	    container_of(base, struct vmw_user_stream, base);
+	struct vmw_resource *res = &stream->stream.res;
+
+	*p_base = NULL;
+	vmw_resource_unreference(&res);
+}
+
+int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_resource *res;
+	struct vmw_user_stream *stream;
+	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret = 0;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_stream_free) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	stream = container_of(res, struct vmw_user_stream, stream.res);
+	if (stream->base.tfile != tfile) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ttm_ref_object_base_unref(tfile, stream->base.hash.key, TTM_REF_USAGE);
+out:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct vmw_private *dev_priv = vmw_priv(dev);
+	struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL);
+	struct vmw_resource *res;
+	struct vmw_resource *tmp;
+	struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
+	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+	int ret;
+
+	if (unlikely(stream == NULL))
+		return -ENOMEM;
+
+	res = &stream->stream.res;
+	stream->base.shareable = false;
+	stream->base.tfile = NULL;
+
+	ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free);
+	if (unlikely(ret != 0))
+		return ret;
+
+	tmp = vmw_resource_reference(res);
+	ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM,
+				   &vmw_user_stream_base_release, NULL);
+
+	if (unlikely(ret != 0)) {
+		vmw_resource_unreference(&tmp);
+		goto out_err;
+	}
+
+	arg->stream_id = res->id;
+out_err:
+	vmw_resource_unreference(&res);
+	return ret;
+}
+
+int vmw_user_stream_lookup(struct vmw_private *dev_priv,
+			   struct ttm_object_file *tfile,
+			   uint32_t *inout_id, struct vmw_resource **out)
+{
+	struct vmw_user_stream *stream;
+	struct vmw_resource *res;
+	int ret;
+
+	res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id);
+	if (unlikely(res == NULL))
+		return -EINVAL;
+
+	if (res->res_free != &vmw_user_stream_free) {
+		ret = -EINVAL;
+		goto err_ref;
+	}
+
+	stream = container_of(res, struct vmw_user_stream, stream.res);
+	if (stream->base.tfile != tfile) {
+		ret = -EPERM;
+		goto err_ref;
+	}
+
+	*inout_id = stream->stream.stream_id;
+	*out = res;
+	return 0;
+err_ref:
+	vmw_resource_unreference(&res);
+	return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
new file mode 100644
index 0000000..e3df4ad
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
@@ -0,0 +1,99 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "drmP.h"
+#include "vmwgfx_drv.h"
+
+int vmw_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct vmw_private *dev_priv;
+
+	if (unlikely(vma->vm_pgoff < VMWGFX_FILE_PAGE_OFFSET)) {
+		if (vmw_fifo_mmap(filp, vma) == 0)
+			return 0;
+		return drm_mmap(filp, vma);
+	}
+
+	file_priv = (struct drm_file *)filp->private_data;
+	dev_priv = vmw_priv(file_priv->minor->dev);
+	return ttm_bo_mmap(filp, vma, &dev_priv->bdev);
+}
+
+static int vmw_ttm_mem_global_init(struct ttm_global_reference *ref)
+{
+	DRM_INFO("global init.\n");
+	return ttm_mem_global_init(ref->object);
+}
+
+static void vmw_ttm_mem_global_release(struct ttm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+int vmw_ttm_global_init(struct vmw_private *dev_priv)
+{
+	struct ttm_global_reference *global_ref;
+	int ret;
+
+	global_ref = &dev_priv->mem_global_ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &vmw_ttm_mem_global_init;
+	global_ref->release = &vmw_ttm_mem_global_release;
+
+	ret = ttm_global_item_ref(global_ref);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM memory accounting.\n");
+		return ret;
+	}
+
+	dev_priv->bo_global_ref.mem_glob =
+		dev_priv->mem_global_ref.object;
+	global_ref = &dev_priv->bo_global_ref.ref;
+	global_ref->global_type = TTM_GLOBAL_TTM_BO;
+	global_ref->size = sizeof(struct ttm_bo_global);
+	global_ref->init = &ttm_bo_global_init;
+	global_ref->release = &ttm_bo_global_release;
+		ret = ttm_global_item_ref(global_ref);
+
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed setting up TTM buffer objects.\n");
+		goto out_no_bo;
+	}
+
+	return 0;
+out_no_bo:
+	ttm_global_item_unref(&dev_priv->mem_global_ref);
+	return ret;
+}
+
+void vmw_ttm_global_release(struct vmw_private *dev_priv)
+{
+	ttm_global_item_unref(&dev_priv->bo_global_ref.ref);
+	ttm_global_item_unref(&dev_priv->mem_global_ref);
+}
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index 27ae750..bf31592 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -1,8 +1,6 @@
 #ifndef __HID_LG_H
 #define __HID_LG_H
 
-#include <linux/autoconf.h>
-
 #ifdef CONFIG_LOGITECH_FF
 int lgff_init(struct hid_device *hdev);
 #else
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 95ccbe3..46c3c56 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -228,6 +228,18 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called k8temp.
 
+config SENSORS_K10TEMP
+	tristate "AMD Phenom/Sempron/Turion/Opteron temperature sensor"
+	depends on X86 && PCI
+	help
+	  If you say yes here you get support for the temperature
+	  sensor(s) inside your CPU. Supported are later revisions of
+	  the AMD Family 10h and all revisions of the AMD Family 11h
+	  microarchitectures.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called k10temp.
+
 config SENSORS_AMS
 	tristate "Apple Motion Sensor driver"
 	depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
@@ -810,6 +822,14 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp421.
 
+config SENSORS_VIA_CPUTEMP
+	tristate "VIA CPU temperature sensor"
+	depends on X86
+	help
+	  If you say yes here you get support for the temperature
+	  sensor inside your CPU. Supported are all known variants of
+	  the VIA C7 and Nano.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on PCI
@@ -998,6 +1018,23 @@
 	  will be called lis3lv02d and a specific module for the SPI transport
 	  is called lis3lv02d_spi.
 
+config SENSORS_LIS3_I2C
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
+	depends on I2C && INPUT
+	select INPUT_POLLDEV
+	default n
+	help
+	  This driver provides support for the LIS3LV02Dx accelerometer connected
+	  via I2C. The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the device to act as a pinball machine-esque joystick.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for the I2C transport
+	  is called lis3lv02d_i2c.
+
 config SENSORS_APPLESMC
 	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
 	depends on INPUT && X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 33c2ee1..450c8e8 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -53,8 +53,10 @@
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
+obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
 obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
 obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
+obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
@@ -87,6 +89,7 @@
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
+obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
new file mode 100644
index 0000000..d8a26d1
--- /dev/null
+++ b/drivers/hwmon/k10temp.c
@@ -0,0 +1,197 @@
+/*
+ * k10temp.c - AMD Family 10h/11h processor hardware monitoring
+ *
+ * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
+ *
+ *
+ * This driver is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This driver is distributed in 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 driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <asm/processor.h>
+
+MODULE_DESCRIPTION("AMD Family 10h/11h CPU core temperature monitor");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL");
+
+static bool force;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
+
+#define REG_HARDWARE_THERMAL_CONTROL	0x64
+#define  HTC_ENABLE			0x00000001
+
+#define REG_REPORTED_TEMPERATURE	0xa4
+
+#define REG_NORTHBRIDGE_CAPABILITIES	0xe8
+#define  NB_CAP_HTC			0x00000400
+
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	u32 regval;
+
+	pci_read_config_dword(to_pci_dev(dev),
+			      REG_REPORTED_TEMPERATURE, &regval);
+	return sprintf(buf, "%u\n", (regval >> 21) * 125);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", 70 * 1000);
+}
+
+static ssize_t show_temp_crit(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int show_hyst = attr->index;
+	u32 regval;
+	int value;
+
+	pci_read_config_dword(to_pci_dev(dev),
+			      REG_HARDWARE_THERMAL_CONTROL, &regval);
+	value = ((regval >> 16) & 0x7f) * 500 + 52000;
+	if (show_hyst)
+		value -= ((regval >> 24) & 0xf) * 500;
+	return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "k10temp\n");
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static bool __devinit has_erratum_319(void)
+{
+	/*
+	 * Erratum 319: The thermal sensor of older Family 10h processors
+	 *              (B steppings) may be unreliable.
+	 */
+	return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
+}
+
+static int __devinit k10temp_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct device *hwmon_dev;
+	u32 reg_caps, reg_htc;
+	int err;
+
+	if (has_erratum_319() && !force) {
+		dev_err(&pdev->dev,
+			"unreliable CPU thermal sensor; monitoring disabled\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_temp1_input);
+	if (err)
+		goto exit;
+	err = device_create_file(&pdev->dev, &dev_attr_temp1_max);
+	if (err)
+		goto exit_remove;
+
+	pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, &reg_caps);
+	pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, &reg_htc);
+	if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) {
+		err = device_create_file(&pdev->dev,
+				&sensor_dev_attr_temp1_crit.dev_attr);
+		if (err)
+			goto exit_remove;
+		err = device_create_file(&pdev->dev,
+				&sensor_dev_attr_temp1_crit_hyst.dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
+		goto exit_remove;
+
+	hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(hwmon_dev)) {
+		err = PTR_ERR(hwmon_dev);
+		goto exit_remove;
+	}
+	dev_set_drvdata(&pdev->dev, hwmon_dev);
+
+	if (has_erratum_319() && force)
+		dev_warn(&pdev->dev,
+			 "unreliable CPU thermal sensor; check erratum 319\n");
+	return 0;
+
+exit_remove:
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	device_remove_file(&pdev->dev, &dev_attr_temp1_input);
+	device_remove_file(&pdev->dev, &dev_attr_temp1_max);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_crit.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+exit:
+	return err;
+}
+
+static void __devexit k10temp_remove(struct pci_dev *pdev)
+{
+	hwmon_device_unregister(dev_get_drvdata(&pdev->dev));
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	device_remove_file(&pdev->dev, &dev_attr_temp1_input);
+	device_remove_file(&pdev->dev, &dev_attr_temp1_max);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_crit.dev_attr);
+	device_remove_file(&pdev->dev,
+			   &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+	dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static struct pci_device_id k10temp_id_table[] = {
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
+	{}
+};
+MODULE_DEVICE_TABLE(pci, k10temp_id_table);
+
+static struct pci_driver k10temp_driver = {
+	.name = "k10temp",
+	.id_table = k10temp_id_table,
+	.probe = k10temp_probe,
+	.remove = __devexit_p(k10temp_remove),
+};
+
+static int __init k10temp_init(void)
+{
+	return pci_register_driver(&k10temp_driver);
+}
+
+static void __exit k10temp_exit(void)
+{
+	pci_unregister_driver(&k10temp_driver);
+}
+
+module_init(k10temp_init)
+module_exit(k10temp_exit)
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
new file mode 100644
index 0000000..dc1f540
--- /dev/null
+++ b/drivers/hwmon/lis3lv02d_i2c.c
@@ -0,0 +1,183 @@
+/*
+ * drivers/hwmon/lis3lv02d_i2c.c
+ *
+ * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
+ * Driver is based on corresponding SPI driver written by Daniel Mack
+ * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include "lis3lv02d.h"
+
+#define DRV_NAME 	"lis3lv02d_i2c"
+
+static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	*v = i2c_smbus_read_byte_data(c, reg);
+	return 0;
+}
+
+static int lis3_i2c_init(struct lis3lv02d *lis3)
+{
+	u8 reg;
+	int ret;
+
+	/* power up the device */
+	ret = lis3->read(lis3, CTRL_REG1, &reg);
+	if (ret < 0)
+		return ret;
+
+	reg |= CTRL1_PD0;
+	return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+/* Default axis mapping but it can be overwritten by platform data */
+static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
+						     LIS3_DEV_Y,
+						     LIS3_DEV_Z };
+
+static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata) {
+		if (pdata->axis_x)
+			lis3lv02d_axis_map.x = pdata->axis_x;
+
+		if (pdata->axis_y)
+			lis3lv02d_axis_map.y = pdata->axis_y;
+
+		if (pdata->axis_z)
+			lis3lv02d_axis_map.z = pdata->axis_z;
+
+		if (pdata->setup_resources)
+			ret = pdata->setup_resources();
+
+		if (ret)
+			goto fail;
+	}
+
+	lis3_dev.pdata	  = pdata;
+	lis3_dev.bus_priv = client;
+	lis3_dev.init	  = lis3_i2c_init;
+	lis3_dev.read	  = lis3_i2c_read;
+	lis3_dev.write	  = lis3_i2c_write;
+	lis3_dev.irq	  = client->irq;
+	lis3_dev.ac	  = lis3lv02d_axis_map;
+
+	i2c_set_clientdata(client, &lis3_dev);
+	ret = lis3lv02d_init_device(&lis3_dev);
+fail:
+	return ret;
+}
+
+static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+{
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
+
+	lis3lv02d_joystick_disable();
+	lis3lv02d_poweroff(lis3);
+
+	return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+#ifdef CONFIG_PM
+static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	if (!lis3->pdata->wakeup_flags)
+		lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3lv02d_i2c_resume(struct i2c_client *client)
+{
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	if (!lis3->pdata->wakeup_flags)
+		lis3lv02d_poweron(lis3);
+	return 0;
+}
+
+static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
+{
+	lis3lv02d_i2c_suspend(client, PMSG_SUSPEND);
+}
+#else
+#define lis3lv02d_i2c_suspend	NULL
+#define lis3lv02d_i2c_resume	NULL
+#define lis3lv02d_i2c_shutdown	NULL
+#endif
+
+static const struct i2c_device_id lis3lv02d_id[] = {
+	{"lis3lv02d", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
+
+static struct i2c_driver lis3lv02d_i2c_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+	},
+	.suspend = lis3lv02d_i2c_suspend,
+	.shutdown = lis3lv02d_i2c_shutdown,
+	.resume = lis3lv02d_i2c_resume,
+	.probe	= lis3lv02d_i2c_probe,
+	.remove	= __devexit_p(lis3lv02d_i2c_remove),
+	.id_table = lis3lv02d_id,
+};
+
+static int __init lis3lv02d_init(void)
+{
+	return i2c_add_driver(&lis3lv02d_i2c_driver);
+}
+
+static void __exit lis3lv02d_exit(void)
+{
+	i2c_del_driver(&lis3lv02d_i2c_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("lis3lv02d I2C interface");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init);
+module_exit(lis3lv02d_exit);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index ebe38b6..864a371 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -305,7 +305,7 @@
 	int d1 = 0;
 	int i;
 
-	for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++)
+	for (i = 1; i < ARRAY_SIZE(temppoints); i++)
 		/* Find pointer to interpolate */
 		if (data->supply_uV > temppoints[i - 1].vdd) {
 			d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd)
@@ -332,12 +332,12 @@
 
 	const int c1 = -4;
 	const int c2 = 40500; /* x 10 ^ -6 */
-	const int c3 = 2800; /* x10 ^ -9 */
+	const int c3 = -2800; /* x10 ^ -9 */
 
 	RHlinear = c1*1000
 		+ c2 * data->val_humid/1000
 		+ (data->val_humid * data->val_humid * c3)/1000000;
-	return (temp - 25000) * (10000 + 800 * data->val_humid)
+	return (temp - 25000) * (10000 + 80 * data->val_humid)
 		/ 1000000 + RHlinear;
 }
 
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 8ad50fd..9ca9781 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -136,11 +136,11 @@
 
 struct smsc47m1_sio_data {
 	enum chips type;
+	u8 activate;		/* Remember initial device state */
 };
 
 
-static int smsc47m1_probe(struct platform_device *pdev);
-static int __devexit smsc47m1_remove(struct platform_device *pdev);
+static int __exit smsc47m1_remove(struct platform_device *pdev);
 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 		int init);
 
@@ -160,8 +160,7 @@
 		.owner	= THIS_MODULE,
 		.name	= DRVNAME,
 	},
-	.probe		= smsc47m1_probe,
-	.remove		= __devexit_p(smsc47m1_remove),
+	.remove		= __exit_p(smsc47m1_remove),
 };
 
 static ssize_t get_fan(struct device *dev, struct device_attribute
@@ -470,24 +469,126 @@
 	superio_select();
 	*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
 	      |  superio_inb(SUPERIO_REG_BASE + 1);
-	val = superio_inb(SUPERIO_REG_ACT);
-	if (*addr == 0 || (val & 0x01) == 0) {
-		pr_info(DRVNAME ": Device is disabled, will not use\n");
+	if (*addr == 0) {
+		pr_info(DRVNAME ": Device address not set, will not use\n");
 		superio_exit();
 		return -ENODEV;
 	}
 
+	/* Enable only if address is set (needed at least on the
+	 * Compaq Presario S4000NX) */
+	sio_data->activate = superio_inb(SUPERIO_REG_ACT);
+	if ((sio_data->activate & 0x01) == 0) {
+		pr_info(DRVNAME ": Enabling device\n");
+		superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
+	}
+
 	superio_exit();
 	return 0;
 }
 
-static int __devinit smsc47m1_probe(struct platform_device *pdev)
+/* Restore device to its initial state */
+static void __init smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
+{
+	if ((sio_data->activate & 0x01) == 0) {
+		superio_enter();
+		superio_select();
+
+		pr_info(DRVNAME ": Disabling device\n");
+		superio_outb(SUPERIO_REG_ACT, sio_data->activate);
+
+		superio_exit();
+	}
+}
+
+#define CHECK		1
+#define REQUEST		2
+#define RELEASE		3
+
+/*
+ * This function can be used to:
+ *  - test for resource conflicts with ACPI
+ *  - request the resources
+ *  - release the resources
+ * We only allocate the I/O ports we really need, to minimize the risk of
+ * conflicts with ACPI or with other drivers.
+ */
+static int smsc47m1_handle_resources(unsigned short address, enum chips type,
+				     int action, struct device *dev)
+{
+	static const u8 ports_m1[] = {
+		/* register, region length */
+		0x04, 1,
+		0x33, 4,
+		0x56, 7,
+	};
+
+	static const u8 ports_m2[] = {
+		/* register, region length */
+		0x04, 1,
+		0x09, 1,
+		0x2c, 2,
+		0x35, 4,
+		0x56, 7,
+		0x69, 4,
+	};
+
+	int i, ports_size, err;
+	const u8 *ports;
+
+	switch (type) {
+	case smsc47m1:
+	default:
+		ports = ports_m1;
+		ports_size = ARRAY_SIZE(ports_m1);
+		break;
+	case smsc47m2:
+		ports = ports_m2;
+		ports_size = ARRAY_SIZE(ports_m2);
+		break;
+	}
+
+	for (i = 0; i + 1 < ports_size; i += 2) {
+		unsigned short start = address + ports[i];
+		unsigned short len = ports[i + 1];
+
+		switch (action) {
+		case CHECK:
+			/* Only check for conflicts */
+			err = acpi_check_region(start, len, DRVNAME);
+			if (err)
+				return err;
+			break;
+		case REQUEST:
+			/* Request the resources */
+			if (!request_region(start, len, DRVNAME)) {
+				dev_err(dev, "Region 0x%hx-0x%hx already in "
+					"use!\n", start, start + len);
+
+				/* Undo all requests */
+				for (i -= 2; i >= 0; i -= 2)
+					release_region(address + ports[i],
+						       ports[i + 1]);
+				return -EBUSY;
+			}
+			break;
+		case RELEASE:
+			/* Release the resources */
+			release_region(start, len);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int __init smsc47m1_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct smsc47m1_sio_data *sio_data = dev->platform_data;
 	struct smsc47m1_data *data;
 	struct resource *res;
-	int err = 0;
+	int err;
 	int fan1, fan2, fan3, pwm1, pwm2, pwm3;
 
 	static const char *names[] = {
@@ -496,12 +597,10 @@
 	};
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) {
-		dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
-			(unsigned long)res->start,
-			(unsigned long)res->end);
-		return -EBUSY;
-	}
+	err = smsc47m1_handle_resources(res->start, sio_data->type,
+					REQUEST, dev);
+	if (err < 0)
+		return err;
 
 	if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
 		err = -ENOMEM;
@@ -637,11 +736,11 @@
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 error_release:
-	release_region(res->start, SMSC_EXTENT);
+	smsc47m1_handle_resources(res->start, sio_data->type, RELEASE, dev);
 	return err;
 }
 
-static int __devexit smsc47m1_remove(struct platform_device *pdev)
+static int __exit smsc47m1_remove(struct platform_device *pdev)
 {
 	struct smsc47m1_data *data = platform_get_drvdata(pdev);
 	struct resource *res;
@@ -650,7 +749,7 @@
 	sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, SMSC_EXTENT);
+	smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
@@ -717,7 +816,7 @@
 	};
 	int err;
 
-	err = acpi_check_resource_conflict(&res);
+	err = smsc47m1_handle_resources(address, sio_data->type, CHECK, NULL);
 	if (err)
 		goto exit;
 
@@ -766,27 +865,29 @@
 	if (smsc47m1_find(&address, &sio_data))
 		return -ENODEV;
 
-	err = platform_driver_register(&smsc47m1_driver);
-	if (err)
-		goto exit;
-
 	/* Sets global pdev as a side effect */
 	err = smsc47m1_device_add(address, &sio_data);
 	if (err)
-		goto exit_driver;
+		goto exit;
+
+	err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe);
+	if (err)
+		goto exit_device;
 
 	return 0;
 
-exit_driver:
-	platform_driver_unregister(&smsc47m1_driver);
+exit_device:
+	platform_device_unregister(pdev);
+	smsc47m1_restore(&sio_data);
 exit:
 	return err;
 }
 
 static void __exit sm_smsc47m1_exit(void)
 {
-	platform_device_unregister(pdev);
 	platform_driver_unregister(&smsc47m1_driver);
+	smsc47m1_restore(pdev->dev.platform_data);
+	platform_device_unregister(pdev);
 }
 
 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
new file mode 100644
index 0000000..7442cf7
--- /dev/null
+++ b/drivers/hwmon/via-cputemp.c
@@ -0,0 +1,356 @@
+/*
+ * via-cputemp.c - Driver for VIA CPU core temperature monitoring
+ * Copyright (C) 2009 VIA Technologies, Inc.
+ *
+ * based on existing coretemp.c, which is
+ *
+ * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/hwmon.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/cpu.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+#define DRVNAME	"via_cputemp"
+
+enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW;
+
+/*
+ * Functions declaration
+ */
+
+struct via_cputemp_data {
+	struct device *hwmon_dev;
+	const char *name;
+	u32 id;
+	u32 msr;
+};
+
+/*
+ * Sysfs stuff
+ */
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+			  *devattr, char *buf)
+{
+	int ret;
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct via_cputemp_data *data = dev_get_drvdata(dev);
+
+	if (attr->index == SHOW_NAME)
+		ret = sprintf(buf, "%s\n", data->name);
+	else	/* show label */
+		ret = sprintf(buf, "Core %d\n", data->id);
+	return ret;
+}
+
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *devattr, char *buf)
+{
+	struct via_cputemp_data *data = dev_get_drvdata(dev);
+	u32 eax, edx;
+	int err;
+
+	err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+	if (err)
+		return -EAGAIN;
+
+	return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
+			  SHOW_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
+
+static struct attribute *via_cputemp_attributes[] = {
+	&sensor_dev_attr_name.dev_attr.attr,
+	&sensor_dev_attr_temp1_label.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group via_cputemp_group = {
+	.attrs = via_cputemp_attributes,
+};
+
+static int __devinit via_cputemp_probe(struct platform_device *pdev)
+{
+	struct via_cputemp_data *data;
+	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
+	int err;
+	u32 eax, edx;
+
+	data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		dev_err(&pdev->dev, "Out of memory\n");
+		goto exit;
+	}
+
+	data->id = pdev->id;
+	data->name = "via_cputemp";
+
+	switch (c->x86_model) {
+	case 0xA:
+		/* C7 A */
+	case 0xD:
+		/* C7 D */
+		data->msr = 0x1169;
+		break;
+	case 0xF:
+		/* Nano */
+		data->msr = 0x1423;
+		break;
+	default:
+		err = -ENODEV;
+		goto exit_free;
+	}
+
+	/* test if we can access the TEMPERATURE MSR */
+	err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
+	if (err) {
+		dev_err(&pdev->dev,
+			"Unable to access TEMPERATURE MSR, giving up\n");
+		goto exit_free;
+	}
+
+	platform_set_drvdata(pdev, data);
+
+	err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n",
+			err);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
+exit_free:
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __devexit via_cputemp_remove(struct platform_device *pdev)
+{
+	struct via_cputemp_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+	return 0;
+}
+
+static struct platform_driver via_cputemp_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRVNAME,
+	},
+	.probe = via_cputemp_probe,
+	.remove = __devexit_p(via_cputemp_remove),
+};
+
+struct pdev_entry {
+	struct list_head list;
+	struct platform_device *pdev;
+	unsigned int cpu;
+};
+
+static LIST_HEAD(pdev_list);
+static DEFINE_MUTEX(pdev_list_mutex);
+
+static int __cpuinit via_cputemp_device_add(unsigned int cpu)
+{
+	int err;
+	struct platform_device *pdev;
+	struct pdev_entry *pdev_entry;
+
+	pdev = platform_device_alloc(DRVNAME, cpu);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
+	if (!pdev_entry) {
+		err = -ENOMEM;
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_free;
+	}
+
+	pdev_entry->pdev = pdev;
+	pdev_entry->cpu = cpu;
+	mutex_lock(&pdev_list_mutex);
+	list_add_tail(&pdev_entry->list, &pdev_list);
+	mutex_unlock(&pdev_list_mutex);
+
+	return 0;
+
+exit_device_free:
+	kfree(pdev_entry);
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void via_cputemp_device_remove(unsigned int cpu)
+{
+	struct pdev_entry *p, *n;
+	mutex_lock(&pdev_list_mutex);
+	list_for_each_entry_safe(p, n, &pdev_list, list) {
+		if (p->cpu == cpu) {
+			platform_device_unregister(p->pdev);
+			list_del(&p->list);
+			kfree(p);
+		}
+	}
+	mutex_unlock(&pdev_list_mutex);
+}
+
+static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb,
+				 unsigned long action, void *hcpu)
+{
+	unsigned int cpu = (unsigned long) hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+		via_cputemp_device_add(cpu);
+		break;
+	case CPU_DOWN_PREPARE:
+		via_cputemp_device_remove(cpu);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block via_cputemp_cpu_notifier __refdata = {
+	.notifier_call = via_cputemp_cpu_callback,
+};
+#endif				/* !CONFIG_HOTPLUG_CPU */
+
+static int __init via_cputemp_init(void)
+{
+	int i, err;
+	struct pdev_entry *p, *n;
+
+	if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
+		printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	err = platform_driver_register(&via_cputemp_driver);
+	if (err)
+		goto exit;
+
+	for_each_online_cpu(i) {
+		struct cpuinfo_x86 *c = &cpu_data(i);
+
+		if (c->x86 != 6)
+			continue;
+
+		if (c->x86_model < 0x0a)
+			continue;
+
+		if (c->x86_model > 0x0f) {
+			printk(KERN_WARNING DRVNAME ": Unknown CPU "
+				"model 0x%x\n", c->x86_model);
+			continue;
+		}
+
+		err = via_cputemp_device_add(i);
+		if (err)
+			goto exit_devices_unreg;
+	}
+	if (list_empty(&pdev_list)) {
+		err = -ENODEV;
+		goto exit_driver_unreg;
+	}
+
+#ifdef CONFIG_HOTPLUG_CPU
+	register_hotcpu_notifier(&via_cputemp_cpu_notifier);
+#endif
+	return 0;
+
+exit_devices_unreg:
+	mutex_lock(&pdev_list_mutex);
+	list_for_each_entry_safe(p, n, &pdev_list, list) {
+		platform_device_unregister(p->pdev);
+		list_del(&p->list);
+		kfree(p);
+	}
+	mutex_unlock(&pdev_list_mutex);
+exit_driver_unreg:
+	platform_driver_unregister(&via_cputemp_driver);
+exit:
+	return err;
+}
+
+static void __exit via_cputemp_exit(void)
+{
+	struct pdev_entry *p, *n;
+#ifdef CONFIG_HOTPLUG_CPU
+	unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
+#endif
+	mutex_lock(&pdev_list_mutex);
+	list_for_each_entry_safe(p, n, &pdev_list, list) {
+		platform_device_unregister(p->pdev);
+		list_del(&p->list);
+		kfree(p);
+	}
+	mutex_unlock(&pdev_list_mutex);
+	platform_driver_unregister(&via_cputemp_driver);
+}
+
+MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
+MODULE_DESCRIPTION("VIA CPU temperature monitor");
+MODULE_LICENSE("GPL");
+
+module_init(via_cputemp_init)
+module_exit(via_cputemp_exit)
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index b257c72..38e2805 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -1135,6 +1135,7 @@
 		"W83687THF",
 	};
 
+	sio_data->sioaddr = sioaddr;
 	superio_enter(sio_data);
 	val = force_id ? force_id : superio_inb(sio_data, DEVID);
 	switch (val) {
@@ -1177,7 +1178,6 @@
 	}
 
 	err = 0;
-	sio_data->sioaddr = sioaddr;
 	pr_info(DRVNAME ": Found %s chip at %#x\n",
 		names[sio_data->type], *addr);
 
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index bd07803..abbb069 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -36,7 +36,6 @@
 #include <linux/mutex.h>
 #include <linux/inetdevice.h>
 #include <linux/workqueue.h>
-#include <linux/if_arp.h>
 #include <net/arp.h>
 #include <net/neighbour.h>
 #include <net/route.h>
@@ -92,22 +91,12 @@
 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
 		     const unsigned char *dst_dev_addr)
 {
-	switch (dev->type) {
-	case ARPHRD_INFINIBAND:
-		dev_addr->dev_type = RDMA_NODE_IB_CA;
-		break;
-	case ARPHRD_ETHER:
-		dev_addr->dev_type = RDMA_NODE_RNIC;
-		break;
-	default:
-		return -EADDRNOTAVAIL;
-	}
-
+	dev_addr->dev_type = dev->type;
 	memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
 	memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
 	if (dst_dev_addr)
 		memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
-	dev_addr->src_dev = dev;
+	dev_addr->bound_dev_if = dev->ifindex;
 	return 0;
 }
 EXPORT_SYMBOL(rdma_copy_addr);
@@ -117,6 +106,15 @@
 	struct net_device *dev;
 	int ret = -EADDRNOTAVAIL;
 
+	if (dev_addr->bound_dev_if) {
+		dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+		if (!dev)
+			return -ENODEV;
+		ret = rdma_copy_addr(dev_addr, dev, NULL);
+		dev_put(dev);
+		return ret;
+	}
+
 	switch (addr->sa_family) {
 	case AF_INET:
 		dev = ip_dev_find(&init_net,
@@ -131,6 +129,7 @@
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
+		read_lock(&dev_base_lock);
 		for_each_netdev(&init_net, dev) {
 			if (ipv6_chk_addr(&init_net,
 					  &((struct sockaddr_in6 *) addr)->sin6_addr,
@@ -139,6 +138,7 @@
 				break;
 			}
 		}
+		read_unlock(&dev_base_lock);
 		break;
 #endif
 	}
@@ -176,48 +176,9 @@
 	mutex_unlock(&lock);
 }
 
-static void addr_send_arp(struct sockaddr *dst_in)
-{
-	struct rtable *rt;
-	struct flowi fl;
-
-	memset(&fl, 0, sizeof fl);
-
-	switch (dst_in->sa_family) {
-	case AF_INET:
-		fl.nl_u.ip4_u.daddr =
-			((struct sockaddr_in *) dst_in)->sin_addr.s_addr;
-
-		if (ip_route_output_key(&init_net, &rt, &fl))
-			return;
-
-		neigh_event_send(rt->u.dst.neighbour, NULL);
-		ip_rt_put(rt);
-		break;
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-	{
-		struct dst_entry *dst;
-
-		fl.nl_u.ip6_u.daddr =
-			((struct sockaddr_in6 *) dst_in)->sin6_addr;
-
-		dst = ip6_route_output(&init_net, NULL, &fl);
-		if (!dst)
-			return;
-
-		neigh_event_send(dst->neighbour, NULL);
-		dst_release(dst);
-		break;
-	}
-#endif
-	}
-}
-
-static int addr4_resolve_remote(struct sockaddr_in *src_in,
-			       struct sockaddr_in *dst_in,
-			       struct rdma_dev_addr *addr)
+static int addr4_resolve(struct sockaddr_in *src_in,
+			 struct sockaddr_in *dst_in,
+			 struct rdma_dev_addr *addr)
 {
 	__be32 src_ip = src_in->sin_addr.s_addr;
 	__be32 dst_ip = dst_in->sin_addr.s_addr;
@@ -229,10 +190,22 @@
 	memset(&fl, 0, sizeof fl);
 	fl.nl_u.ip4_u.daddr = dst_ip;
 	fl.nl_u.ip4_u.saddr = src_ip;
+	fl.oif = addr->bound_dev_if;
+
 	ret = ip_route_output_key(&init_net, &rt, &fl);
 	if (ret)
 		goto out;
 
+	src_in->sin_family = AF_INET;
+	src_in->sin_addr.s_addr = rt->rt_src;
+
+	if (rt->idev->dev->flags & IFF_LOOPBACK) {
+		ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
+		if (!ret)
+			memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
+		goto put;
+	}
+
 	/* If the device does ARP internally, return 'done' */
 	if (rt->idev->dev->flags & IFF_NOARP) {
 		rdma_copy_addr(addr, rt->idev->dev, NULL);
@@ -240,21 +213,14 @@
 	}
 
 	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
-	if (!neigh) {
+	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+		neigh_event_send(rt->u.dst.neighbour, NULL);
 		ret = -ENODATA;
+		if (neigh)
+			goto release;
 		goto put;
 	}
 
-	if (!(neigh->nud_state & NUD_VALID)) {
-		ret = -ENODATA;
-		goto release;
-	}
-
-	if (!src_ip) {
-		src_in->sin_family = dst_in->sin_family;
-		src_in->sin_addr.s_addr = rt->rt_src;
-	}
-
 	ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
 release:
 	neigh_release(neigh);
@@ -265,52 +231,77 @@
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-static int addr6_resolve_remote(struct sockaddr_in6 *src_in,
-			       struct sockaddr_in6 *dst_in,
-			       struct rdma_dev_addr *addr)
+static int addr6_resolve(struct sockaddr_in6 *src_in,
+			 struct sockaddr_in6 *dst_in,
+			 struct rdma_dev_addr *addr)
 {
 	struct flowi fl;
 	struct neighbour *neigh;
 	struct dst_entry *dst;
-	int ret = -ENODATA;
+	int ret;
 
 	memset(&fl, 0, sizeof fl);
-	fl.nl_u.ip6_u.daddr = dst_in->sin6_addr;
-	fl.nl_u.ip6_u.saddr = src_in->sin6_addr;
+	ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr);
+	ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr);
+	fl.oif = addr->bound_dev_if;
 
 	dst = ip6_route_output(&init_net, NULL, &fl);
-	if (!dst)
-		return ret;
+	if ((ret = dst->error))
+		goto put;
 
-	if (dst->dev->flags & IFF_NOARP) {
-		ret = rdma_copy_addr(addr, dst->dev, NULL);
-	} else {
-		neigh = dst->neighbour;
-		if (neigh && (neigh->nud_state & NUD_VALID))
-			ret = rdma_copy_addr(addr, neigh->dev, neigh->ha);
+	if (ipv6_addr_any(&fl.fl6_src)) {
+		ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev,
+					 &fl.fl6_dst, 0, &fl.fl6_src);
+		if (ret)
+			goto put;
+
+		src_in->sin6_family = AF_INET6;
+		ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src);
 	}
 
+	if (dst->dev->flags & IFF_LOOPBACK) {
+		ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
+		if (!ret)
+			memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
+		goto put;
+	}
+
+	/* If the device does ARP internally, return 'done' */
+	if (dst->dev->flags & IFF_NOARP) {
+		ret = rdma_copy_addr(addr, dst->dev, NULL);
+		goto put;
+	}
+
+	neigh = dst->neighbour;
+	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+		neigh_event_send(dst->neighbour, NULL);
+		ret = -ENODATA;
+		goto put;
+	}
+
+	ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+put:
 	dst_release(dst);
 	return ret;
 }
 #else
-static int addr6_resolve_remote(struct sockaddr_in6 *src_in,
-			       struct sockaddr_in6 *dst_in,
-			       struct rdma_dev_addr *addr)
+static int addr6_resolve(struct sockaddr_in6 *src_in,
+			 struct sockaddr_in6 *dst_in,
+			 struct rdma_dev_addr *addr)
 {
 	return -EADDRNOTAVAIL;
 }
 #endif
 
-static int addr_resolve_remote(struct sockaddr *src_in,
-				struct sockaddr *dst_in,
-				struct rdma_dev_addr *addr)
+static int addr_resolve(struct sockaddr *src_in,
+			struct sockaddr *dst_in,
+			struct rdma_dev_addr *addr)
 {
 	if (src_in->sa_family == AF_INET) {
-		return addr4_resolve_remote((struct sockaddr_in *) src_in,
+		return addr4_resolve((struct sockaddr_in *) src_in,
 			(struct sockaddr_in *) dst_in, addr);
 	} else
-		return addr6_resolve_remote((struct sockaddr_in6 *) src_in,
+		return addr6_resolve((struct sockaddr_in6 *) src_in,
 			(struct sockaddr_in6 *) dst_in, addr);
 }
 
@@ -327,8 +318,7 @@
 		if (req->status == -ENODATA) {
 			src_in = (struct sockaddr *) &req->src_addr;
 			dst_in = (struct sockaddr *) &req->dst_addr;
-			req->status = addr_resolve_remote(src_in, dst_in,
-							  req->addr);
+			req->status = addr_resolve(src_in, dst_in, req->addr);
 			if (req->status && time_after_eq(jiffies, req->timeout))
 				req->status = -ETIMEDOUT;
 			else if (req->status == -ENODATA)
@@ -352,82 +342,6 @@
 	}
 }
 
-static int addr_resolve_local(struct sockaddr *src_in,
-			      struct sockaddr *dst_in,
-			      struct rdma_dev_addr *addr)
-{
-	struct net_device *dev;
-	int ret;
-
-	switch (dst_in->sa_family) {
-	case AF_INET:
-	{
-		__be32 src_ip = ((struct sockaddr_in *) src_in)->sin_addr.s_addr;
-		__be32 dst_ip = ((struct sockaddr_in *) dst_in)->sin_addr.s_addr;
-
-		dev = ip_dev_find(&init_net, dst_ip);
-		if (!dev)
-			return -EADDRNOTAVAIL;
-
-		if (ipv4_is_zeronet(src_ip)) {
-			src_in->sa_family = dst_in->sa_family;
-			((struct sockaddr_in *) src_in)->sin_addr.s_addr = dst_ip;
-			ret = rdma_copy_addr(addr, dev, dev->dev_addr);
-		} else if (ipv4_is_loopback(src_ip)) {
-			ret = rdma_translate_ip(dst_in, addr);
-			if (!ret)
-				memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
-		} else {
-			ret = rdma_translate_ip(src_in, addr);
-			if (!ret)
-				memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
-		}
-		dev_put(dev);
-		break;
-	}
-
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	case AF_INET6:
-	{
-		struct in6_addr *a;
-
-		for_each_netdev(&init_net, dev)
-			if (ipv6_chk_addr(&init_net,
-					  &((struct sockaddr_in6 *) dst_in)->sin6_addr,
-					  dev, 1))
-				break;
-
-		if (!dev)
-			return -EADDRNOTAVAIL;
-
-		a = &((struct sockaddr_in6 *) src_in)->sin6_addr;
-
-		if (ipv6_addr_any(a)) {
-			src_in->sa_family = dst_in->sa_family;
-			((struct sockaddr_in6 *) src_in)->sin6_addr =
-				((struct sockaddr_in6 *) dst_in)->sin6_addr;
-			ret = rdma_copy_addr(addr, dev, dev->dev_addr);
-		} else if (ipv6_addr_loopback(a)) {
-			ret = rdma_translate_ip(dst_in, addr);
-			if (!ret)
-				memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
-		} else  {
-			ret = rdma_translate_ip(src_in, addr);
-			if (!ret)
-				memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
-		}
-		break;
-	}
-#endif
-
-	default:
-		ret = -EADDRNOTAVAIL;
-		break;
-	}
-
-	return ret;
-}
-
 int rdma_resolve_ip(struct rdma_addr_client *client,
 		    struct sockaddr *src_addr, struct sockaddr *dst_addr,
 		    struct rdma_dev_addr *addr, int timeout_ms,
@@ -443,22 +357,28 @@
 	if (!req)
 		return -ENOMEM;
 
-	if (src_addr)
-		memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
-	memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
+	src_in = (struct sockaddr *) &req->src_addr;
+	dst_in = (struct sockaddr *) &req->dst_addr;
+
+	if (src_addr) {
+		if (src_addr->sa_family != dst_addr->sa_family) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		memcpy(src_in, src_addr, ip_addr_size(src_addr));
+	} else {
+		src_in->sa_family = dst_addr->sa_family;
+	}
+
+	memcpy(dst_in, dst_addr, ip_addr_size(dst_addr));
 	req->addr = addr;
 	req->callback = callback;
 	req->context = context;
 	req->client = client;
 	atomic_inc(&client->refcount);
 
-	src_in = (struct sockaddr *) &req->src_addr;
-	dst_in = (struct sockaddr *) &req->dst_addr;
-
-	req->status = addr_resolve_local(src_in, dst_in, addr);
-	if (req->status == -EADDRNOTAVAIL)
-		req->status = addr_resolve_remote(src_in, dst_in, addr);
-
+	req->status = addr_resolve(src_in, dst_in, addr);
 	switch (req->status) {
 	case 0:
 		req->timeout = jiffies;
@@ -467,15 +387,16 @@
 	case -ENODATA:
 		req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
 		queue_req(req);
-		addr_send_arp(dst_in);
 		break;
 	default:
 		ret = req->status;
 		atomic_dec(&client->refcount);
-		kfree(req);
-		break;
+		goto err;
 	}
 	return ret;
+err:
+	kfree(req);
+	return ret;
 }
 EXPORT_SYMBOL(rdma_resolve_ip);
 
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 0753178..fbdd731 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -330,17 +330,7 @@
 	union ib_gid gid;
 	int ret = -ENODEV;
 
-	switch (rdma_node_get_transport(dev_addr->dev_type)) {
-	case RDMA_TRANSPORT_IB:
-		ib_addr_get_sgid(dev_addr, &gid);
-		break;
-	case RDMA_TRANSPORT_IWARP:
-		iw_addr_get_sgid(dev_addr, &gid);
-		break;
-	default:
-		return -ENODEV;
-	}
-
+	rdma_addr_get_sgid(dev_addr, &gid);
 	list_for_each_entry(cma_dev, &dev_list, list) {
 		ret = ib_find_cached_gid(cma_dev->device, &gid,
 					 &id_priv->id.port_num, NULL);
@@ -1032,11 +1022,17 @@
 	if (rt->num_paths == 2)
 		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
 
-	ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
-	ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
-				&id->route.addr.dev_addr);
-	if (ret)
-		goto destroy_id;
+	if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) {
+		rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
+		rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+		ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey);
+	} else {
+		ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
+					&rt->addr.dev_addr);
+		if (ret)
+			goto destroy_id;
+	}
+	rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
 
 	id_priv = container_of(id, struct rdma_id_private, id);
 	id_priv->state = CMA_CONNECT;
@@ -1071,10 +1067,12 @@
 	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
 			  ip_ver, port, src, dst);
 
-	ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
-				&id->route.addr.dev_addr);
-	if (ret)
-		goto err;
+	if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) {
+		ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
+					&id->route.addr.dev_addr);
+		if (ret)
+			goto err;
+	}
 
 	id_priv = container_of(id, struct rdma_id_private, id);
 	id_priv->state = CMA_CONNECT;
@@ -1474,15 +1472,6 @@
 	mutex_unlock(&lock);
 }
 
-static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
-{
-	struct sockaddr_storage addr_in;
-
-	memset(&addr_in, 0, sizeof addr_in);
-	addr_in.ss_family = af;
-	return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
-}
-
 int rdma_listen(struct rdma_cm_id *id, int backlog)
 {
 	struct rdma_id_private *id_priv;
@@ -1490,7 +1479,8 @@
 
 	id_priv = container_of(id, struct rdma_id_private, id);
 	if (id_priv->state == CMA_IDLE) {
-		ret = cma_bind_any(id, AF_INET);
+		((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
+		ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
 		if (ret)
 			return ret;
 	}
@@ -1565,8 +1555,8 @@
 	struct sockaddr_in6 *sin6;
 
 	memset(&path_rec, 0, sizeof path_rec);
-	ib_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
-	ib_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
+	rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
+	rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
 	path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr));
 	path_rec.numb_path = 1;
 	path_rec.reversible = 1;
@@ -1781,7 +1771,11 @@
 	if (ret)
 		goto out;
 
-	ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+	id_priv->id.route.addr.dev_addr.dev_type =
+		(rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ?
+		ARPHRD_INFINIBAND : ARPHRD_ETHER;
+
+	rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
 	ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
 	id_priv->id.port_num = p;
 	cma_attach_to_dev(id_priv, cma_dev);
@@ -1839,7 +1833,7 @@
 static int cma_resolve_loopback(struct rdma_id_private *id_priv)
 {
 	struct cma_work *work;
-	struct sockaddr_in *src_in, *dst_in;
+	struct sockaddr *src, *dst;
 	union ib_gid gid;
 	int ret;
 
@@ -1853,14 +1847,19 @@
 			goto err;
 	}
 
-	ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
-	ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
+	rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
+	rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
 
-	if (cma_zero_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) {
-		src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
-		dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
-		src_in->sin_family = dst_in->sin_family;
-		src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
+	src = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
+	if (cma_zero_addr(src)) {
+		dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr;
+		if ((src->sa_family = dst->sa_family) == AF_INET) {
+			((struct sockaddr_in *) src)->sin_addr.s_addr =
+				((struct sockaddr_in *) dst)->sin_addr.s_addr;
+		} else {
+			ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr,
+				       &((struct sockaddr_in6 *) dst)->sin6_addr);
+		}
 	}
 
 	work->id = id_priv;
@@ -1878,10 +1877,14 @@
 static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
 			 struct sockaddr *dst_addr)
 {
-	if (src_addr && src_addr->sa_family)
-		return rdma_bind_addr(id, src_addr);
-	else
-		return cma_bind_any(id, dst_addr->sa_family);
+	if (!src_addr || !src_addr->sa_family) {
+		src_addr = (struct sockaddr *) &id->route.addr.src_addr;
+		if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
+			((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
+				((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
+		}
+	}
+	return rdma_bind_addr(id, src_addr);
 }
 
 int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
@@ -2077,6 +2080,25 @@
 	return ret;
 }
 
+static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
+			       struct sockaddr *addr)
+{
+#if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE)
+	struct sockaddr_in6 *sin6;
+
+	if (addr->sa_family != AF_INET6)
+		return 0;
+
+	sin6 = (struct sockaddr_in6 *) addr;
+	if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
+	    !sin6->sin6_scope_id)
+			return -EINVAL;
+
+	dev_addr->bound_dev_if = sin6->sin6_scope_id;
+#endif
+	return 0;
+}
+
 int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 {
 	struct rdma_id_private *id_priv;
@@ -2089,7 +2111,13 @@
 	if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
 		return -EINVAL;
 
-	if (!cma_any_addr(addr)) {
+	ret = cma_check_linklocal(&id->route.addr.dev_addr, addr);
+	if (ret)
+		goto err1;
+
+	if (cma_loopback_addr(addr)) {
+		ret = cma_bind_loopback(id_priv);
+	} else if (!cma_zero_addr(addr)) {
 		ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
 		if (ret)
 			goto err1;
@@ -2108,7 +2136,7 @@
 
 	return 0;
 err2:
-	if (!cma_any_addr(addr)) {
+	if (id_priv->cma_dev) {
 		mutex_lock(&lock);
 		cma_detach_from_dev(id_priv);
 		mutex_unlock(&lock);
@@ -2687,10 +2715,15 @@
 	if (cma_any_addr(addr)) {
 		memset(mgid, 0, sizeof *mgid);
 	} else if ((addr->sa_family == AF_INET6) &&
-		   ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFF10A01B) ==
+		   ((be32_to_cpu(sin6->sin6_addr.s6_addr32[0]) & 0xFFF0FFFF) ==
 								 0xFF10A01B)) {
 		/* IPv6 address is an SA assigned MGID. */
 		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+	} else if ((addr->sa_family == AF_INET6)) {
+		ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map);
+		if (id_priv->id.ps == RDMA_PS_UDP)
+			mc_map[7] = 0x01;	/* Use RDMA CM signature */
+		*mgid = *(union ib_gid *) (mc_map + 4);
 	} else {
 		ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
 		if (id_priv->id.ps == RDMA_PS_UDP)
@@ -2716,7 +2749,7 @@
 	cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
 	if (id_priv->id.ps == RDMA_PS_UDP)
 		rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
-	ib_addr_get_sgid(dev_addr, &rec.port_gid);
+	rdma_addr_get_sgid(dev_addr, &rec.port_gid);
 	rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
 	rec.join_state = 1;
 
@@ -2815,7 +2848,7 @@
 
 	dev_addr = &id_priv->id.route.addr.dev_addr;
 
-	if ((dev_addr->src_dev == ndev) &&
+	if ((dev_addr->bound_dev_if == ndev->ifindex) &&
 	    memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
 		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
 		       ndev->name, &id_priv->id);
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 8254371..7e1ffd8c 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -604,6 +604,12 @@
 	return ret ? ret : id;
 }
 
+void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec)
+{
+	ib_unpack(path_rec_table, ARRAY_SIZE(path_rec_table), attribute, rec);
+}
+EXPORT_SYMBOL(ib_sa_unpack_path);
+
 static void ib_sa_path_rec_callback(struct ib_sa_query *sa_query,
 				    int status,
 				    struct ib_sa_mad *mad)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index bb96d3c..b2e16c3 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -43,6 +43,7 @@
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
 #include <rdma/rdma_cm.h>
+#include <rdma/rdma_cm_ib.h>
 
 MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
@@ -562,10 +563,10 @@
 	switch (route->num_paths) {
 	case 0:
 		dev_addr = &route->addr.dev_addr;
-		ib_addr_get_dgid(dev_addr,
-				 (union ib_gid *) &resp->ib_route[0].dgid);
-		ib_addr_get_sgid(dev_addr,
-				 (union ib_gid *) &resp->ib_route[0].sgid);
+		rdma_addr_get_dgid(dev_addr,
+				   (union ib_gid *) &resp->ib_route[0].dgid);
+		rdma_addr_get_sgid(dev_addr,
+				   (union ib_gid *) &resp->ib_route[0].sgid);
 		resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
 		break;
 	case 2:
@@ -812,6 +813,51 @@
 	return ret;
 }
 
+static int ucma_set_ib_path(struct ucma_context *ctx,
+			    struct ib_path_rec_data *path_data, size_t optlen)
+{
+	struct ib_sa_path_rec sa_path;
+	struct rdma_cm_event event;
+	int ret;
+
+	if (optlen % sizeof(*path_data))
+		return -EINVAL;
+
+	for (; optlen; optlen -= sizeof(*path_data), path_data++) {
+		if (path_data->flags == (IB_PATH_GMP | IB_PATH_PRIMARY |
+					 IB_PATH_BIDIRECTIONAL))
+			break;
+	}
+
+	if (!optlen)
+		return -EINVAL;
+
+	ib_sa_unpack_path(path_data->path_rec, &sa_path);
+	ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
+	if (ret)
+		return ret;
+
+	memset(&event, 0, sizeof event);
+	event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+	return ucma_event_handler(ctx->cm_id, &event);
+}
+
+static int ucma_set_option_ib(struct ucma_context *ctx, int optname,
+			      void *optval, size_t optlen)
+{
+	int ret;
+
+	switch (optname) {
+	case RDMA_OPTION_IB_PATH:
+		ret = ucma_set_ib_path(ctx, optval, optlen);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	return ret;
+}
+
 static int ucma_set_option_level(struct ucma_context *ctx, int level,
 				 int optname, void *optval, size_t optlen)
 {
@@ -821,6 +867,9 @@
 	case RDMA_OPTION_ID:
 		ret = ucma_set_option_id(ctx, optname, optval, optlen);
 		break;
+	case RDMA_OPTION_IB:
+		ret = ucma_set_option_ib(ctx, optname, optval, optlen);
+		break;
 	default:
 		ret = -ENOSYS;
 	}
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 56feab6..112d397 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -285,7 +285,7 @@
 
 	ucontext = ibdev->alloc_ucontext(ibdev, &udata);
 	if (IS_ERR(ucontext)) {
-		ret = PTR_ERR(file->ucontext);
+		ret = PTR_ERR(ucontext);
 		goto err;
 	}
 
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index aec0fbd..5f284ff 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -492,6 +492,7 @@
 					int is_async, int *fd)
 {
 	struct ib_uverbs_event_file *ev_file;
+	struct path path;
 	struct file *filp;
 	int ret;
 
@@ -519,8 +520,10 @@
 	 * system call on a uverbs file, which will already have a
 	 * module reference.
 	 */
-	filp = alloc_file(uverbs_event_mnt, dget(uverbs_event_mnt->mnt_root),
-			  FMODE_READ, fops_get(&uverbs_event_fops));
+	path.mnt = uverbs_event_mnt;
+	path.dentry = uverbs_event_mnt->mnt_root;
+	path_get(&path);
+	filp = alloc_file(&path, FMODE_READ, fops_get(&uverbs_event_fops));
 	if (!filp) {
 		ret = -ENFILE;
 		goto err_fd;
@@ -531,6 +534,8 @@
 	return filp;
 
 err_fd:
+	fops_put(&uverbs_event_fops);
+	path_put(&path);
 	put_unused_fd(*fd);
 
 err:
diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c
index a6d8944..ad51886 100644
--- a/drivers/infiniband/hw/amso1100/c2_qp.c
+++ b/drivers/infiniband/hw/amso1100/c2_qp.c
@@ -798,8 +798,10 @@
 	u8 actual_sge_count;
 	u32 msg_size;
 
-	if (qp->state > IB_QPS_RTS)
-		return -EINVAL;
+	if (qp->state > IB_QPS_RTS) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	while (ib_wr) {
 
@@ -930,6 +932,7 @@
 		ib_wr = ib_wr->next;
 	}
 
+out:
 	if (err)
 		*bad_wr = ib_wr;
 	return err;
@@ -944,8 +947,10 @@
 	unsigned long lock_flags;
 	int err = 0;
 
-	if (qp->state > IB_QPS_RTS)
-		return -EINVAL;
+	if (qp->state > IB_QPS_RTS) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	/*
 	 * Try and post each work request
@@ -998,6 +1003,7 @@
 		ib_wr = ib_wr->next;
 	}
 
+out:
 	if (err)
 		*bad_wr = ib_wr;
 	return err;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 1cecf98..3eb8cec 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -365,18 +365,19 @@
 	spin_lock_irqsave(&qhp->lock, flag);
 	if (qhp->attr.state > IWCH_QP_STATE_RTS) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		return -EINVAL;
+		err = -EINVAL;
+		goto out;
 	}
 	num_wrs = Q_FREECNT(qhp->wq.sq_rptr, qhp->wq.sq_wptr,
 		  qhp->wq.sq_size_log2);
 	if (num_wrs <= 0) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out;
 	}
 	while (wr) {
 		if (num_wrs == 0) {
 			err = -ENOMEM;
-			*bad_wr = wr;
 			break;
 		}
 		idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
@@ -428,10 +429,8 @@
 			     wr->opcode);
 			err = -EINVAL;
 		}
-		if (err) {
-			*bad_wr = wr;
+		if (err)
 			break;
-		}
 		wqe->send.wrid.id0.hi = qhp->wq.sq_wptr;
 		sqp->wr_id = wr->wr_id;
 		sqp->opcode = wr2opcode(t3_wr_opcode);
@@ -454,6 +453,10 @@
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
 	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+
+out:
+	if (err)
+		*bad_wr = wr;
 	return err;
 }
 
@@ -471,18 +474,19 @@
 	spin_lock_irqsave(&qhp->lock, flag);
 	if (qhp->attr.state > IWCH_QP_STATE_RTS) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		return -EINVAL;
+		err = -EINVAL;
+		goto out;
 	}
 	num_wrs = Q_FREECNT(qhp->wq.rq_rptr, qhp->wq.rq_wptr,
 			    qhp->wq.rq_size_log2) - 1;
 	if (!wr) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		return -EINVAL;
+		err = -ENOMEM;
+		goto out;
 	}
 	while (wr) {
 		if (wr->num_sge > T3_MAX_SGE) {
 			err = -EINVAL;
-			*bad_wr = wr;
 			break;
 		}
 		idx = Q_PTR2IDX(qhp->wq.wptr, qhp->wq.size_log2);
@@ -494,10 +498,10 @@
 				err = build_zero_stag_recv(qhp, wqe, wr);
 		else
 			err = -ENOMEM;
-		if (err) {
-			*bad_wr = wr;
+
+		if (err)
 			break;
-		}
+
 		build_fw_riwrh((void *) wqe, T3_WR_RCV, T3_COMPLETION_FLAG,
 			       Q_GENBIT(qhp->wq.wptr, qhp->wq.size_log2),
 			       0, sizeof(struct t3_receive_wr) >> 3, T3_SOPEOP);
@@ -511,6 +515,10 @@
 	}
 	spin_unlock_irqrestore(&qhp->lock, flag);
 	ring_doorbell(qhp->wq.doorbell, qhp->wq.qpid);
+
+out:
+	if (err)
+		*bad_wr = wr;
 	return err;
 }
 
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index c825142..0136abd 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -375,6 +375,7 @@
 extern rwlock_t ehca_cq_idr_lock;
 extern struct idr ehca_qp_idr;
 extern struct idr ehca_cq_idr;
+extern spinlock_t shca_list_lock;
 
 extern int ehca_static_rate;
 extern int ehca_port_act_time;
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 523e733..3b87589 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -169,12 +169,15 @@
 	unsigned long flags;
 	u64 h_ret;
 
-	spin_lock_irqsave(&eq->spinlock, flags);
 	ibmebus_free_irq(eq->ist, (void *)shca);
 
-	h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
+	spin_lock_irqsave(&shca_list_lock, flags);
+	eq->is_initialized = 0;
+	spin_unlock_irqrestore(&shca_list_lock, flags);
 
-	spin_unlock_irqrestore(&eq->spinlock, flags);
+	tasklet_kill(&eq->interrupt_task);
+
+	h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
 
 	if (h_ret != H_SUCCESS) {
 		ehca_err(&shca->ib_device, "Can't free EQ resources.");
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index fb2d83c..129a6be 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -123,7 +123,7 @@
 DEFINE_IDR(ehca_cq_idr);
 
 static LIST_HEAD(shca_list); /* list of all registered ehcas */
-static DEFINE_SPINLOCK(shca_list_lock);
+DEFINE_SPINLOCK(shca_list_lock);
 
 static struct timer_list poll_eqs_timer;
 
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index 8fd88cd..e3ec7fd 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -400,7 +400,6 @@
 
 static inline int post_one_send(struct ehca_qp *my_qp,
 			 struct ib_send_wr *cur_send_wr,
-			 struct ib_send_wr **bad_send_wr,
 			 int hidden)
 {
 	struct ehca_wqe *wqe_p;
@@ -412,8 +411,6 @@
 	wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
 	if (unlikely(!wqe_p)) {
 		/* too many posted work requests: queue overflow */
-		if (bad_send_wr)
-			*bad_send_wr = cur_send_wr;
 		ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
 			 "qp_num=%x", my_qp->ib_qp.qp_num);
 		return -ENOMEM;
@@ -433,8 +430,6 @@
 	 */
 	if (unlikely(ret)) {
 		my_qp->ipz_squeue.current_q_offset = start_offset;
-		if (bad_send_wr)
-			*bad_send_wr = cur_send_wr;
 		ehca_err(my_qp->ib_qp.device, "Could not write WQE "
 			 "qp_num=%x", my_qp->ib_qp.qp_num);
 		return -EINVAL;
@@ -448,7 +443,6 @@
 		   struct ib_send_wr **bad_send_wr)
 {
 	struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
-	struct ib_send_wr *cur_send_wr;
 	int wqe_cnt = 0;
 	int ret = 0;
 	unsigned long flags;
@@ -457,7 +451,8 @@
 	if (unlikely(my_qp->state < IB_QPS_RTS)) {
 		ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
 			 my_qp->state, qp->qp_num);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
 
 	/* LOCK the QUEUE */
@@ -476,24 +471,21 @@
 		struct ib_send_wr circ_wr;
 		memset(&circ_wr, 0, sizeof(circ_wr));
 		circ_wr.opcode = IB_WR_RDMA_READ;
-		post_one_send(my_qp, &circ_wr, NULL, 1); /* ignore retcode */
+		post_one_send(my_qp, &circ_wr, 1); /* ignore retcode */
 		wqe_cnt++;
 		ehca_dbg(qp->device, "posted circ wr  qp_num=%x", qp->qp_num);
 		my_qp->message_count = my_qp->packet_count = 0;
 	}
 
 	/* loop processes list of send reqs */
-	for (cur_send_wr = send_wr; cur_send_wr != NULL;
-	     cur_send_wr = cur_send_wr->next) {
-		ret = post_one_send(my_qp, cur_send_wr, bad_send_wr, 0);
+	while (send_wr) {
+		ret = post_one_send(my_qp, send_wr, 0);
 		if (unlikely(ret)) {
-			/* if one or more WQEs were successful, don't fail */
-			if (wqe_cnt)
-				ret = 0;
 			goto post_send_exit0;
 		}
 		wqe_cnt++;
-	} /* eof for cur_send_wr */
+		send_wr = send_wr->next;
+	}
 
 post_send_exit0:
 	iosync(); /* serialize GAL register access */
@@ -503,6 +495,10 @@
 			 my_qp, qp->qp_num, wqe_cnt, ret);
 	my_qp->message_count += wqe_cnt;
 	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+
+out:
+	if (ret)
+		*bad_send_wr = send_wr;
 	return ret;
 }
 
@@ -511,7 +507,6 @@
 			      struct ib_recv_wr *recv_wr,
 			      struct ib_recv_wr **bad_recv_wr)
 {
-	struct ib_recv_wr *cur_recv_wr;
 	struct ehca_wqe *wqe_p;
 	int wqe_cnt = 0;
 	int ret = 0;
@@ -522,27 +517,23 @@
 	if (unlikely(!HAS_RQ(my_qp))) {
 		ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
 			 my_qp, my_qp->real_qp_num, my_qp->ext_type);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out;
 	}
 
 	/* LOCK the QUEUE */
 	spin_lock_irqsave(&my_qp->spinlock_r, flags);
 
-	/* loop processes list of send reqs */
-	for (cur_recv_wr = recv_wr; cur_recv_wr != NULL;
-	     cur_recv_wr = cur_recv_wr->next) {
+	/* loop processes list of recv reqs */
+	while (recv_wr) {
 		u64 start_offset = my_qp->ipz_rqueue.current_q_offset;
 		/* get pointer next to free WQE */
 		wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue);
 		if (unlikely(!wqe_p)) {
 			/* too many posted work requests: queue overflow */
-			if (bad_recv_wr)
-				*bad_recv_wr = cur_recv_wr;
-			if (wqe_cnt == 0) {
-				ret = -ENOMEM;
-				ehca_err(dev, "Too many posted WQEs "
-					 "qp_num=%x", my_qp->real_qp_num);
-			}
+			ret = -ENOMEM;
+			ehca_err(dev, "Too many posted WQEs "
+				"qp_num=%x", my_qp->real_qp_num);
 			goto post_recv_exit0;
 		}
 		/*
@@ -552,7 +543,7 @@
 		rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size;
 
 		/* write a RECV WQE into the QUEUE */
-		ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr,
+		ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, recv_wr,
 				rq_map_idx);
 		/*
 		 * if something failed,
@@ -560,22 +551,20 @@
 		 */
 		if (unlikely(ret)) {
 			my_qp->ipz_rqueue.current_q_offset = start_offset;
-			*bad_recv_wr = cur_recv_wr;
-			if (wqe_cnt == 0) {
-				ret = -EINVAL;
-				ehca_err(dev, "Could not write WQE "
-					 "qp_num=%x", my_qp->real_qp_num);
-			}
+			ret = -EINVAL;
+			ehca_err(dev, "Could not write WQE "
+				"qp_num=%x", my_qp->real_qp_num);
 			goto post_recv_exit0;
 		}
 
 		qmap_entry = &my_qp->rq_map.map[rq_map_idx];
-		qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id);
+		qmap_entry->app_wr_id = get_app_wr_id(recv_wr->wr_id);
 		qmap_entry->reported = 0;
 		qmap_entry->cqe_req = 1;
 
 		wqe_cnt++;
-	} /* eof for cur_recv_wr */
+		recv_wr = recv_wr->next;
+	} /* eof for recv_wr */
 
 post_recv_exit0:
 	iosync(); /* serialize GAL register access */
@@ -584,6 +573,11 @@
 	    ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
 		     my_qp, my_qp->real_qp_num, wqe_cnt, ret);
 	spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
+
+out:
+	if (ret)
+		*bad_recv_wr = recv_wr;
+
 	return ret;
 }
 
@@ -597,6 +591,7 @@
 	if (unlikely(my_qp->state == IB_QPS_RESET)) {
 		ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
 			 my_qp->state, qp->qp_num);
+		*bad_recv_wr = recv_wr;
 		return -EINVAL;
 	}
 
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 013d1380..d2787fe 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -39,6 +39,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
@@ -1697,7 +1698,7 @@
 			      unsigned len, int avail)
 {
 	unsigned long flags;
-	unsigned end, cnt = 0, next;
+	unsigned end, cnt = 0;
 
 	/* There are two bits per send buffer (busy and generation) */
 	start *= 2;
@@ -1748,12 +1749,7 @@
 
 	if (dd->ipath_pioupd_thresh) {
 		end = 2 * (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k);
-		next = find_first_bit(dd->ipath_pioavailkernel, end);
-		while (next < end) {
-			cnt++;
-			next = find_next_bit(dd->ipath_pioavailkernel, end,
-					next + 1);
-		}
+		cnt = bitmap_weight(dd->ipath_pioavailkernel, end);
 	}
 	spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
 
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 3cb3f47..e596537 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -103,7 +103,7 @@
 		props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
 	if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
 		props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
-	if (dev->dev->caps.max_gso_sz)
+	if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH)
 		props->device_cap_flags |= IB_DEVICE_UD_TSO;
 	if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
 		props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 256a00c..989555c 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -54,7 +54,8 @@
 	/*
 	 * Largest possible UD header: send with GRH and immediate data.
 	 */
-	MLX4_IB_UD_HEADER_SIZE		= 72
+	MLX4_IB_UD_HEADER_SIZE		= 72,
+	MLX4_IB_LSO_HEADER_SPARE	= 128,
 };
 
 struct mlx4_ib_sqp {
@@ -67,7 +68,8 @@
 };
 
 enum {
-	MLX4_IB_MIN_SQ_STRIDE = 6
+	MLX4_IB_MIN_SQ_STRIDE	= 6,
+	MLX4_IB_CACHE_LINE_SIZE	= 64,
 };
 
 static const __be32 mlx4_ib_opcode[] = {
@@ -261,7 +263,7 @@
 	case IB_QPT_UD:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_datagram_seg) +
-			((flags & MLX4_IB_QP_LSO) ? 64 : 0);
+			((flags & MLX4_IB_QP_LSO) ? MLX4_IB_LSO_HEADER_SPARE : 0);
 	case IB_QPT_UC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_raddr_seg);
@@ -897,7 +899,6 @@
 
 	context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
 				     (to_mlx4_st(ibqp->qp_type) << 16));
-	context->flags     |= cpu_to_be32(1 << 8); /* DE? */
 
 	if (!(attr_mask & IB_QP_PATH_MIG_STATE))
 		context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11);
@@ -1467,16 +1468,12 @@
 
 static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
 			 struct mlx4_ib_qp *qp, unsigned *lso_seg_len,
-			 __be32 *lso_hdr_sz)
+			 __be32 *lso_hdr_sz, __be32 *blh)
 {
 	unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
 
-	/*
-	 * This is a temporary limitation and will be removed in
-	 * a forthcoming FW release:
-	 */
-	if (unlikely(halign > 64))
-		return -EINVAL;
+	if (unlikely(halign > MLX4_IB_CACHE_LINE_SIZE))
+		*blh = cpu_to_be32(1 << 6);
 
 	if (unlikely(!(qp->flags & MLX4_IB_QP_LSO) &&
 		     wr->num_sge > qp->sq.max_gs - (halign >> 4)))
@@ -1522,6 +1519,7 @@
 	__be32 dummy;
 	__be32 *lso_wqe;
 	__be32 uninitialized_var(lso_hdr_sz);
+	__be32 blh;
 	int i;
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
@@ -1530,6 +1528,7 @@
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		lso_wqe = &dummy;
+		blh = 0;
 
 		if (mlx4_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
 			err = -ENOMEM;
@@ -1616,7 +1615,7 @@
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
 			if (wr->opcode == IB_WR_LSO) {
-				err = build_lso_seg(wqe, wr, qp, &seglen, &lso_hdr_sz);
+				err = build_lso_seg(wqe, wr, qp, &seglen, &lso_hdr_sz, &blh);
 				if (unlikely(err)) {
 					*bad_wr = wr;
 					goto out;
@@ -1687,7 +1686,7 @@
 		}
 
 		ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
-			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0);
+			(ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
 		stamp = ind + qp->sq_spare_wqes;
 		ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift);
diff --git a/drivers/infiniband/hw/nes/Kconfig b/drivers/infiniband/hw/nes/Kconfig
index d449eb6..846dc97 100644
--- a/drivers/infiniband/hw/nes/Kconfig
+++ b/drivers/infiniband/hw/nes/Kconfig
@@ -4,14 +4,13 @@
 	select LIBCRC32C
 	select INET_LRO
 	---help---
-	  This is a low-level driver for NetEffect RDMA enabled
-	  Network Interface Cards (RNIC).
+	  This is the RDMA Network Interface Card (RNIC) driver for
+	  NetEffect Ethernet Cluster Server Adapters.
 
 config INFINIBAND_NES_DEBUG
 	bool "Verbose debugging output"
 	depends on INFINIBAND_NES
 	default n
 	---help---
-	  This option causes the NetEffect RNIC driver to produce debug
-	  messages.  Select this if you are developing the driver
-	  or trying to diagnose a problem.
+	  This option enables debug messages from the NetEffect RNIC
+	  driver.  Select this if you are diagnosing a problem.
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index cbde0cf..b9d09ba 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -521,7 +521,8 @@
 	spin_lock_init(&nesdev->indexed_regs_lock);
 
 	/* Remap the PCI registers in adapter BAR0 to kernel VA space */
-	mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), sizeof(mmio_regs));
+	mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0),
+				    pci_resource_len(pcidev, BAR_0));
 	if (mmio_regs == NULL) {
 		printk(KERN_ERR PFX "Unable to remap BAR0\n");
 		ret = -EIO;
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index bcc6abc..9884056 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 73473db..39468c27 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -52,6 +52,7 @@
 #include <linux/random.h>
 #include <linux/list.h>
 #include <linux/threads.h>
+#include <linux/highmem.h>
 #include <net/arp.h>
 #include <net/neighbour.h>
 #include <net/route.h>
@@ -251,6 +252,33 @@
 
 	mpa_frame = (struct ietf_mpa_frame *)buffer;
 	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
+	/* make sure mpa private data len is less than 512 bytes */
+	if (cm_node->mpa_frame_size > IETF_MAX_PRIV_DATA_LEN) {
+		nes_debug(NES_DBG_CM, "The received Length of Private"
+			" Data field exceeds 512 octets\n");
+		return -EINVAL;
+	}
+	/*
+	 * make sure MPA receiver interoperate with the
+	 * received MPA version and MPA key information
+	 *
+	 */
+	if (mpa_frame->rev != mpa_version) {
+		nes_debug(NES_DBG_CM, "The received mpa version"
+				" can not be interoperated\n");
+		return -EINVAL;
+	}
+	if (cm_node->state != NES_CM_STATE_MPAREQ_SENT) {
+		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) {
+			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
+			return -EINVAL;
+		}
+	} else {
+		if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE)) {
+			nes_debug(NES_DBG_CM, "Unexpected MPA Key received \n");
+			return -EINVAL;
+		}
+	}
 
 	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
 		nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
@@ -486,6 +514,8 @@
 		send_reset(cm_node, NULL);
 		break;
 	default:
+		add_ref_cm_node(cm_node);
+		send_reset(cm_node, NULL);
 		create_event(cm_node, NES_CM_EVENT_ABORTED);
 	}
 }
@@ -949,6 +979,7 @@
 				reset_entry);
 		{
 			struct nes_cm_node *loopback = cm_node->loopbackpartner;
+			enum nes_cm_node_state old_state;
 			if (NES_CM_STATE_FIN_WAIT1 <= cm_node->state) {
 				rem_ref_cm_node(cm_node->cm_core, cm_node);
 			} else {
@@ -960,11 +991,12 @@
 							 NES_CM_STATE_CLOSED;
 						WARN_ON(1);
 					} else {
-						cm_node->state =
-							NES_CM_STATE_CLOSED;
-						rem_ref_cm_node(
-							cm_node->cm_core,
-							cm_node);
+						old_state = cm_node->state;
+						cm_node->state = NES_CM_STATE_LISTENER_DESTROYED;
+						if (old_state != NES_CM_STATE_MPAREQ_RCVD)
+							rem_ref_cm_node(
+								cm_node->cm_core,
+								cm_node);
 					}
 				} else {
 					struct nes_cm_event event;
@@ -980,20 +1012,9 @@
 							 loopback->loc_port;
 					event.cm_info.cm_id = loopback->cm_id;
 					cm_event_connect_error(&event);
+					cm_node->state = NES_CM_STATE_LISTENER_DESTROYED;
 					loopback->state = NES_CM_STATE_CLOSED;
 
-					event.cm_node = cm_node;
-					event.cm_info.rem_addr =
-							 cm_node->rem_addr;
-					event.cm_info.loc_addr =
-							 cm_node->loc_addr;
-					event.cm_info.rem_port =
-							 cm_node->rem_port;
-					event.cm_info.loc_port =
-							 cm_node->loc_port;
-					event.cm_info.cm_id = cm_node->cm_id;
-					cm_event_reset(&event);
-
 					rem_ref_cm_node(cm_node->cm_core,
 							 cm_node);
 
@@ -1077,12 +1098,13 @@
 /**
  * nes_addr_resolve_neigh
  */
-static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
+static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpindex)
 {
 	struct rtable *rt;
 	struct flowi fl;
 	struct neighbour *neigh;
-	int rc = -1;
+	int rc = arpindex;
+	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 
 	memset(&fl, 0, sizeof fl);
 	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
@@ -1098,6 +1120,21 @@
 			nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
 				  " is %pM, Gateway is 0x%08X \n", dst_ip,
 				  neigh->ha, ntohl(rt->rt_gateway));
+
+			if (arpindex >= 0) {
+				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
+							neigh->ha, ETH_ALEN)){
+					/* Mac address same as in nes_arp_table */
+					neigh_release(neigh);
+					ip_rt_put(rt);
+					return rc;
+				}
+
+				nes_manage_arp_cache(nesvnic->netdev,
+						nesadapter->arp_table[arpindex].mac_addr,
+						dst_ip, NES_ARP_DELETE);
+			}
+
 			nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
 					     dst_ip, NES_ARP_ADD);
 			rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
@@ -1113,7 +1150,6 @@
 	return rc;
 }
 
-
 /**
  * make_cm_node - create a new instance of a cm node
  */
@@ -1123,6 +1159,7 @@
 {
 	struct nes_cm_node *cm_node;
 	struct timespec ts;
+	int oldarpindex = 0;
 	int arpindex = 0;
 	struct nes_device *nesdev;
 	struct nes_adapter *nesadapter;
@@ -1176,17 +1213,18 @@
 	nesadapter = nesdev->nesadapter;
 
 	cm_node->loopbackpartner = NULL;
+
 	/* get the mac addr for the remote node */
 	if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
 		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
-	else
-		arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
+	else {
+		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
+		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
+
+	}
 	if (arpindex < 0) {
-		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr);
-		if (arpindex < 0) {
-			kfree(cm_node);
-			return NULL;
-		}
+		kfree(cm_node);
+		return NULL;
 	}
 
 	/* copy the mac addr to node context */
@@ -1333,13 +1371,20 @@
 	case NES_CM_STATE_SYN_RCVD:
 	case NES_CM_STATE_SYN_SENT:
 	case NES_CM_STATE_ESTABLISHED:
-	case NES_CM_STATE_MPAREQ_SENT:
 	case NES_CM_STATE_MPAREJ_RCVD:
 		cm_node->tcp_cntxt.rcv_nxt++;
 		cleanup_retrans_entry(cm_node);
 		cm_node->state = NES_CM_STATE_LAST_ACK;
 		send_fin(cm_node, NULL);
 		break;
+	case NES_CM_STATE_MPAREQ_SENT:
+		create_event(cm_node, NES_CM_EVENT_ABORTED);
+		cm_node->tcp_cntxt.rcv_nxt++;
+		cleanup_retrans_entry(cm_node);
+		cm_node->state = NES_CM_STATE_CLOSED;
+		add_ref_cm_node(cm_node);
+		send_reset(cm_node, NULL);
+		break;
 	case NES_CM_STATE_FIN_WAIT1:
 		cm_node->tcp_cntxt.rcv_nxt++;
 		cleanup_retrans_entry(cm_node);
@@ -1590,6 +1635,7 @@
 		break;
 	case NES_CM_STATE_CLOSED:
 		cleanup_retrans_entry(cm_node);
+		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
 		break;
 	case NES_CM_STATE_TSA:
@@ -1641,9 +1687,15 @@
 		passive_open_err(cm_node, skb, 1);
 		break;
 	case NES_CM_STATE_LISTENING:
+		cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
+		cleanup_retrans_entry(cm_node);
+		cm_node->state = NES_CM_STATE_CLOSED;
+		send_reset(cm_node, skb);
+		break;
 	case NES_CM_STATE_CLOSED:
 		cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
 		cleanup_retrans_entry(cm_node);
+		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
 		break;
 	case NES_CM_STATE_ESTABLISHED:
@@ -1712,8 +1764,13 @@
 			dev_kfree_skb_any(skb);
 		break;
 	case NES_CM_STATE_LISTENING:
+		cleanup_retrans_entry(cm_node);
+		cm_node->state = NES_CM_STATE_CLOSED;
+		send_reset(cm_node, skb);
+		break;
 	case NES_CM_STATE_CLOSED:
 		cleanup_retrans_entry(cm_node);
+		add_ref_cm_node(cm_node);
 		send_reset(cm_node, skb);
 		break;
 	case NES_CM_STATE_LAST_ACK:
@@ -1974,7 +2031,7 @@
 	if (!cm_node)
 		return NULL;
 	mpa_frame = &cm_node->mpa_frame;
-	strcpy(mpa_frame->key, IEFT_MPA_KEY_REQ);
+	memcpy(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE);
 	mpa_frame->flags = IETF_MPA_FLAGS_CRC;
 	mpa_frame->rev =  IETF_MPA_VERSION;
 	mpa_frame->priv_data_len = htons(private_data_len);
@@ -2102,30 +2159,39 @@
 			cm_node->state = NES_CM_STATE_CLOSED;
 			rem_ref_cm_node(cm_core, cm_node);
 		} else {
-			ret = send_mpa_reject(cm_node);
-			if (ret) {
-				cm_node->state = NES_CM_STATE_CLOSED;
-				err = send_reset(cm_node, NULL);
-				if (err)
-					WARN_ON(1);
-			} else
-				cm_id->add_ref(cm_id);
+			if (cm_node->state == NES_CM_STATE_LISTENER_DESTROYED) {
+				rem_ref_cm_node(cm_core, cm_node);
+			} else {
+				ret = send_mpa_reject(cm_node);
+				if (ret) {
+					cm_node->state = NES_CM_STATE_CLOSED;
+					err = send_reset(cm_node, NULL);
+					if (err)
+						WARN_ON(1);
+				} else
+					cm_id->add_ref(cm_id);
+			}
 		}
 	} else {
 		cm_node->cm_id = NULL;
-		event.cm_node = loopback;
-		event.cm_info.rem_addr = loopback->rem_addr;
-		event.cm_info.loc_addr = loopback->loc_addr;
-		event.cm_info.rem_port = loopback->rem_port;
-		event.cm_info.loc_port = loopback->loc_port;
-		event.cm_info.cm_id = loopback->cm_id;
-		cm_event_mpa_reject(&event);
-		rem_ref_cm_node(cm_core, cm_node);
-		loopback->state = NES_CM_STATE_CLOSING;
+		if (cm_node->state == NES_CM_STATE_LISTENER_DESTROYED) {
+			rem_ref_cm_node(cm_core, cm_node);
+			rem_ref_cm_node(cm_core, loopback);
+		} else {
+			event.cm_node = loopback;
+			event.cm_info.rem_addr = loopback->rem_addr;
+			event.cm_info.loc_addr = loopback->loc_addr;
+			event.cm_info.rem_port = loopback->rem_port;
+			event.cm_info.loc_port = loopback->loc_port;
+			event.cm_info.cm_id = loopback->cm_id;
+			cm_event_mpa_reject(&event);
+			rem_ref_cm_node(cm_core, cm_node);
+			loopback->state = NES_CM_STATE_CLOSING;
 
-		cm_id = loopback->cm_id;
-		rem_ref_cm_node(cm_core, loopback);
-		cm_id->rem_ref(cm_id);
+			cm_id = loopback->cm_id;
+			rem_ref_cm_node(cm_core, loopback);
+			cm_id->rem_ref(cm_id);
+		}
 	}
 
 	return ret;
@@ -2164,11 +2230,15 @@
 	case NES_CM_STATE_CLOSING:
 		ret = -1;
 		break;
-	case NES_CM_STATE_MPAREJ_RCVD:
 	case NES_CM_STATE_LISTENING:
+		cleanup_retrans_entry(cm_node);
+		send_reset(cm_node, NULL);
+		break;
+	case NES_CM_STATE_MPAREJ_RCVD:
 	case NES_CM_STATE_UNKNOWN:
 	case NES_CM_STATE_INITED:
 	case NES_CM_STATE_CLOSED:
+	case NES_CM_STATE_LISTENER_DESTROYED:
 		ret = rem_ref_cm_node(cm_core, cm_node);
 		break;
 	case NES_CM_STATE_TSA:
@@ -2687,8 +2757,6 @@
 	struct nes_pd *nespd;
 	u64 tagged_offset;
 
-
-
 	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
 	if (!ibqp)
 		return -EINVAL;
@@ -2704,6 +2772,13 @@
 		"%s\n", cm_node, nesvnic, nesvnic->netdev,
 		nesvnic->netdev->name);
 
+	if (NES_CM_STATE_LISTENER_DESTROYED == cm_node->state) {
+		if (cm_node->loopbackpartner)
+			rem_ref_cm_node(cm_node->cm_core, cm_node->loopbackpartner);
+		rem_ref_cm_node(cm_node->cm_core, cm_node);
+		return -EINVAL;
+	}
+
 	/* associate the node with the QP */
 	nesqp->cm_node = (void *)cm_node;
 	cm_node->nesqp = nesqp;
@@ -2786,6 +2861,10 @@
 			cpu_to_le32(conn_param->private_data_len +
 			sizeof(struct ietf_mpa_frame));
 		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey;
+		if (nesqp->sq_kmapped) {
+			nesqp->sq_kmapped = 0;
+			kunmap(nesqp->page);
+		}
 
 		nesqp->nesqp_context->ird_ord_sizes |=
 			cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
@@ -2929,7 +3008,7 @@
 	if (cm_node->mpa_frame_size > MAX_CM_BUFFER)
 		return -EINVAL;
 
-	strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP);
+	memcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
 	if (loopback) {
 		memcpy(&loopback->mpa_frame.priv_data, pdata, pdata_len);
 		loopback->mpa_frame.priv_data_len = pdata_len;
@@ -2974,6 +3053,9 @@
 	if (!nesdev)
 		return -EINVAL;
 
+	if (!(cm_id->local_addr.sin_port) || !(cm_id->remote_addr.sin_port))
+		return -EINVAL;
+
 	nes_debug(NES_DBG_CM, "QP%u, current IP = 0x%08X, Destination IP = "
 		"0x%08X:0x%04X, local = 0x%08X:0x%04X.\n", nesqp->hwqp.qp_id,
 		ntohl(nesvnic->local_ipaddr),
@@ -3251,6 +3333,11 @@
 		wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
 		wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
 
+		if (nesqp->sq_kmapped) {
+			nesqp->sq_kmapped = 0;
+			kunmap(nesqp->page);
+		}
+
 		/* use the reserved spot on the WQ for the extra first WQE */
 		nesqp->nesqp_context->ird_ord_sizes &=
 			cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
@@ -3346,7 +3433,7 @@
 	nesqp->cm_id = NULL;
 	cm_id->provider_data = NULL;
 	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
-	cm_event.status = IW_CM_EVENT_STATUS_REJECTED;
+	cm_event.status = -ECONNRESET;
 	cm_event.provider_data = cm_id->provider_data;
 	cm_event.local_addr = cm_id->local_addr;
 	cm_event.remote_addr = cm_id->remote_addr;
@@ -3390,6 +3477,8 @@
 
 	nes_debug(NES_DBG_CM, "%p - cm_id = %p\n", event->cm_node, cm_id);
 	nesqp = cm_id->provider_data;
+	if (!nesqp)
+		return;
 
 	nesqp->cm_id = NULL;
 	/* cm_id->provider_data = NULL; */
@@ -3401,8 +3490,8 @@
 	cm_event.private_data = NULL;
 	cm_event.private_data_len = 0;
 
-	ret = cm_id->event_handler(cm_id, &cm_event);
 	cm_id->add_ref(cm_id);
+	ret = cm_id->event_handler(cm_id, &cm_event);
 	atomic_inc(&cm_closes);
 	cm_event.event = IW_CM_EVENT_CLOSE;
 	cm_event.status = IW_CM_EVENT_STATUS_OK;
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index 90e8e4d..d9825fd 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -47,6 +47,8 @@
 #define IEFT_MPA_KEY_REP  "MPA ID Rep Frame"
 #define IETF_MPA_KEY_SIZE 16
 #define IETF_MPA_VERSION  1
+#define IETF_MAX_PRIV_DATA_LEN 512
+#define IETF_MPA_FRAME_SIZE     20
 
 enum ietf_mpa_flags {
 	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */
@@ -169,7 +171,7 @@
 
 #define NES_CM_DEF_SEQ2      0x18ed5740
 #define NES_CM_DEF_LOCAL_ID2 0xb807
-#define	MAX_CM_BUFFER	512
+#define	MAX_CM_BUFFER	(IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN)
 
 
 typedef u32 nes_addr_t;
@@ -198,6 +200,7 @@
 	NES_CM_STATE_TIME_WAIT,
 	NES_CM_STATE_LAST_ACK,
 	NES_CM_STATE_CLOSING,
+	NES_CM_STATE_LISTENER_DESTROYED,
 	NES_CM_STATE_CLOSED
 };
 
diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h
index 0fb8d81..b4393a1 100644
--- a/drivers/infiniband/hw/nes/nes_context.h
+++ b/drivers/infiniband/hw/nes/nes_context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 3512d6d..b1c2cbb 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -424,8 +424,9 @@
 
 	nesadapter->base_pd = 1;
 
-	nesadapter->device_cap_flags =
-		IB_DEVICE_LOCAL_DMA_LKEY | IB_DEVICE_MEM_WINDOW;
+	nesadapter->device_cap_flags = IB_DEVICE_LOCAL_DMA_LKEY |
+				       IB_DEVICE_MEM_WINDOW |
+				       IB_DEVICE_MEM_MGT_EXTENSIONS;
 
 	nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
 			[(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
@@ -436,11 +437,12 @@
 	nesadapter->qp_table = (struct nes_qp **)(&nesadapter->allocated_arps[BITS_TO_LONGS(arp_table_size)]);
 
 
-	/* mark the usual suspect QPs and CQs as in use */
+	/* mark the usual suspect QPs, MR and CQs as in use */
 	for (u32temp = 0; u32temp < NES_FIRST_QPN; u32temp++) {
 		set_bit(u32temp, nesadapter->allocated_qps);
 		set_bit(u32temp, nesadapter->allocated_cqs);
 	}
+	set_bit(0, nesadapter->allocated_mrs);
 
 	for (u32temp = 0; u32temp < 20; u32temp++)
 		set_bit(u32temp, nesadapter->allocated_pds);
@@ -481,7 +483,7 @@
 	nesadapter->max_irrq_wr = (u32temp >> 16) & 3;
 
 	nesadapter->max_sge = 4;
-	nesadapter->max_cqe = 32767;
+	nesadapter->max_cqe = 32766;
 
 	if (nes_read_eeprom_values(nesdev, nesadapter)) {
 		printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
@@ -1355,6 +1357,8 @@
 	}
 	if ((phy_type == NES_PHY_TYPE_ARGUS) ||
 	    (phy_type == NES_PHY_TYPE_SFP_D)) {
+		u32 first_time = 1;
+
 		/* Check firmware heartbeat */
 		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
 		temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
@@ -1362,8 +1366,13 @@
 		nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee);
 		temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
 
-		if (temp_phy_data != temp_phy_data2)
-			return 0;
+		if (temp_phy_data != temp_phy_data2) {
+			nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
+			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+			if ((temp_phy_data & 0xff) > 0x20)
+				return 0;
+			printk(PFX "Reinitializing PHY\n");
+		}
 
 		/* no heartbeat, configure the PHY */
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000);
@@ -1399,7 +1408,7 @@
 		temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
 		do {
 			if (counter++ > 150) {
-				nes_debug(NES_DBG_PHY, "No PHY heartbeat\n");
+				printk(PFX "No PHY heartbeat\n");
 				break;
 			}
 			mdelay(1);
@@ -1413,11 +1422,20 @@
 			nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd);
 			temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
 			if (counter++ > 300) {
-				nes_debug(NES_DBG_PHY, "PHY did not track\n");
-				break;
+				if (((temp_phy_data & 0xff) == 0x0) && first_time) {
+					first_time = 0;
+					counter = 0;
+					/* reset AMCC PHY and try again */
+					nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x00c0);
+					nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x0040);
+					continue;
+				} else {
+					printk(PFX "PHY did not track\n");
+					break;
+				}
 			}
 			mdelay(10);
-		} while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
+		} while ((temp_phy_data & 0xff) < 0x30);
 
 		/* setup signal integrity */
 		nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000);
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index f28a41b..084be0e 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+* Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
@@ -546,11 +546,23 @@
 	NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX = 14,
 };
 
+enum nes_iwarp_sq_fmr_opcodes {
+	NES_IWARP_SQ_FMR_WQE_ZERO_BASED			= (1<<6),
+	NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K		= (0<<7),
+	NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M		= (1<<7),
+	NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ	= (1<<16),
+	NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_WRITE 	= (1<<17),
+	NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_READ 	= (1<<18),
+	NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_WRITE = (1<<19),
+	NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND 	= (1<<20),
+};
+
+#define NES_IWARP_SQ_FMR_WQE_MR_LENGTH_HIGH_MASK	0xFF;
+
 enum nes_iwarp_sq_locinv_wqe_word_idx {
 	NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX = 6,
 };
 
-
 enum nes_iwarp_rq_wqe_word_idx {
 	NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX = 1,
 	NES_IWARP_RQ_WQE_COMP_CTX_LOW_IDX = 2,
@@ -1153,6 +1165,19 @@
 	/* TODO: need to add list for two level tables */
 };
 
+#define NES_4K_PBL_CHUNK_SIZE	4096
+
+struct nes_fast_mr_wqe_pbl {
+	u64		*kva;
+	dma_addr_t	paddr;
+};
+
+struct nes_ib_fast_reg_page_list {
+	struct ib_fast_reg_page_list	ibfrpl;
+	struct nes_fast_mr_wqe_pbl 	nes_wqe_pbl;
+	u64 				pbl;
+};
+
 struct nes_listener {
 	struct work_struct      work;
 	struct workqueue_struct *wq;
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index de18fdf..ab11027 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h
index cc90c14..71e133a 100644
--- a/drivers/infiniband/hw/nes/nes_user.h
+++ b/drivers/infiniband/hw/nes/nes_user.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Topspin Communications.  All rights reserved.
  * Copyright (c) 2005 Cisco Systems.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
@@ -86,6 +86,7 @@
 	IWNES_MEMREG_TYPE_CQ = 0x0002,
 	IWNES_MEMREG_TYPE_MW = 0x0003,
 	IWNES_MEMREG_TYPE_FMR = 0x0004,
+	IWNES_MEMREG_TYPE_FMEM = 0x0005,
 };
 
 struct nes_mem_reg_req {
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index 9687c39..729d525 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index a680c42..64d3136 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -275,342 +275,236 @@
 }
 
 
-/**
- * nes_alloc_fmr
+/*
+ * nes_alloc_fast_mr
  */
-static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
-		int ibmr_access_flags,
-		struct ib_fmr_attr *ibfmr_attr)
+static int alloc_fast_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
+			     u32 stag, u32 page_count)
 {
-	unsigned long flags;
-	struct nes_pd *nespd = to_nespd(ibpd);
-	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
-	struct nes_device *nesdev = nesvnic->nesdev;
-	struct nes_adapter *nesadapter = nesdev->nesadapter;
-	struct nes_fmr *nesfmr;
-	struct nes_cqp_request *cqp_request;
 	struct nes_hw_cqp_wqe *cqp_wqe;
+	struct nes_cqp_request *cqp_request;
+	unsigned long flags;
 	int ret;
-	u32 stag;
-	u32 stag_index = 0;
-	u32 next_stag_index = 0;
-	u32 driver_key = 0;
+	struct nes_adapter *nesadapter = nesdev->nesadapter;
 	u32 opcode = 0;
-	u8 stag_key = 0;
-	int i=0;
-	struct nes_vpbl vpbl;
+	u16 major_code;
+	u64 region_length = page_count * PAGE_SIZE;
 
-	get_random_bytes(&next_stag_index, sizeof(next_stag_index));
-	stag_key = (u8)next_stag_index;
 
-	driver_key = 0;
-
-	next_stag_index >>= 8;
-	next_stag_index %= nesadapter->max_mr;
-
-	ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
-			nesadapter->max_mr, &stag_index, &next_stag_index);
-	if (ret) {
-		goto failed_resource_alloc;
-	}
-
-	nesfmr = kzalloc(sizeof(*nesfmr), GFP_KERNEL);
-	if (!nesfmr) {
-		ret = -ENOMEM;
-		goto failed_fmr_alloc;
-	}
-
-	nesfmr->nesmr.mode = IWNES_MEMREG_TYPE_FMR;
-	if (ibfmr_attr->max_pages == 1) {
-		/* use zero length PBL */
-		nesfmr->nesmr.pbl_4k = 0;
-		nesfmr->nesmr.pbls_used = 0;
-	} else if (ibfmr_attr->max_pages <= 32) {
-		/* use PBL 256 */
-		nesfmr->nesmr.pbl_4k = 0;
-		nesfmr->nesmr.pbls_used = 1;
-	} else if (ibfmr_attr->max_pages <= 512) {
-		/* use 4K PBLs */
-		nesfmr->nesmr.pbl_4k = 1;
-		nesfmr->nesmr.pbls_used = 1;
-	} else {
-		/* use two level 4K PBLs */
-		/* add support for two level 256B PBLs */
-		nesfmr->nesmr.pbl_4k = 1;
-		nesfmr->nesmr.pbls_used = 1 + (ibfmr_attr->max_pages >> 9) +
-				((ibfmr_attr->max_pages & 511) ? 1 : 0);
-	}
-	/* Register the region with the adapter */
-	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
-
-	/* track PBL resources */
-	if (nesfmr->nesmr.pbls_used != 0) {
-		if (nesfmr->nesmr.pbl_4k) {
-			if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) {
-				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-				ret = -ENOMEM;
-				goto failed_vpbl_avail;
-			} else {
-				nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used;
-			}
-		} else {
-			if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) {
-				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-				ret = -ENOMEM;
-				goto failed_vpbl_avail;
-			} else {
-				nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used;
-			}
-		}
-	}
-
-	/* one level pbl */
-	if (nesfmr->nesmr.pbls_used == 0) {
-		nesfmr->root_vpbl.pbl_vbase = NULL;
-		nes_debug(NES_DBG_MR,  "zero level pbl \n");
-	} else if (nesfmr->nesmr.pbls_used == 1) {
-		/* can change it to kmalloc & dma_map_single */
-		nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
-				&nesfmr->root_vpbl.pbl_pbase);
-		if (!nesfmr->root_vpbl.pbl_vbase) {
-			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-			ret = -ENOMEM;
-			goto failed_vpbl_alloc;
-		}
-		nesfmr->leaf_pbl_cnt = 0;
-		nes_debug(NES_DBG_MR, "one level pbl, root_vpbl.pbl_vbase=%p \n",
-				nesfmr->root_vpbl.pbl_vbase);
-	}
-	/* two level pbl */
-	else {
-		nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192,
-				&nesfmr->root_vpbl.pbl_pbase);
-		if (!nesfmr->root_vpbl.pbl_vbase) {
-			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-			ret = -ENOMEM;
-			goto failed_vpbl_alloc;
-		}
-
-		nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1;
-		nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_ATOMIC);
-		if (!nesfmr->root_vpbl.leaf_vpbl) {
-			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-			ret = -ENOMEM;
-			goto failed_leaf_vpbl_alloc;
-		}
-
-		nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p"
-				" leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n",
-				nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl);
-
-		for (i=0; i<nesfmr->leaf_pbl_cnt; i++)
-			nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase = NULL;
-
-		for (i=0; i<nesfmr->leaf_pbl_cnt; i++) {
-			vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
-					&vpbl.pbl_pbase);
-
-			if (!vpbl.pbl_vbase) {
-				ret = -ENOMEM;
-				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
-				goto failed_leaf_vpbl_pages_alloc;
-			}
-
-			nesfmr->root_vpbl.pbl_vbase[i].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase);
-			nesfmr->root_vpbl.pbl_vbase[i].pa_high = cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32)));
-			nesfmr->root_vpbl.leaf_vpbl[i] = vpbl;
-
-			nes_debug(NES_DBG_MR, "pbase_low=0x%x, pbase_high=0x%x, vpbl=%p\n",
-					nesfmr->root_vpbl.pbl_vbase[i].pa_low,
-					nesfmr->root_vpbl.pbl_vbase[i].pa_high,
-					&nesfmr->root_vpbl.leaf_vpbl[i]);
-		}
-	}
-	nesfmr->ib_qp = NULL;
-	nesfmr->access_rights =0;
-
-	stag = stag_index << 8;
-	stag |= driver_key;
-	stag += (u32)stag_key;
-
-	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
 	cqp_request = nes_get_cqp_request(nesdev);
 	if (cqp_request == NULL) {
 		nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
-		ret = -ENOMEM;
-		goto failed_leaf_vpbl_pages_alloc;
+		return -ENOMEM;
 	}
+	nes_debug(NES_DBG_MR, "alloc_fast_reg_mr: page_count = %d, "
+			      "region_length = %llu\n",
+			      page_count, region_length);
 	cqp_request->waiting = 1;
 	cqp_wqe = &cqp_request->cqp_wqe;
 
-	nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n",
-			stag, stag_index);
-
-	opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR;
-
-	if (nesfmr->nesmr.pbl_4k == 1)
-		opcode |= NES_CQP_STAG_PBL_BLK_SIZE;
-
-	if (ibmr_access_flags & IB_ACCESS_REMOTE_WRITE) {
-		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE |
-				NES_CQP_STAG_RIGHTS_LOCAL_WRITE | NES_CQP_STAG_REM_ACC_EN;
-		nesfmr->access_rights |=
-				NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_RIGHTS_LOCAL_WRITE |
-				NES_CQP_STAG_REM_ACC_EN;
+	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
+	if (nesadapter->free_4kpbl > 0) {
+		nesadapter->free_4kpbl--;
+		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+	} else {
+		/* No 4kpbl's available: */
+		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+		nes_debug(NES_DBG_MR, "Out of Pbls\n");
+		nes_free_cqp_request(nesdev, cqp_request);
+		return -ENOMEM;
 	}
 
-	if (ibmr_access_flags & IB_ACCESS_REMOTE_READ) {
-		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ |
-				NES_CQP_STAG_RIGHTS_LOCAL_READ | NES_CQP_STAG_REM_ACC_EN;
-		nesfmr->access_rights |=
-				NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_LOCAL_READ |
-				NES_CQP_STAG_REM_ACC_EN;
-	}
+	opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_MR |
+		 NES_CQP_STAG_PBL_BLK_SIZE | NES_CQP_STAG_VA_TO |
+		 NES_CQP_STAG_REM_ACC_EN;
+	/*
+	 * The current OFED API does not support the zero based TO option.
+	 * If added then need to changed the NES_CQP_STAG_VA* option.  Also,
+	 * the API does not support that ability to have the MR set for local
+	 * access only when created and not allow the SQ op to override. Given
+	 * this the remote enable must be set here.
+	 */
 
 	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
 	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
-	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));
-	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, 1);
 
-	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] =
-			cpu_to_le32((nesfmr->nesmr.pbls_used>1) ?
-			(nesfmr->nesmr.pbls_used-1) : nesfmr->nesmr.pbls_used);
+	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =
+			cpu_to_le32((u32)(region_length >> 8) & 0xff000000);
+	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=
+			cpu_to_le32(nespd->pd_id & 0x00007fff);
+
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
+	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, 0);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, 0);
+	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, 0);
+	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX, (page_count * 8));
+	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);
+	barrier();
 
 	atomic_set(&cqp_request->refcount, 2);
 	nes_post_cqp_request(nesdev, cqp_request);
 
 	/* Wait for CQP */
-	ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
-			NES_EVENT_TIMEOUT);
-	nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
-			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
-			stag, ret, cqp_request->major_code, cqp_request->minor_code);
+	ret = wait_event_timeout(cqp_request->waitq,
+				 (0 != cqp_request->request_done),
+				 NES_EVENT_TIMEOUT);
 
-	if ((!ret) || (cqp_request->major_code)) {
-		nes_put_cqp_request(nesdev, cqp_request);
-		ret = (!ret) ? -ETIME : -EIO;
-		goto failed_leaf_vpbl_pages_alloc;
-	}
+	nes_debug(NES_DBG_MR, "Allocate STag 0x%08X completed, "
+		  "wait_event_timeout ret = %u, CQP Major:Minor codes = "
+		  "0x%04X:0x%04X.\n", stag, ret, cqp_request->major_code,
+		  cqp_request->minor_code);
+	major_code = cqp_request->major_code;
 	nes_put_cqp_request(nesdev, cqp_request);
-	nesfmr->nesmr.ibfmr.lkey = stag;
-	nesfmr->nesmr.ibfmr.rkey = stag;
-	nesfmr->attr = *ibfmr_attr;
 
-	return &nesfmr->nesmr.ibfmr;
-
-	failed_leaf_vpbl_pages_alloc:
-	/* unroll all allocated pages */
-	for (i=0; i<nesfmr->leaf_pbl_cnt; i++) {
-		if (nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase) {
-			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase,
-					nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase);
-		}
-	}
-	if (nesfmr->root_vpbl.leaf_vpbl)
-		kfree(nesfmr->root_vpbl.leaf_vpbl);
-
-	failed_leaf_vpbl_alloc:
-	if (nesfmr->leaf_pbl_cnt == 0) {
-		if (nesfmr->root_vpbl.pbl_vbase)
-			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase,
-					nesfmr->root_vpbl.pbl_pbase);
-	} else
-		pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase,
-				nesfmr->root_vpbl.pbl_pbase);
-
-	failed_vpbl_alloc:
-	if (nesfmr->nesmr.pbls_used != 0) {
+	if (!ret || major_code) {
 		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
-		if (nesfmr->nesmr.pbl_4k)
-			nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used;
-		else
-			nesadapter->free_256pbl += nesfmr->nesmr.pbls_used;
+		nesadapter->free_4kpbl++;
 		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
 	}
 
-failed_vpbl_avail:
-	kfree(nesfmr);
-
-	failed_fmr_alloc:
-	nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
-
-	failed_resource_alloc:
-	return ERR_PTR(ret);
+	if (!ret)
+		return -ETIME;
+	else if (major_code)
+		return -EIO;
+	return 0;
 }
 
-
-/**
- * nes_dealloc_fmr
+/*
+ * nes_alloc_fast_reg_mr
  */
-static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
+struct ib_mr *nes_alloc_fast_reg_mr(struct ib_pd *ibpd, int max_page_list_len)
 {
-	unsigned long flags;
-	struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr);
-	struct nes_fmr *nesfmr = to_nesfmr(nesmr);
-	struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device);
+	struct nes_pd *nespd = to_nespd(ibpd);
+	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
 	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_adapter *nesadapter = nesdev->nesadapter;
-	int i = 0;
-	int rc;
 
-	/* free the resources */
-	if (nesfmr->leaf_pbl_cnt == 0) {
-		/* single PBL case */
-		if (nesfmr->root_vpbl.pbl_vbase)
-			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase,
-					nesfmr->root_vpbl.pbl_pbase);
+	u32 next_stag_index;
+	u8 stag_key = 0;
+	u32 driver_key = 0;
+	int err = 0;
+	u32 stag_index = 0;
+	struct nes_mr *nesmr;
+	u32 stag;
+	int ret;
+	struct ib_mr *ibmr;
+/*
+ * Note:  Set to always use a fixed length single page entry PBL.  This is to allow
+ *	 for the fast_reg_mr operation to always know the size of the PBL.
+ */
+	if (max_page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))
+		return ERR_PTR(-E2BIG);
+
+	get_random_bytes(&next_stag_index, sizeof(next_stag_index));
+	stag_key = (u8)next_stag_index;
+	next_stag_index >>= 8;
+	next_stag_index %= nesadapter->max_mr;
+
+	err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
+				 nesadapter->max_mr, &stag_index,
+				 &next_stag_index);
+	if (err)
+		return ERR_PTR(err);
+
+	nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
+	if (!nesmr) {
+		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	stag = stag_index << 8;
+	stag |= driver_key;
+	stag += (u32)stag_key;
+
+	nes_debug(NES_DBG_MR, "Allocating STag 0x%08X index = 0x%08X\n",
+		  stag, stag_index);
+
+	ret = alloc_fast_reg_mr(nesdev, nespd, stag, max_page_list_len);
+
+	if (ret == 0) {
+		nesmr->ibmr.rkey = stag;
+		nesmr->ibmr.lkey = stag;
+		nesmr->mode = IWNES_MEMREG_TYPE_FMEM;
+		ibmr = &nesmr->ibmr;
 	} else {
-		for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) {
-			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase,
-					nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase);
-		}
-		kfree(nesfmr->root_vpbl.leaf_vpbl);
-		pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase,
-				nesfmr->root_vpbl.pbl_pbase);
+		kfree(nesmr);
+		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
+		ibmr = ERR_PTR(-ENOMEM);
 	}
-	nesmr->ibmw.device = ibfmr->device;
-	nesmr->ibmw.pd = ibfmr->pd;
-	nesmr->ibmw.rkey = ibfmr->rkey;
-	nesmr->ibmw.uobject = NULL;
+	return ibmr;
+}
 
-	rc = nes_dealloc_mw(&nesmr->ibmw);
+/*
+ * nes_alloc_fast_reg_page_list
+ */
+static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list(
+							struct ib_device *ibdev,
+							int page_list_len)
+{
+	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct ib_fast_reg_page_list *pifrpl;
+	struct nes_ib_fast_reg_page_list *pnesfrpl;
 
-	if ((rc == 0) && (nesfmr->nesmr.pbls_used != 0)) {
-		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
-		if (nesfmr->nesmr.pbl_4k) {
-			nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used;
-			WARN_ON(nesadapter->free_4kpbl > nesadapter->max_4kpbl);
-		} else {
-			nesadapter->free_256pbl += nesfmr->nesmr.pbls_used;
-			WARN_ON(nesadapter->free_256pbl > nesadapter->max_256pbl);
-		}
-		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
+	if (page_list_len > (NES_4K_PBL_CHUNK_SIZE / sizeof(u64)))
+		return ERR_PTR(-E2BIG);
+	/*
+	 * Allocate the ib_fast_reg_page_list structure, the
+	 * nes_fast_bpl structure, and the PLB table.
+	 */
+	pnesfrpl = kmalloc(sizeof(struct nes_ib_fast_reg_page_list) +
+			   page_list_len * sizeof(u64), GFP_KERNEL);
+
+	if (!pnesfrpl)
+		return ERR_PTR(-ENOMEM);
+
+	pifrpl = &pnesfrpl->ibfrpl;
+	pifrpl->page_list = &pnesfrpl->pbl;
+	pifrpl->max_page_list_len = page_list_len;
+	/*
+	 * Allocate the WQE PBL
+	 */
+	pnesfrpl->nes_wqe_pbl.kva = pci_alloc_consistent(nesdev->pcidev,
+							 page_list_len * sizeof(u64),
+							 &pnesfrpl->nes_wqe_pbl.paddr);
+
+	if (!pnesfrpl->nes_wqe_pbl.kva) {
+		kfree(pnesfrpl);
+		return ERR_PTR(-ENOMEM);
 	}
+	nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "
+		  "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "
+		  "pbl.paddr= %p\n", pnesfrpl, &pnesfrpl->ibfrpl,
+		  pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,
+		  (void *)pnesfrpl->nes_wqe_pbl.paddr);
 
-	return rc;
+	return pifrpl;
 }
 
-
-/**
- * nes_map_phys_fmr
+/*
+ * nes_free_fast_reg_page_list
  */
-static int nes_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
-		int list_len, u64 iova)
+static void nes_free_fast_reg_page_list(struct ib_fast_reg_page_list *pifrpl)
 {
-	return 0;
+	struct nes_vnic *nesvnic = to_nesvnic(pifrpl->device);
+	struct nes_device *nesdev = nesvnic->nesdev;
+	struct nes_ib_fast_reg_page_list *pnesfrpl;
+
+	pnesfrpl = container_of(pifrpl, struct nes_ib_fast_reg_page_list, ibfrpl);
+	/*
+	 * Free the WQE PBL.
+	 */
+	pci_free_consistent(nesdev->pcidev,
+			    pifrpl->max_page_list_len * sizeof(u64),
+			    pnesfrpl->nes_wqe_pbl.kva,
+			    pnesfrpl->nes_wqe_pbl.paddr);
+	/*
+	 * Free the PBL structure
+	 */
+	kfree(pnesfrpl);
 }
 
-
-/**
- * nes_unmap_frm
- */
-static int nes_unmap_fmr(struct list_head *ibfmr_list)
-{
-	return 0;
-}
-
-
-
 /**
  * nes_query_device
  */
@@ -633,23 +527,23 @@
 	props->max_qp_wr = nesdev->nesadapter->max_qp_wr - 2;
 	props->max_sge = nesdev->nesadapter->max_sge;
 	props->max_cq = nesibdev->max_cq;
-	props->max_cqe = nesdev->nesadapter->max_cqe - 1;
+	props->max_cqe = nesdev->nesadapter->max_cqe;
 	props->max_mr = nesibdev->max_mr;
 	props->max_mw = nesibdev->max_mr;
 	props->max_pd = nesibdev->max_pd;
 	props->max_sge_rd = 1;
 	switch (nesdev->nesadapter->max_irrq_wr) {
 		case 0:
-			props->max_qp_rd_atom = 1;
+			props->max_qp_rd_atom = 2;
 			break;
 		case 1:
-			props->max_qp_rd_atom = 4;
+			props->max_qp_rd_atom = 8;
 			break;
 		case 2:
-			props->max_qp_rd_atom = 16;
+			props->max_qp_rd_atom = 32;
 			break;
 		case 3:
-			props->max_qp_rd_atom = 32;
+			props->max_qp_rd_atom = 64;
 			break;
 		default:
 			props->max_qp_rd_atom = 0;
@@ -1121,6 +1015,7 @@
 		kunmap(nesqp->page);
 		return -ENOMEM;
 	}
+	nesqp->sq_kmapped = 1;
 	nesqp->hwqp.q2_vbase = mem;
 	mem += 256;
 	memset(nesqp->hwqp.q2_vbase, 0, 256);
@@ -1198,7 +1093,10 @@
 		pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);
 		pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase );
 		nesqp->pbl_vbase = NULL;
-		kunmap(nesqp->page);
+		if (nesqp->sq_kmapped) {
+			nesqp->sq_kmapped = 0;
+			kunmap(nesqp->page);
+		}
 	}
 }
 
@@ -1504,8 +1402,6 @@
 			nes_debug(NES_DBG_QP, "QP%u structure located @%p.Size = %u.\n",
 					nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp));
 			spin_lock_init(&nesqp->lock);
-			init_waitqueue_head(&nesqp->state_waitq);
-			init_waitqueue_head(&nesqp->kick_waitq);
 			nes_add_ref(&nesqp->ibqp);
 			break;
 		default:
@@ -1513,6 +1409,8 @@
 			return ERR_PTR(-EINVAL);
 	}
 
+	nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR);
+
 	/* update the QP table */
 	nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
 	nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",
@@ -1607,8 +1505,10 @@
 				nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index;
 			}
 		}
-		if (nesqp->pbl_pbase)
+		if (nesqp->pbl_pbase && nesqp->sq_kmapped) {
+			nesqp->sq_kmapped = 0;
 			kunmap(nesqp->page);
+		}
 	} else {
 		/* Clean any pending completions from the cq(s) */
 		if (nesqp->nesscq)
@@ -1649,6 +1549,9 @@
 	unsigned long flags;
 	int ret;
 
+	if (entries > nesadapter->max_cqe)
+		return ERR_PTR(-EINVAL);
+
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs,
 			nesadapter->max_cq, &cq_num, &nesadapter->next_cq);
 	if (err) {
@@ -2606,9 +2509,6 @@
 			stag = stag_index << 8;
 			stag |= driver_key;
 			stag += (u32)stag_key;
-			if (stag == 0) {
-				stag = 1;
-			}
 
 			iova_start = virt;
 			/* Make the leaf PBL the root if only one PBL */
@@ -3109,7 +3009,6 @@
 								" already done based on hw state.\n",
 								nesqp->hwqp.qp_id);
 						issue_modify_qp = 0;
-						nesqp->in_disconnect = 0;
 					}
 					switch (nesqp->hw_iwarp_state) {
 						case NES_AEQE_IWARP_STATE_CLOSING:
@@ -3122,7 +3021,6 @@
 							break;
 						default:
 							next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
-							nesqp->in_disconnect = 1;
 							nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
 							break;
 					}
@@ -3139,7 +3037,6 @@
 				next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
 				nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
 				issue_modify_qp = 1;
-				nesqp->in_disconnect = 1;
 				break;
 			case IB_QPS_ERR:
 			case IB_QPS_RESET:
@@ -3162,7 +3059,6 @@
 				if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) &&
 						(nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) {
 					next_iwarp_state |= NES_CQP_QP_RESET;
-					nesqp->in_disconnect = 1;
 				} else {
 					nes_debug(NES_DBG_MOD_QP, "QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n",
 							nesqp->hwqp.qp_id, nesqp->hw_tcp_state);
@@ -3373,21 +3269,17 @@
 	struct nes_device *nesdev = nesvnic->nesdev;
 	struct nes_qp *nesqp = to_nesqp(ibqp);
 	struct nes_hw_qp_wqe *wqe;
-	int err;
+	int err = 0;
 	u32 qsize = nesqp->hwqp.sq_size;
 	u32 head;
-	u32 wqe_misc;
-	u32 wqe_count;
+	u32 wqe_misc = 0;
+	u32 wqe_count = 0;
 	u32 counter;
-	u32 total_payload_length;
 
-	err = 0;
-	wqe_misc = 0;
-	wqe_count = 0;
-	total_payload_length = 0;
-
-	if (nesqp->ibqp_state > IB_QPS_RTS)
-		return -EINVAL;
+	if (nesqp->ibqp_state > IB_QPS_RTS) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	spin_lock_irqsave(&nesqp->lock, flags);
 
@@ -3413,94 +3305,208 @@
 		u64temp = (u64)(ib_wr->wr_id);
 		set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,
 					u64temp);
-			switch (ib_wr->opcode) {
-				case IB_WR_SEND:
-					if (ib_wr->send_flags & IB_SEND_SOLICITED) {
-						wqe_misc = NES_IWARP_SQ_OP_SENDSE;
-					} else {
-						wqe_misc = NES_IWARP_SQ_OP_SEND;
-					}
-					if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
-						err = -EINVAL;
-						break;
-					}
-					if (ib_wr->send_flags & IB_SEND_FENCE) {
-						wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
-					}
-					if ((ib_wr->send_flags & IB_SEND_INLINE) &&
-							((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
-							(ib_wr->sg_list[0].length <= 64)) {
-						memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
-							       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
-						set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
-								ib_wr->sg_list[0].length);
-						wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
-					} else {
-						fill_wqe_sg_send(wqe, ib_wr, 1);
-					}
+		switch (ib_wr->opcode) {
+		case IB_WR_SEND:
+		case IB_WR_SEND_WITH_INV:
+			if (IB_WR_SEND == ib_wr->opcode) {
+				if (ib_wr->send_flags & IB_SEND_SOLICITED)
+					wqe_misc = NES_IWARP_SQ_OP_SENDSE;
+				else
+					wqe_misc = NES_IWARP_SQ_OP_SEND;
+			} else {
+				if (ib_wr->send_flags & IB_SEND_SOLICITED)
+					wqe_misc = NES_IWARP_SQ_OP_SENDSEINV;
+				else
+					wqe_misc = NES_IWARP_SQ_OP_SENDINV;
 
-					break;
-				case IB_WR_RDMA_WRITE:
-					wqe_misc = NES_IWARP_SQ_OP_RDMAW;
-					if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
-						nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n",
-								ib_wr->num_sge,
-								nesdev->nesadapter->max_sge);
-						err = -EINVAL;
-						break;
-					}
-					if (ib_wr->send_flags & IB_SEND_FENCE) {
-						wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
-					}
-
-					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
-							ib_wr->wr.rdma.rkey);
-					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
-							ib_wr->wr.rdma.remote_addr);
-
-					if ((ib_wr->send_flags & IB_SEND_INLINE) &&
-							((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
-							(ib_wr->sg_list[0].length <= 64)) {
-						memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
-							       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
-						set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
-								ib_wr->sg_list[0].length);
-						wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
-					} else {
-						fill_wqe_sg_send(wqe, ib_wr, 1);
-					}
-					wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] =
-							wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX];
-					break;
-				case IB_WR_RDMA_READ:
-					/* iWARP only supports 1 sge for RDMA reads */
-					if (ib_wr->num_sge > 1) {
-						nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n",
-								ib_wr->num_sge);
-						err = -EINVAL;
-						break;
-					}
-					wqe_misc = NES_IWARP_SQ_OP_RDMAR;
-					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
-							ib_wr->wr.rdma.remote_addr);
-					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
-							ib_wr->wr.rdma.rkey);
-					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,
-							ib_wr->sg_list->length);
-					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
-							ib_wr->sg_list->addr);
-					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX,
-							ib_wr->sg_list->lkey);
-					break;
-				default:
-					/* error */
-					err = -EINVAL;
-					break;
+				set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,
+						    ib_wr->ex.invalidate_rkey);
 			}
 
-		if (ib_wr->send_flags & IB_SEND_SIGNALED) {
-			wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
+			if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
+				err = -EINVAL;
+				break;
+			}
+
+			if (ib_wr->send_flags & IB_SEND_FENCE)
+				wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
+
+			if ((ib_wr->send_flags & IB_SEND_INLINE) &&
+			    ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
+			     (ib_wr->sg_list[0].length <= 64)) {
+				memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
+				       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
+				set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
+						    ib_wr->sg_list[0].length);
+				wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
+			} else {
+				fill_wqe_sg_send(wqe, ib_wr, 1);
+			}
+
+			break;
+		case IB_WR_RDMA_WRITE:
+			wqe_misc = NES_IWARP_SQ_OP_RDMAW;
+			if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
+				nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n",
+					  ib_wr->num_sge, nesdev->nesadapter->max_sge);
+				err = -EINVAL;
+				break;
+			}
+
+			if (ib_wr->send_flags & IB_SEND_FENCE)
+				wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
+
+			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
+					    ib_wr->wr.rdma.rkey);
+			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
+					    ib_wr->wr.rdma.remote_addr);
+
+			if ((ib_wr->send_flags & IB_SEND_INLINE) &&
+			    ((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
+			     (ib_wr->sg_list[0].length <= 64)) {
+				memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
+				       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
+				set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
+						    ib_wr->sg_list[0].length);
+				wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
+			} else {
+				fill_wqe_sg_send(wqe, ib_wr, 1);
+			}
+
+			wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] =
+				wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX];
+			break;
+		case IB_WR_RDMA_READ:
+		case IB_WR_RDMA_READ_WITH_INV:
+			/* iWARP only supports 1 sge for RDMA reads */
+			if (ib_wr->num_sge > 1) {
+				nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n",
+					  ib_wr->num_sge);
+				err = -EINVAL;
+				break;
+			}
+			if (ib_wr->opcode == IB_WR_RDMA_READ) {
+				wqe_misc = NES_IWARP_SQ_OP_RDMAR;
+			} else {
+				wqe_misc = NES_IWARP_SQ_OP_RDMAR_LOCINV;
+				set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX,
+						    ib_wr->ex.invalidate_rkey);
+			}
+
+			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
+					    ib_wr->wr.rdma.remote_addr);
+			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
+					    ib_wr->wr.rdma.rkey);
+			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,
+					    ib_wr->sg_list->length);
+			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
+					    ib_wr->sg_list->addr);
+			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX,
+					    ib_wr->sg_list->lkey);
+			break;
+		case IB_WR_LOCAL_INV:
+			wqe_misc = NES_IWARP_SQ_OP_LOCINV;
+			set_wqe_32bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX,
+					    ib_wr->ex.invalidate_rkey);
+			break;
+		case IB_WR_FAST_REG_MR:
+		{
+			int i;
+			int flags = ib_wr->wr.fast_reg.access_flags;
+			struct nes_ib_fast_reg_page_list *pnesfrpl =
+				container_of(ib_wr->wr.fast_reg.page_list,
+					     struct nes_ib_fast_reg_page_list,
+					     ibfrpl);
+			u64 *src_page_list = pnesfrpl->ibfrpl.page_list;
+			u64 *dst_page_list = pnesfrpl->nes_wqe_pbl.kva;
+
+			if (ib_wr->wr.fast_reg.page_list_len >
+			    (NES_4K_PBL_CHUNK_SIZE / sizeof(u64))) {
+				nes_debug(NES_DBG_IW_TX, "SQ_FMR: bad page_list_len\n");
+				err = -EINVAL;
+				break;
+			}
+			wqe_misc = NES_IWARP_SQ_OP_FAST_REG;
+			set_wqe_64bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX,
+					    ib_wr->wr.fast_reg.iova_start);
+			set_wqe_32bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
+					    ib_wr->wr.fast_reg.length);
+			set_wqe_32bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
+					    ib_wr->wr.fast_reg.rkey);
+			/* Set page size: */
+			if (ib_wr->wr.fast_reg.page_shift == 12) {
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_4K;
+			} else if (ib_wr->wr.fast_reg.page_shift == 21) {
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_PAGE_SIZE_2M;
+			} else {
+				nes_debug(NES_DBG_IW_TX, "Invalid page shift,"
+					  " ib_wr=%u, max=1\n", ib_wr->num_sge);
+				err = -EINVAL;
+				break;
+			}
+			/* Set access_flags */
+			wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_READ;
+			if (flags & IB_ACCESS_LOCAL_WRITE)
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_LOCAL_WRITE;
+
+			if (flags & IB_ACCESS_REMOTE_WRITE)
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_WRITE;
+
+			if (flags & IB_ACCESS_REMOTE_READ)
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_REMOTE_READ;
+
+			if (flags & IB_ACCESS_MW_BIND)
+				wqe_misc |= NES_IWARP_SQ_FMR_WQE_RIGHTS_ENABLE_WINDOW_BIND;
+
+			/* Fill in PBL info: */
+			if (ib_wr->wr.fast_reg.page_list_len >
+			    pnesfrpl->ibfrpl.max_page_list_len) {
+				nes_debug(NES_DBG_IW_TX, "Invalid page list length,"
+					  " ib_wr=%p, value=%u, max=%u\n",
+					  ib_wr, ib_wr->wr.fast_reg.page_list_len,
+					  pnesfrpl->ibfrpl.max_page_list_len);
+				err = -EINVAL;
+				break;
+			}
+
+			set_wqe_64bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX,
+					    pnesfrpl->nes_wqe_pbl.paddr);
+
+			set_wqe_32bit_value(wqe->wqe_words,
+					    NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX,
+					    ib_wr->wr.fast_reg.page_list_len * 8);
+
+			for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)
+				dst_page_list[i] = cpu_to_le64(src_page_list[i]);
+
+			nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %p, "
+				  "length: %d, rkey: %0x, pgl_paddr: %p, "
+				  "page_list_len: %u, wqe_misc: %x\n",
+				  (void *)ib_wr->wr.fast_reg.iova_start,
+				  ib_wr->wr.fast_reg.length,
+				  ib_wr->wr.fast_reg.rkey,
+				  (void *)pnesfrpl->nes_wqe_pbl.paddr,
+				  ib_wr->wr.fast_reg.page_list_len,
+				  wqe_misc);
+			break;
 		}
+		default:
+			/* error */
+			err = -EINVAL;
+			break;
+		}
+
+		if (err)
+			break;
+
+		if ((ib_wr->send_flags & IB_SEND_SIGNALED) || nesqp->sig_all)
+			wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
+
 		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc);
 
 		ib_wr = ib_wr->next;
@@ -3522,6 +3528,7 @@
 
 	spin_unlock_irqrestore(&nesqp->lock, flags);
 
+out:
 	if (err)
 		*bad_wr = ib_wr;
 	return err;
@@ -3548,8 +3555,10 @@
 	u32 counter;
 	u32 total_payload_length;
 
-	if (nesqp->ibqp_state > IB_QPS_RTS)
-		return -EINVAL;
+	if (nesqp->ibqp_state > IB_QPS_RTS) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	spin_lock_irqsave(&nesqp->lock, flags);
 
@@ -3612,6 +3621,7 @@
 
 	spin_unlock_irqrestore(&nesqp->lock, flags);
 
+out:
 	if (err)
 		*bad_wr = ib_wr;
 	return err;
@@ -3720,6 +3730,12 @@
 						nes_debug(NES_DBG_CQ, "Operation = Send.\n");
 						entry->opcode = IB_WC_SEND;
 						break;
+					case NES_IWARP_SQ_OP_LOCINV:
+						entry->opcode = IB_WR_LOCAL_INV;
+						break;
+					case NES_IWARP_SQ_OP_FAST_REG:
+						entry->opcode = IB_WC_FAST_REG_MR;
+						break;
 				}
 
 				nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1);
@@ -3890,10 +3906,9 @@
 	nesibdev->ibdev.dealloc_mw = nes_dealloc_mw;
 	nesibdev->ibdev.bind_mw = nes_bind_mw;
 
-	nesibdev->ibdev.alloc_fmr = nes_alloc_fmr;
-	nesibdev->ibdev.unmap_fmr = nes_unmap_fmr;
-	nesibdev->ibdev.dealloc_fmr = nes_dealloc_fmr;
-	nesibdev->ibdev.map_phys_fmr = nes_map_phys_fmr;
+	nesibdev->ibdev.alloc_fast_reg_mr = nes_alloc_fast_reg_mr;
+	nesibdev->ibdev.alloc_fast_reg_page_list = nes_alloc_fast_reg_page_list;
+	nesibdev->ibdev.free_fast_reg_page_list = nes_free_fast_reg_page_list;
 
 	nesibdev->ibdev.attach_mcast = nes_multicast_attach;
 	nesibdev->ibdev.detach_mcast = nes_multicast_detach;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index 89822d7..2df9993e 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved.
+ * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -135,19 +135,15 @@
 	struct ib_qp          ibqp;
 	void                  *allocated_buffer;
 	struct iw_cm_id       *cm_id;
-	struct workqueue_struct *wq;
 	struct nes_cq         *nesscq;
 	struct nes_cq         *nesrcq;
 	struct nes_pd         *nespd;
 	void *cm_node; /* handle of the node this QP is associated with */
 	struct ietf_mpa_frame *ietf_frame;
 	dma_addr_t            ietf_frame_pbase;
-	wait_queue_head_t     state_waitq;
 	struct ib_mr          *lsmm_mr;
-	unsigned long         socket;
 	struct nes_hw_qp      hwqp;
 	struct work_struct    work;
-	struct work_struct    ae_work;
 	enum ib_qp_state      ibqp_state;
 	u32                   iwarp_state;
 	u32                   hte_index;
@@ -165,19 +161,20 @@
 	struct page           *page;
 	struct timer_list     terminate_timer;
 	enum ib_event_type    terminate_eventtype;
-	wait_queue_head_t     kick_waitq;
-	u16                   in_disconnect;
+	u16                   active_conn:1;
+	u16                   skip_lsmm:1;
+	u16                   user_mode:1;
+	u16                   hte_added:1;
+	u16                   flush_issued:1;
+	u16                   destroyed:1;
+	u16                   sig_all:1;
+	u16                   rsvd:9;
 	u16                   private_data_len;
 	u16                   term_sq_flush_code;
 	u16                   term_rq_flush_code;
-	u8                    active_conn;
-	u8                    skip_lsmm;
-	u8                    user_mode;
-	u8                    hte_added;
 	u8                    hw_iwarp_state;
-	u8                    flush_issued;
 	u8                    hw_tcp_state;
 	u8                    term_flags;
-	u8                    destroyed;
+	u8                    sq_kmapped;
 };
 #endif			/* NES_VERBS_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2bf5116..df3eb8c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -884,6 +884,7 @@
 
 	neigh->neighbour = neighbour;
 	neigh->dev = dev;
+	memset(&neigh->dgid.raw, 0, sizeof (union ib_gid));
 	*to_ipoib_neigh(neighbour) = neigh;
 	skb_queue_head_init(&neigh->queue);
 	ipoib_cm_set(neigh, NULL);
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index b9453d0..274c883 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -209,6 +209,8 @@
 	mem_copy->copy_buf = NULL;
 }
 
+#define IS_4K_ALIGNED(addr)	((((unsigned long)addr) & ~MASK_4K) == 0)
+
 /**
  * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses
  * and returns the length of resulting physical address array (may be less than
@@ -221,62 +223,52 @@
  * where --few fragments of the same page-- are present in the SG as
  * consecutive elements. Also, it handles one entry SG.
  */
+
 static int iser_sg_to_page_vec(struct iser_data_buf *data,
 			       struct iser_page_vec *page_vec,
 			       struct ib_device *ibdev)
 {
-	struct scatterlist *sgl = (struct scatterlist *)data->buf;
-	struct scatterlist *sg;
-	u64 first_addr, last_addr, page;
-	int end_aligned;
-	unsigned int cur_page = 0;
+	struct scatterlist *sg, *sgl = (struct scatterlist *)data->buf;
+	u64 start_addr, end_addr, page, chunk_start = 0;
 	unsigned long total_sz = 0;
-	int i;
+	unsigned int dma_len;
+	int i, new_chunk, cur_page, last_ent = data->dma_nents - 1;
 
 	/* compute the offset of first element */
 	page_vec->offset = (u64) sgl[0].offset & ~MASK_4K;
 
+	new_chunk = 1;
+	cur_page  = 0;
 	for_each_sg(sgl, sg, data->dma_nents, i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
-
+		start_addr = ib_sg_dma_address(ibdev, sg);
+		if (new_chunk)
+			chunk_start = start_addr;
+		dma_len = ib_sg_dma_len(ibdev, sg);
+		end_addr = start_addr + dma_len;
 		total_sz += dma_len;
 
-		first_addr = ib_sg_dma_address(ibdev, sg);
-		last_addr  = first_addr + dma_len;
-
-		end_aligned   = !(last_addr  & ~MASK_4K);
-
-		/* continue to collect page fragments till aligned or SG ends */
-		while (!end_aligned && (i + 1 < data->dma_nents)) {
-			sg = sg_next(sg);
-			i++;
-			dma_len = ib_sg_dma_len(ibdev, sg);
-			total_sz += dma_len;
-			last_addr = ib_sg_dma_address(ibdev, sg) + dma_len;
-			end_aligned = !(last_addr  & ~MASK_4K);
+		/* collect page fragments until aligned or end of SG list */
+		if (!IS_4K_ALIGNED(end_addr) && i < last_ent) {
+			new_chunk = 0;
+			continue;
 		}
+		new_chunk = 1;
 
-		/* handle the 1st page in the 1st DMA element */
-		if (cur_page == 0) {
-			page = first_addr & MASK_4K;
-			page_vec->pages[cur_page] = page;
-			cur_page++;
+		/* address of the first page in the contiguous chunk;
+		   masking relevant for the very first SG entry,
+		   which might be unaligned */
+		page = chunk_start & MASK_4K;
+		do {
+			page_vec->pages[cur_page++] = page;
 			page += SIZE_4K;
-		} else
-			page = first_addr;
-
-		for (; page < last_addr; page += SIZE_4K) {
-			page_vec->pages[cur_page] = page;
-			cur_page++;
-		}
-
+		} while (page < end_addr);
 	}
+
 	page_vec->data_size = total_sz;
 	iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page);
 	return cur_page;
 }
 
-#define IS_4K_ALIGNED(addr)	((((unsigned long)addr) & ~MASK_4K) == 0)
 
 /**
  * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
@@ -284,42 +276,40 @@
  * the number of entries which are aligned correctly. Supports the case where
  * consecutive SG elements are actually fragments of the same physcial page.
  */
-static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data,
-					      struct ib_device *ibdev)
+static int iser_data_buf_aligned_len(struct iser_data_buf *data,
+				      struct ib_device *ibdev)
 {
-	struct scatterlist *sgl, *sg;
-	u64 end_addr, next_addr;
-	int i, cnt;
-	unsigned int ret_len = 0;
+	struct scatterlist *sgl, *sg, *next_sg = NULL;
+	u64 start_addr, end_addr;
+	int i, ret_len, start_check = 0;
+
+	if (data->dma_nents == 1)
+		return 1;
 
 	sgl = (struct scatterlist *)data->buf;
+	start_addr  = ib_sg_dma_address(ibdev, sgl);
 
-	cnt = 0;
 	for_each_sg(sgl, sg, data->dma_nents, i) {
-		/* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
-		   "offset: %ld sz: %ld\n", i,
-		   (unsigned long)sg_phys(sg),
-		   (unsigned long)sg->offset,
-		   (unsigned long)sg->length); */
-		end_addr = ib_sg_dma_address(ibdev, sg) +
-			   ib_sg_dma_len(ibdev, sg);
-		/* iser_dbg("Checking sg iobuf end address "
-		       "0x%08lX\n", end_addr); */
-		if (i + 1 < data->dma_nents) {
-			next_addr = ib_sg_dma_address(ibdev, sg_next(sg));
-			/* are i, i+1 fragments of the same page? */
-			if (end_addr == next_addr) {
-				cnt++;
-				continue;
-			} else if (!IS_4K_ALIGNED(end_addr)) {
-				ret_len = cnt + 1;
-				break;
-			}
-		}
-		cnt++;
+		if (start_check && !IS_4K_ALIGNED(start_addr))
+			break;
+
+		next_sg = sg_next(sg);
+		if (!next_sg)
+			break;
+
+		end_addr    = start_addr + ib_sg_dma_len(ibdev, sg);
+		start_addr  = ib_sg_dma_address(ibdev, next_sg);
+
+		if (end_addr == start_addr) {
+			start_check = 0;
+			continue;
+		} else
+			start_check = 1;
+
+		if (!IS_4K_ALIGNED(end_addr))
+			break;
 	}
-	if (i == data->dma_nents)
-		ret_len = cnt;	/* loop ended */
+	ret_len = (next_sg) ? i : i+1;
 	iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n",
 		 ret_len, data->dma_nents, data);
 	return ret_len;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5c16001..ab06071 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -296,9 +296,15 @@
  * @value: value of the event
  *
  * This function should be used by drivers implementing various input
- * devices. See also input_inject_event().
+ * devices to report input events. See also input_inject_event().
+ *
+ * NOTE: input_event() may be safely used right after input device was
+ * allocated with input_allocate_device(), even before it is registered
+ * with input_register_device(), but the event will not reach any of the
+ * input handlers. Such early invocation of input_event() may be used
+ * to 'seed' initial state of a switch or initial position of absolute
+ * axis, etc.
  */
-
 void input_event(struct input_dev *dev,
 		 unsigned int type, unsigned int code, int value)
 {
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index 181d30e..e457404 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -22,11 +22,11 @@
 
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/input.h>
 #include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <mach/hardware.h>
-#include <mach/gpio.h>
 #include <mach/ep93xx_keypad.h>
 
 /*
@@ -60,38 +60,37 @@
 #define KEY_REG_KEY1_MASK	(0x0000003f)
 #define KEY_REG_KEY1_SHIFT	(0)
 
-#define keypad_readl(off)	__raw_readl(keypad->mmio_base + (off))
-#define keypad_writel(v, off)	__raw_writel((v), keypad->mmio_base + (off))
-
-#define MAX_MATRIX_KEY_NUM	(MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
+#define EP93XX_MATRIX_SIZE	(EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS)
 
 struct ep93xx_keypad {
 	struct ep93xx_keypad_platform_data *pdata;
-
-	struct clk *clk;
 	struct input_dev *input_dev;
+	struct clk *clk;
+
 	void __iomem *mmio_base;
 
-	int irq;
-	int enabled;
+	unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE];
 
 	int key1;
 	int key2;
 
-	unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
+	int irq;
+
+	bool enabled;
 };
 
 static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
 {
 	struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
 	struct input_dev *input_dev = keypad->input_dev;
+	unsigned int *key;
 	int i;
 
-	for (i = 0; i < pdata->matrix_key_map_size; i++) {
-		unsigned int key = pdata->matrix_key_map[i];
-		int row = (key >> 28) & 0xf;
-		int col = (key >> 24) & 0xf;
-		int code = key & 0xffffff;
+	key = &pdata->matrix_key_map[0];
+	for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
+		int row = KEY_ROW(*key);
+		int col = KEY_COL(*key);
+		int code = KEY_VAL(*key);
 
 		keypad->matrix_keycodes[(row << 3) + col] = code;
 		__set_bit(code, input_dev->keybit);
@@ -102,9 +101,11 @@
 {
 	struct ep93xx_keypad *keypad = dev_id;
 	struct input_dev *input_dev = keypad->input_dev;
-	unsigned int status = keypad_readl(KEY_REG);
+	unsigned int status;
 	int keycode, key1, key2;
 
+	status = __raw_readl(keypad->mmio_base + KEY_REG);
+
 	keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
 	key1 = keypad->matrix_keycodes[keycode];
 
@@ -152,7 +153,10 @@
 	struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
 	unsigned int val = 0;
 
-	clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV);
+	if (pdata->flags & EP93XX_KEYPAD_KDIV)
+		clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4);
+	else
+		clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16);
 
 	if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY)
 		val |= KEY_INIT_DIS3KY;
@@ -167,7 +171,7 @@
 
 	val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK);
 
-	keypad_writel(val, KEY_INIT);
+	__raw_writel(val, keypad->mmio_base + KEY_INIT);
 }
 
 static int ep93xx_keypad_open(struct input_dev *pdev)
@@ -177,7 +181,7 @@
 	if (!keypad->enabled) {
 		ep93xx_keypad_config(keypad);
 		clk_enable(keypad->clk);
-		keypad->enabled = 1;
+		keypad->enabled = true;
 	}
 
 	return 0;
@@ -189,7 +193,7 @@
 
 	if (keypad->enabled) {
 		clk_disable(keypad->clk);
-		keypad->enabled = 0;
+		keypad->enabled = false;
 	}
 }
 
@@ -211,7 +215,7 @@
 
 	if (keypad->enabled) {
 		clk_disable(keypad->clk);
-		keypad->enabled = 0;
+		keypad->enabled = false;
 	}
 
 	mutex_unlock(&input_dev->mutex);
@@ -236,7 +240,7 @@
 		if (!keypad->enabled) {
 			ep93xx_keypad_config(keypad);
 			clk_enable(keypad->clk);
-			keypad->enabled = 1;
+			keypad->enabled = true;
 		}
 	}
 
@@ -252,88 +256,56 @@
 static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
 {
 	struct ep93xx_keypad *keypad;
-	struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data;
 	struct input_dev *input_dev;
 	struct resource *res;
-	int irq, err, i, gpio;
-
-	if (!pdata ||
-	    !pdata->matrix_key_rows ||
-	    pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS ||
-	    !pdata->matrix_key_cols ||
-	    pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) {
-		dev_err(&pdev->dev, "invalid or missing platform data\n");
-		return -EINVAL;
-	}
+	int err;
 
 	keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL);
-	if (!keypad) {
-		dev_err(&pdev->dev, "failed to allocate driver data\n");
+	if (!keypad)
 		return -ENOMEM;
+
+	keypad->pdata = pdev->dev.platform_data;
+	if (!keypad->pdata) {
+		err = -EINVAL;
+		goto failed_free;
 	}
 
-	keypad->pdata = pdata;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(&pdev->dev, "failed to get keypad irq\n");
+	keypad->irq = platform_get_irq(pdev, 0);
+	if (!keypad->irq) {
 		err = -ENXIO;
 		goto failed_free;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(&pdev->dev, "failed to get I/O memory\n");
 		err = -ENXIO;
 		goto failed_free;
 	}
 
 	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (!res) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
 		err = -EBUSY;
 		goto failed_free;
 	}
 
 	keypad->mmio_base = ioremap(res->start, resource_size(res));
 	if (keypad->mmio_base == NULL) {
-		dev_err(&pdev->dev, "failed to remap I/O memory\n");
 		err = -ENXIO;
 		goto failed_free_mem;
 	}
 
-	/* Request the needed GPIO's */
-	gpio = EP93XX_GPIO_LINE_ROW0;
-	for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) {
-		err = gpio_request(gpio, pdev->name);
-		if (err) {
-			dev_err(&pdev->dev, "failed to request gpio-%d\n",
-				gpio);
-			goto failed_free_rows;
-		}
-	}
-
-	gpio = EP93XX_GPIO_LINE_COL0;
-	for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) {
-		err = gpio_request(gpio, pdev->name);
-		if (err) {
-			dev_err(&pdev->dev, "failed to request gpio-%d\n",
-				gpio);
-			goto failed_free_cols;
-		}
-	}
-
-	keypad->clk = clk_get(&pdev->dev, "key_clk");
-	if (IS_ERR(keypad->clk)) {
-		dev_err(&pdev->dev, "failed to get keypad clock\n");
-		err = PTR_ERR(keypad->clk);
+	err = ep93xx_keypad_acquire_gpio(pdev);
+	if (err)
 		goto failed_free_io;
+
+	keypad->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(keypad->clk)) {
+		err = PTR_ERR(keypad->clk);
+		goto failed_free_gpio;
 	}
 
-	/* Create and register the input driver */
 	input_dev = input_allocate_device();
 	if (!input_dev) {
-		dev_err(&pdev->dev, "failed to allocate input device\n");
 		err = -ENOMEM;
 		goto failed_put_clk;
 	}
@@ -358,44 +330,29 @@
 	ep93xx_keypad_build_keycode(keypad);
 	platform_set_drvdata(pdev, keypad);
 
-	err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED,
-				pdev->name, keypad);
-	if (err) {
-		dev_err(&pdev->dev, "failed to request IRQ\n");
+	err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,
+			  IRQF_DISABLED, pdev->name, keypad);
+	if (err)
 		goto failed_free_dev;
-	}
 
-	keypad->irq = irq;
-
-	/* Register the input device */
 	err = input_register_device(input_dev);
-	if (err) {
-		dev_err(&pdev->dev, "failed to register input device\n");
+	if (err)
 		goto failed_free_irq;
-	}
 
 	device_init_wakeup(&pdev->dev, 1);
 
 	return 0;
 
 failed_free_irq:
-	free_irq(irq, pdev);
+	free_irq(keypad->irq, pdev);
 	platform_set_drvdata(pdev, NULL);
 failed_free_dev:
 	input_free_device(input_dev);
 failed_put_clk:
 	clk_put(keypad->clk);
+failed_free_gpio:
+	ep93xx_keypad_release_gpio(pdev);
 failed_free_io:
-	i = keypad->pdata->matrix_key_cols - 1;
-	gpio = EP93XX_GPIO_LINE_COL0 + i;
-failed_free_cols:
-	for ( ; i >= 0; i--, gpio--)
-		gpio_free(gpio);
-	i = keypad->pdata->matrix_key_rows - 1;
-	gpio = EP93XX_GPIO_LINE_ROW0 + i;
-failed_free_rows:
-	for ( ; i >= 0; i--, gpio--)
-		gpio_free(gpio);
 	iounmap(keypad->mmio_base);
 failed_free_mem:
 	release_mem_region(res->start, resource_size(res));
@@ -408,7 +365,6 @@
 {
 	struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
 	struct resource *res;
-	int i, gpio;
 
 	free_irq(keypad->irq, pdev);
 
@@ -420,15 +376,7 @@
 
 	input_unregister_device(keypad->input_dev);
 
-	i = keypad->pdata->matrix_key_cols - 1;
-	gpio = EP93XX_GPIO_LINE_COL0 + i;
-	for ( ; i >= 0; i--, gpio--)
-		gpio_free(gpio);
-
-	i = keypad->pdata->matrix_key_rows - 1;
-	gpio = EP93XX_GPIO_LINE_ROW0 + i;
-	for ( ; i >= 0; i--, gpio--)
-		gpio_free(gpio);
+	ep93xx_keypad_release_gpio(pdev);
 
 	iounmap(keypad->mmio_base);
 
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index a3f492a..f93c2c0 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
  * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
  * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
  *
  * ALPS detection, tap switching and status querying info is taken from
  * tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -28,7 +29,6 @@
 #define dbg(format, arg...) do {} while (0)
 #endif
 
-
 #define ALPS_OLDPROTO		0x01	/* old style input */
 #define ALPS_DUALPOINT		0x02	/* touchpad has trackstick */
 #define ALPS_PASS		0x04	/* device has a pass-through port */
@@ -37,7 +37,8 @@
 #define ALPS_FW_BK_1		0x10	/* front & back buttons present */
 #define ALPS_FW_BK_2		0x20	/* front & back buttons present */
 #define ALPS_FOUR_BUTTONS	0x40	/* 4 direction button present */
-
+#define ALPS_PS2_INTERLEAVED	0x80	/* 3-byte PS/2 packet interleaved with
+					   6-byte ALPS packet */
 
 static const struct alps_model_info alps_model_data[] = {
 	{ { 0x32, 0x02, 0x14 },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
@@ -58,7 +59,9 @@
 	{ { 0x20, 0x02, 0x0e },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
 	{ { 0x22, 0x02, 0x0a },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
 	{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
-	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
+	/* Dell Latitude E5500, E6400, E6500, Precision M4400 */
+	{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,
+		ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
 	{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS },	  /* Dell Vostro 1400 */
 };
 
@@ -69,20 +72,88 @@
  */
 
 /*
- * ALPS abolute Mode - new format
+ * PS/2 packet format
+ *
+ * byte 0:  0    0 YSGN XSGN    1    M    R    L
+ * byte 1: X7   X6   X5   X4   X3   X2   X1   X0
+ * byte 2: Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+ *
+ * Note that the device never signals overflow condition.
+ *
+ * ALPS absolute Mode - new format
  *
  * byte 0:  1    ?    ?    ?    1    ?    ?    ?
  * byte 1:  0   x6   x5   x4   x3   x2   x1   x0
- * byte 2:  0   x10  x9   x8   x7    ?  fin  ges
+ * byte 2:  0  x10   x9   x8   x7    ?  fin  ges
  * byte 3:  0   y9   y8   y7    1    M    R    L
  * byte 4:  0   y6   y5   y4   y3   y2   y1   y0
  * byte 5:  0   z6   z5   z4   z3   z2   z1   z0
  *
+ * Dualpoint device -- interleaved packet format
+ *
+ * byte 0:    1    1    0    0    1    1    1    1
+ * byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ * byte 2:    0  x10   x9   x8   x7    0  fin  ges
+ * byte 3:    0    0 YSGN XSGN    1    1    1    1
+ * byte 4:   X7   X6   X5   X4   X3   X2   X1   X0
+ * byte 5:   Y7   Y6   Y5   Y4   Y3   Y2   Y1   Y0
+ * byte 6:    0   y9   y8   y7    1    m    r    l
+ * byte 7:    0   y6   y5   y4   y3   y2   y1   y0
+ * byte 8:    0   z6   z5   z4   z3   z2   z1   z0
+ *
+ * CAPITALS = stick, miniscules = touchpad
+ *
  * ?'s can have different meanings on different models,
  * such as wheel rotation, extra buttons, stick buttons
  * on a dualpoint, etc.
  */
 
+static bool alps_is_valid_first_byte(const struct alps_model_info *model,
+				     unsigned char data)
+{
+	return (data & model->mask0) == model->byte0;
+}
+
+static void alps_report_buttons(struct psmouse *psmouse,
+				struct input_dev *dev1, struct input_dev *dev2,
+				int left, int right, int middle)
+{
+	struct alps_data *priv = psmouse->private;
+	const struct alps_model_info *model = priv->i;
+
+	if (model->flags & ALPS_PS2_INTERLEAVED) {
+		struct input_dev *dev;
+
+		/*
+		 * If shared button has already been reported on the
+		 * other device (dev2) then this event should be also
+		 * sent through that device.
+		 */
+		dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_LEFT, left);
+
+		dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_RIGHT, right);
+
+		dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1;
+		input_report_key(dev, BTN_MIDDLE, middle);
+
+		/*
+		 * Sync the _other_ device now, we'll do the first
+		 * device later once we report the rest of the events.
+		 */
+		input_sync(dev2);
+	} else {
+		/*
+		 * For devices with non-interleaved packets we know what
+		 * device buttons belong to so we can simply report them.
+		 */
+		input_report_key(dev1, BTN_LEFT, left);
+		input_report_key(dev1, BTN_RIGHT, right);
+		input_report_key(dev1, BTN_MIDDLE, middle);
+	}
+}
+
 static void alps_process_packet(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
@@ -93,18 +164,6 @@
 	int x, y, z, ges, fin, left, right, middle;
 	int back = 0, forward = 0;
 
-	if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
-		input_report_key(dev2, BTN_LEFT,   packet[0] & 1);
-		input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
-		input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
-		input_report_rel(dev2, REL_X,
-			packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
-		input_report_rel(dev2, REL_Y,
-			packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
-		input_sync(dev2);
-		return;
-	}
-
 	if (model->flags & ALPS_OLDPROTO) {
 		left = packet[2] & 0x10;
 		right = packet[2] & 0x08;
@@ -140,18 +199,13 @@
 		input_report_rel(dev2, REL_X,  (x > 383 ? (x - 768) : x));
 		input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
 
-		input_report_key(dev2, BTN_LEFT, left);
-		input_report_key(dev2, BTN_RIGHT, right);
-		input_report_key(dev2, BTN_MIDDLE, middle);
+		alps_report_buttons(psmouse, dev2, dev, left, right, middle);
 
-		input_sync(dev);
 		input_sync(dev2);
 		return;
 	}
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev, BTN_MIDDLE, middle);
+	alps_report_buttons(psmouse, dev, dev2, left, right, middle);
 
 	/* Convert hardware tap to a reasonable Z value */
 	if (ges && !fin)
@@ -202,25 +256,168 @@
 	input_sync(dev);
 }
 
-static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
+static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
+					unsigned char packet[],
+					bool report_buttons)
+{
+	struct alps_data *priv = psmouse->private;
+	struct input_dev *dev2 = priv->dev2;
+
+	if (report_buttons)
+		alps_report_buttons(psmouse, dev2, psmouse->dev,
+				packet[0] & 1, packet[0] & 2, packet[0] & 4);
+
+	input_report_rel(dev2, REL_X,
+		packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
+	input_report_rel(dev2, REL_Y,
+		packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+
+	input_sync(dev2);
+}
+
+static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
 
+	if (psmouse->pktcnt < 6)
+		return PSMOUSE_GOOD_DATA;
+
+	if (psmouse->pktcnt == 6) {
+		/*
+		 * Start a timer to flush the packet if it ends up last
+		 * 6-byte packet in the stream. Timer needs to fire
+		 * psmouse core times out itself. 20 ms should be enough
+		 * to decide if we are getting more data or not.
+		 */
+		mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
+		return PSMOUSE_GOOD_DATA;
+	}
+
+	del_timer(&priv->timer);
+
+	if (psmouse->packet[6] & 0x80) {
+
+		/*
+		 * Highest bit is set - that means we either had
+		 * complete ALPS packet and this is start of the
+		 * next packet or we got garbage.
+		 */
+
+		if (((psmouse->packet[3] |
+		      psmouse->packet[4] |
+		      psmouse->packet[5]) & 0x80) ||
+		    (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) {
+			dbg("refusing packet %x %x %x %x "
+			    "(suspected interleaved ps/2)\n",
+			    psmouse->packet[3], psmouse->packet[4],
+			    psmouse->packet[5], psmouse->packet[6]);
+			return PSMOUSE_BAD_DATA;
+		}
+
+		alps_process_packet(psmouse);
+
+		/* Continue with the next packet */
+		psmouse->packet[0] = psmouse->packet[6];
+		psmouse->pktcnt = 1;
+
+	} else {
+
+		/*
+		 * High bit is 0 - that means that we indeed got a PS/2
+		 * packet in the middle of ALPS packet.
+		 *
+		 * There is also possibility that we got 6-byte ALPS
+		 * packet followed  by 3-byte packet from trackpoint. We
+		 * can not distinguish between these 2 scenarios but
+		 * becase the latter is unlikely to happen in course of
+		 * normal operation (user would need to press all
+		 * buttons on the pad and start moving trackpoint
+		 * without touching the pad surface) we assume former.
+		 * Even if we are wrong the wost thing that would happen
+		 * the cursor would jump but we should not get protocol
+		 * desynchronization.
+		 */
+
+		alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
+					    false);
+
+		/*
+		 * Continue with the standard ALPS protocol handling,
+		 * but make sure we won't process it as an interleaved
+		 * packet again, which may happen if all buttons are
+		 * pressed. To avoid this let's reset the 4th bit which
+		 * is normally 1.
+		 */
+		psmouse->packet[3] = psmouse->packet[6] & 0xf7;
+		psmouse->pktcnt = 4;
+	}
+
+	return PSMOUSE_GOOD_DATA;
+}
+
+static void alps_flush_packet(unsigned long data)
+{
+	struct psmouse *psmouse = (struct psmouse *)data;
+
+	serio_pause_rx(psmouse->ps2dev.serio);
+
+	if (psmouse->pktcnt == 6) {
+
+		/*
+		 * We did not any more data in reasonable amount of time.
+		 * Validate the last 3 bytes and process as a standard
+		 * ALPS packet.
+		 */
+		if ((psmouse->packet[3] |
+		     psmouse->packet[4] |
+		     psmouse->packet[5]) & 0x80) {
+			dbg("refusing packet %x %x %x "
+			    "(suspected interleaved ps/2)\n",
+			    psmouse->packet[3], psmouse->packet[4],
+			    psmouse->packet[5]);
+		} else {
+			alps_process_packet(psmouse);
+		}
+		psmouse->pktcnt = 0;
+	}
+
+	serio_continue_rx(psmouse->ps2dev.serio);
+}
+
+static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
+{
+	struct alps_data *priv = psmouse->private;
+	const struct alps_model_info *model = priv->i;
+
 	if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
 		if (psmouse->pktcnt == 3) {
-			alps_process_packet(psmouse);
+			alps_report_bare_ps2_packet(psmouse, psmouse->packet,
+						    true);
 			return PSMOUSE_FULL_PACKET;
 		}
 		return PSMOUSE_GOOD_DATA;
 	}
 
-	if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
+	/* Check for PS/2 packet stuffed in the middle of ALPS packet. */
+
+	if ((model->flags & ALPS_PS2_INTERLEAVED) &&
+	    psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
+		return alps_handle_interleaved_ps2(psmouse);
+	}
+
+	if (!alps_is_valid_first_byte(model, psmouse->packet[0])) {
+		dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
+		    psmouse->packet[0], model->mask0, model->byte0);
 		return PSMOUSE_BAD_DATA;
+	}
 
 	/* Bytes 2 - 6 should have 0 in the highest bit */
 	if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
-	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
+	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
+		dbg("refusing packet[%i] = %x\n",
+		    psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]);
 		return PSMOUSE_BAD_DATA;
+	}
 
 	if (psmouse->pktcnt == 6) {
 		alps_process_packet(psmouse);
@@ -459,6 +656,7 @@
 	struct alps_data *priv = psmouse->private;
 
 	psmouse_reset(psmouse);
+	del_timer_sync(&priv->timer);
 	input_unregister_device(priv->dev2);
 	kfree(priv);
 }
@@ -476,6 +674,8 @@
 		goto init_fail;
 
 	priv->dev2 = dev2;
+	setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
+
 	psmouse->private = priv;
 
 	model = alps_get_model(psmouse, &version);
@@ -487,6 +687,17 @@
 	if (alps_hw_init(psmouse))
 		goto init_fail;
 
+	/*
+	 * Undo part of setup done for us by psmouse core since touchpad
+	 * is not a relative device.
+	 */
+	__clear_bit(EV_REL, dev1->evbit);
+	__clear_bit(REL_X, dev1->relbit);
+	__clear_bit(REL_Y, dev1->relbit);
+
+	/*
+	 * Now set up our capabilities.
+	 */
 	dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
 	dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
 	dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index bc87936..904ed8b 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -23,6 +23,7 @@
 	char phys[32];			/* Phys */
 	const struct alps_model_info *i;/* Info */
 	int prev_fin;			/* Finger bit from previous packet */
+	struct timer_list timer;
 };
 
 #ifdef CONFIG_MOUSE_PS2_ALPS
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
index f479ea5..320b7ca 100644
--- a/drivers/input/serio/altera_ps2.c
+++ b/drivers/input/serio/altera_ps2.c
@@ -79,11 +79,11 @@
 /*
  * Add one device to this driver.
  */
-static int altera_ps2_probe(struct platform_device *pdev)
+static int __devinit altera_ps2_probe(struct platform_device *pdev)
 {
 	struct ps2if *ps2if;
 	struct serio *serio;
-	int error;
+	int error, irq;
 
 	ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL);
 	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
@@ -108,11 +108,13 @@
 		goto err_free_mem;
 	}
 
-	ps2if->irq  = platform_get_irq(pdev, 0);
-	if (ps2if->irq < 0) {
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
 		error = -ENXIO;
 		goto err_free_mem;
 	}
+	ps2if->irq = irq;
 
 	if (!request_mem_region(ps2if->iomem_res->start,
 				resource_size(ps2if->iomem_res), pdev->name)) {
@@ -155,7 +157,7 @@
 /*
  * Remove one device from this driver.
  */
-static int altera_ps2_remove(struct platform_device *pdev)
+static int __devexit altera_ps2_remove(struct platform_device *pdev)
 {
 	struct ps2if *ps2if = platform_get_drvdata(pdev);
 
@@ -175,9 +177,10 @@
  */
 static struct platform_driver altera_ps2_driver = {
 	.probe		= altera_ps2_probe,
-	.remove		= altera_ps2_remove,
+	.remove		= __devexit_p(altera_ps2_remove),
 	.driver	= {
 		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
 	},
 };
 
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 89b3941..92563a6 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -107,7 +107,7 @@
 	clk_disable(kmi->clk);
 }
 
-static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
 {
 	struct amba_kmi_port *kmi;
 	struct serio *io;
@@ -134,7 +134,7 @@
 	io->port_data	= kmi;
 	io->dev.parent	= &dev->dev;
 
-	kmi->io 	= io;
+	kmi->io		= io;
 	kmi->base	= ioremap(dev->res.start, resource_size(&dev->res));
 	if (!kmi->base) {
 		ret = -ENOMEM;
@@ -162,7 +162,7 @@
 	return ret;
 }
 
-static int amba_kmi_remove(struct amba_device *dev)
+static int __devexit amba_kmi_remove(struct amba_device *dev)
 {
 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
@@ -197,10 +197,11 @@
 static struct amba_driver ambakmi_driver = {
 	.drv		= {
 		.name	= "kmi-pl050",
+		.owner	= THIS_MODULE,
 	},
 	.id_table	= amba_kmi_idtable,
 	.probe		= amba_kmi_probe,
-	.remove		= amba_kmi_remove,
+	.remove		= __devexit_p(amba_kmi_remove),
 	.resume		= amba_kmi_resume,
 };
 
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c
index a6fb7a3..b54452a 100644
--- a/drivers/input/serio/at32psif.c
+++ b/drivers/input/serio/at32psif.c
@@ -137,7 +137,7 @@
 	spin_lock_irqsave(&psif->lock, flags);
 
 	while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--)
-		msleep(10);
+		udelay(50);
 
 	if (timeout >= 0) {
 		psif_writel(psif, THR, val);
@@ -352,6 +352,7 @@
 	.remove		= __exit_p(psif_remove),
 	.driver		= {
 		.name	= "atmel_psif",
+		.owner	= THIS_MODULE,
 	},
 	.suspend	= psif_suspend,
 	.resume		= psif_resume,
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index bd0f92d..06addfa 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org>
  *
  * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
+ *	Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
  *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
  *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
@@ -326,7 +326,7 @@
  * @return: success/error report
  */
 
-static int __init gscps2_probe(struct parisc_device *dev)
+static int __devinit gscps2_probe(struct parisc_device *dev)
 {
 	struct gscps2port *ps2port;
 	struct serio *serio;
@@ -443,7 +443,7 @@
 	.name		= "gsc_ps2",
 	.id_table	= gscps2_device_tbl,
 	.probe		= gscps2_probe,
-	.remove		= gscps2_remove,
+	.remove		= __devexit_p(gscps2_remove),
 };
 
 static int __init gscps2_init(void)
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 7ba9f2b..6cd03eb 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -993,10 +993,8 @@
 
 static int __init hil_mlc_init(void)
 {
-	init_timer(&hil_mlcs_kicker);
-	hil_mlcs_kicker.expires = jiffies + HZ;
-	hil_mlcs_kicker.function = &hil_mlcs_timer;
-	add_timer(&hil_mlcs_kicker);
+	setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0);
+	mod_timer(&hil_mlcs_kicker, jiffies + HZ);
 
 	tasklet_enable(&hil_mlcs_tasklet);
 
@@ -1005,7 +1003,7 @@
 
 static void __exit hil_mlc_exit(void)
 {
-	del_timer(&hil_mlcs_kicker);
+	del_timer_sync(&hil_mlcs_kicker);
 
 	tasklet_disable(&hil_mlcs_tasklet);
 	tasklet_kill(&hil_mlcs_tasklet);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 7fbffe4..64b688d 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -158,6 +158,14 @@
 		},
 	},
 	{
+		/* Gigabyte M1022M netbook */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
+			DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
+			DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
+		},
+	},
+	{
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 1df02d25..d84a36e 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -126,6 +126,8 @@
 static struct platform_device *i8042_platform_device;
 
 static irqreturn_t i8042_interrupt(int irq, void *dev_id);
+static bool (*i8042_platform_filter)(unsigned char data, unsigned char str,
+				     struct serio *serio);
 
 void i8042_lock_chip(void)
 {
@@ -139,6 +141,48 @@
 }
 EXPORT_SYMBOL(i8042_unlock_chip);
 
+int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
+					struct serio *serio))
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&i8042_lock, flags);
+
+	if (i8042_platform_filter) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	i8042_platform_filter = filter;
+
+out:
+	spin_unlock_irqrestore(&i8042_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(i8042_install_filter);
+
+int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
+				       struct serio *port))
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&i8042_lock, flags);
+
+	if (i8042_platform_filter != filter) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	i8042_platform_filter = NULL;
+
+out:
+	spin_unlock_irqrestore(&i8042_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(i8042_remove_filter);
+
 /*
  * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
  * be ready for reading values from it / writing values to it.
@@ -369,6 +413,31 @@
 }
 
 /*
+ * i8042_filter() filters out unwanted bytes from the input data stream.
+ * It is called from i8042_interrupt and thus is running with interrupts
+ * off and i8042_lock held.
+ */
+static bool i8042_filter(unsigned char data, unsigned char str,
+			 struct serio *serio)
+{
+	if (unlikely(i8042_suppress_kbd_ack)) {
+		if ((~str & I8042_STR_AUXDATA) &&
+		    (data == 0xfa || data == 0xfe)) {
+			i8042_suppress_kbd_ack--;
+			dbg("Extra keyboard ACK - filtered out\n");
+			return true;
+		}
+	}
+
+	if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) {
+		dbg("Filtered out by platfrom filter\n");
+		return true;
+	}
+
+	return false;
+}
+
+/*
  * i8042_interrupt() is the most important function in this driver -
  * it handles the interrupts from the i8042, and sends incoming bytes
  * to the upper layers.
@@ -377,13 +446,16 @@
 static irqreturn_t i8042_interrupt(int irq, void *dev_id)
 {
 	struct i8042_port *port;
+	struct serio *serio;
 	unsigned long flags;
 	unsigned char str, data;
 	unsigned int dfl;
 	unsigned int port_no;
+	bool filtered;
 	int ret = 1;
 
 	spin_lock_irqsave(&i8042_lock, flags);
+
 	str = i8042_read_status();
 	if (unlikely(~str & I8042_STR_OBF)) {
 		spin_unlock_irqrestore(&i8042_lock, flags);
@@ -391,8 +463,8 @@
 		ret = 0;
 		goto out;
 	}
+
 	data = i8042_read_data();
-	spin_unlock_irqrestore(&i8042_lock, flags);
 
 	if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
 		static unsigned long last_transmit;
@@ -441,21 +513,19 @@
 	}
 
 	port = &i8042_ports[port_no];
+	serio = port->exists ? port->serio : NULL;
 
 	dbg("%02x <- i8042 (interrupt, %d, %d%s%s)",
 	    data, port_no, irq,
 	    dfl & SERIO_PARITY ? ", bad parity" : "",
 	    dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-	if (unlikely(i8042_suppress_kbd_ack))
-		if (port_no == I8042_KBD_PORT_NO &&
-		    (data == 0xfa || data == 0xfe)) {
-			i8042_suppress_kbd_ack--;
-			goto out;
-		}
+	filtered = i8042_filter(data, str, serio);
 
-	if (likely(port->exists))
-		serio_interrupt(port->serio, data, dfl);
+	spin_unlock_irqrestore(&i8042_lock, flags);
+
+	if (likely(port->exists && !filtered))
+		serio_interrupt(serio, data, dfl);
 
  out:
 	return IRQ_RETVAL(ret);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index f412c69..d55874e 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -180,8 +180,8 @@
 	}
 }
 
-static inline unsigned int
-ps2_test_one(struct ps2if *ps2if, unsigned int mask)
+static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
+					   unsigned int mask)
 {
 	unsigned int val;
 
@@ -197,7 +197,7 @@
  * Test the keyboard interface.  We basically check to make sure that
  * we can drive each line to the keyboard independently of each other.
  */
-static int __init ps2_test(struct ps2if *ps2if)
+static int __devinit ps2_test(struct ps2if *ps2if)
 {
 	unsigned int stat;
 	int ret = 0;
@@ -312,7 +312,7 @@
 /*
  * Remove one device from this driver.
  */
-static int ps2_remove(struct sa1111_dev *dev)
+static int __devexit ps2_remove(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
@@ -335,7 +335,7 @@
 	},
 	.devid		= SA1111_DEVID_PS2,
 	.probe		= ps2_probe,
-	.remove		= ps2_remove,
+	.remove		= __devexit_p(ps2_remove),
 };
 
 static int __init ps2_init(void)
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 9114ae1..16310f3 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom.h
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support
+ *  USB Wacom tablet support
  *
  *  Copyright (c) 2000-2004 Vojtech Pavlik	<vojtech@ucw.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
@@ -69,6 +69,9 @@
  *      v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
  *      v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
  *      v1.51 (pc) - Added support for Intuos4
+ *      v1.52 (pc) - Query Wacom data upon system resume
+ *                 - add defines for features->type
+ *                 - add new devices (0x9F, 0xE2, and 0XE3)
  */
 
 /*
@@ -89,9 +92,9 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.51"
+#define DRIVER_VERSION "v1.52"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_DESC "USB Wacom tablet driver"
 #define DRIVER_LICENSE "GPL"
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -133,6 +136,8 @@
 extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
 extern __u16 wacom_le16_to_cpu(unsigned char *data);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index ea30c98..072f33b 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom_sys.c
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
+ *  USB Wacom tablet support - system specific code
  */
 
 /*
@@ -209,6 +209,7 @@
 	input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) |
 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+		BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
 		BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
 	input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
 }
@@ -256,6 +257,7 @@
 		BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) |
 		BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
+		BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
 		BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) |
 		BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) |
 		BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2);
@@ -269,7 +271,8 @@
 
 void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
 {
-	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2);
+	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
+		BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2);
 }
 
 void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
@@ -277,12 +280,32 @@
 	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER);
 }
 
+void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP ||
+	    wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
+		input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0);
+		input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0);
+		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
+	}
+}
+
+void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+	if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
+		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
+		input_dev->evbit[0] |= BIT_MASK(EV_MSC);
+		input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
+	}
+}
+
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
-			   struct wacom_wac *wacom_wac)
+			   struct wacom_features *features)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct wacom_features *features = wacom_wac->features;
-	char limit = 0, result = 0;
+	char limit = 0;
+	/* result has to be defined as int for some devices */
+	int result = 0;
 	int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0;
 	unsigned char *report;
 
@@ -328,13 +351,24 @@
 			case HID_USAGE_X:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->touch_x_max =
-							features->touch_y_max =
-							wacom_le16_to_cpu(&report[i + 3]);
+						features->device_type = BTN_TOOL_DOUBLETAP;
+						if (features->type == TABLETPC2FG) {
+							/* need to reset back */
+							features->pktlen = WACOM_PKGLEN_TPC2FG;
+							features->device_type = BTN_TOOL_TRIPLETAP;
+						}
 						features->x_max =
+							wacom_le16_to_cpu(&report[i + 3]);
+						features->x_phy =
 							wacom_le16_to_cpu(&report[i + 6]);
-						i += 7;
+						features->unit = report[i + 9];
+						features->unitExpo = report[i + 11];
+						i += 12;
 					} else if (pen) {
+						/* penabled only accepts exact bytes of data */
+						if (features->type == TABLETPC2FG)
+							features->pktlen = WACOM_PKGLEN_PENABLED;
+						features->device_type = BTN_TOOL_PEN;
 						features->x_max =
 							wacom_le16_to_cpu(&report[i + 3]);
 						i += 4;
@@ -350,10 +384,35 @@
 				break;
 
 			case HID_USAGE_Y:
-				if (usage == WCM_DESKTOP)
-					features->y_max =
-						wacom_le16_to_cpu(&report[i + 3]);
-				i += 4;
+				if (usage == WCM_DESKTOP) {
+					if (finger) {
+						features->device_type = BTN_TOOL_DOUBLETAP;
+						if (features->type == TABLETPC2FG) {
+							/* need to reset back */
+							features->pktlen = WACOM_PKGLEN_TPC2FG;
+							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->y_max =
+								wacom_le16_to_cpu(&report[i + 3]);
+							features->y_phy =
+								wacom_le16_to_cpu(&report[i + 6]);
+							i += 7;
+						} else {
+							features->y_max =
+								features->x_max;
+							features->y_phy =
+								wacom_le16_to_cpu(&report[i + 3]);
+							i += 4;
+						}
+					} else if (pen) {
+						/* penabled only accepts exact bytes of data */
+						if (features->type == TABLETPC2FG)
+							features->pktlen = WACOM_PKGLEN_PENABLED;
+						features->device_type = BTN_TOOL_PEN;
+						features->y_max =
+							wacom_le16_to_cpu(&report[i + 3]);
+						i += 4;
+					}
+				}
 				break;
 
 			case HID_USAGE_FINGER:
@@ -376,7 +435,7 @@
 			break;
 
 		case HID_COLLECTION:
-			/* reset UsagePage ans Finger */
+			/* reset UsagePage and Finger */
 			finger = usage = 0;
 			break;
 		}
@@ -388,43 +447,92 @@
 	return result;
 }
 
-static int wacom_query_tablet_data(struct usb_interface *intf)
+static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
 {
 	unsigned char *rep_data;
-	int limit = 0;
-	int error;
+	int limit = 0, report_id = 2;
+	int error = -ENOMEM;
 
 	rep_data = kmalloc(2, GFP_KERNEL);
 	if (!rep_data)
-		return -ENOMEM;
+		return error;
 
-	do {
-		rep_data[0] = 2;
-		rep_data[1] = 2;
-		error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-					2, rep_data, 2);
-		if (error >= 0)
-			error = usb_get_report(intf,
-						WAC_HID_FEATURE_REPORT, 2,
-						rep_data, 2);
-	} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+	/* ask to report tablet data if it is 2FGT or not a Tablet PC */
+	if (features->device_type == BTN_TOOL_TRIPLETAP) {
+		do {
+			rep_data[0] = 3;
+			rep_data[1] = 4;
+			report_id = 3;
+			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+				report_id, rep_data, 2);
+			if (error >= 0)
+				error = usb_get_report(intf,
+					WAC_HID_FEATURE_REPORT, report_id,
+					rep_data, 3);
+		} while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
+	} else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
+		do {
+			rep_data[0] = 2;
+			rep_data[1] = 2;
+			error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+				report_id, rep_data, 2);
+			if (error >= 0)
+				error = usb_get_report(intf,
+					WAC_HID_FEATURE_REPORT, report_id,
+					rep_data, 2);
+		} while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+	}
 
 	kfree(rep_data);
 
 	return error < 0 ? error : 0;
 }
 
+static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
+		struct wacom_features *features)
+{
+	int error = 0;
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	struct hid_descriptor *hid_desc;
+
+	/* default device to penabled */
+	features->device_type = BTN_TOOL_PEN;
+
+	/* only Tablet PCs need to retrieve the info */
+	if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
+		goto out;
+
+	if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
+		if (usb_get_extra_descriptor(&interface->endpoint[0],
+				HID_DEVICET_REPORT, &hid_desc)) {
+			printk("wacom: can not retrieve extra class descriptor\n");
+			error = 1;
+			goto out;
+		}
+	}
+	error = wacom_parse_hid(intf, hid_desc, features);
+	if (error)
+		goto out;
+
+	/* touch device found but size is not defined. use default */
+	if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+		features->x_max = 1023;
+		features->y_max = 1023;
+	}
+
+ out:
+	return error;
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct wacom_features *features;
 	struct input_dev *input_dev;
 	int error = -ENOMEM;
-	struct hid_descriptor *hid_desc;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
 	wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
@@ -432,7 +540,7 @@
 	if (!wacom || !input_dev || !wacom_wac)
 		goto fail1;
 
-	wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
+	wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma);
 	if (!wacom_wac->data)
 		goto fail1;
 
@@ -448,7 +556,7 @@
 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
 	wacom_wac->features = features = get_wacom_feature(id);
-	BUG_ON(features->pktlen > 10);
+	BUG_ON(features->pktlen > WACOM_PKGLEN_MAX);
 
 	input_dev->name = wacom_wac->features->name;
 	wacom->wacom_wac = wacom_wac;
@@ -463,47 +571,24 @@
 
 	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
-	/* Initialize touch_x_max and touch_y_max in case it is not defined */
-	if (wacom_wac->features->type == TABLETPC) {
-		features->touch_x_max = 1023;
-		features->touch_y_max = 1023;
-	} else {
-		features->touch_x_max = 0;
-		features->touch_y_max = 0;
-	}
-
-	/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
-	if (wacom_wac->features->type == TABLETPC) {
-		if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
-			if (usb_get_extra_descriptor(&interface->endpoint[0],
-						     HID_DEVICET_REPORT, &hid_desc)) {
-				printk("wacom: can not retrive extra class descriptor\n");
-				goto fail2;
-			}
-		}
-		error = wacom_parse_hid(intf, hid_desc, wacom_wac);
-		if (error)
-			goto fail2;
-	}
+	/* Retrieve the physical and logical size for OEM devices */
+	error = wacom_retrieve_hid_descriptor(intf, features);
+	if (error)
+		goto fail2;
 
 	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) |
-		BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS);
+	input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH);
+
 	input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
-	if (features->type == TABLETPC) {
-		input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
-		input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0);
-		input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0);
-	}
 	input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
 
 	wacom_init_input_dev(input_dev, wacom_wac);
 
 	usb_fill_int_urb(wacom->irq, dev,
 			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-			 wacom_wac->data, wacom_wac->features->pktlen,
+			 wacom_wac->data, features->pktlen,
 			 wacom_sys_irq, wacom, endpoint->bInterval);
 	wacom->irq->transfer_dma = wacom->data_dma;
 	wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -512,18 +597,14 @@
 	if (error)
 		goto fail3;
 
-	/*
-	 * Ask the tablet to report tablet data if it is not a Tablet PC.
-	 * Note that if query fails it is not a hard failure.
-	 */
-	if (wacom_wac->features->type != TABLETPC)
-		wacom_query_tablet_data(intf);
+	/* Note that if query fails it is not a hard failure */
+	wacom_query_tablet_data(intf, features);
 
 	usb_set_intfdata(intf, wacom);
 	return 0;
 
  fail3:	usb_free_urb(wacom->irq);
- fail2:	usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+ fail2:	usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
  fail1:	input_free_device(input_dev);
 	kfree(wacom);
 	kfree(wacom_wac);
@@ -539,7 +620,7 @@
 	usb_kill_urb(wacom->irq);
 	input_unregister_device(wacom->dev);
 	usb_free_urb(wacom->irq);
-	usb_buffer_free(interface_to_usbdev(intf), 10,
+	usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
 			wacom->wacom_wac->data, wacom->data_dma);
 	kfree(wacom->wacom_wac);
 	kfree(wacom);
@@ -559,12 +640,16 @@
 static int wacom_resume(struct usb_interface *intf)
 {
 	struct wacom *wacom = usb_get_intfdata(intf);
+	struct wacom_features *features = wacom->wacom_wac->features;
 	int rv;
 
 	mutex_lock(&wacom->lock);
-	if (wacom->open)
+	if (wacom->open) {
 		rv = usb_submit_urb(wacom->irq, GFP_NOIO);
-	else
+		/* switch to wacom mode if needed */
+		if (!wacom_retrieve_hid_descriptor(intf, features))
+			wacom_query_tablet_data(intf, features);
+	} else
 		rv = 0;
 	mutex_unlock(&wacom->lock);
 
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index c896d6a..1056f14 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1,7 +1,7 @@
 /*
  * drivers/input/tablet/wacom_wac.c
  *
- *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
+ *  USB Wacom tablet support - Wacom specific code
  *
  */
 
@@ -58,16 +58,15 @@
 	unsigned char *data = wacom->data;
 	int prox, pressure;
 
-	if (data[0] != 2) {
+	if (data[0] != WACOM_REPORT_PENABLED) {
 		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
 		return 0;
 	}
 
 	prox = data[1] & 0x40;
 
-	wacom->id[0] = ERASER_DEVICE_ID;
 	if (prox) {
-
+		wacom->id[0] = ERASER_DEVICE_ID;
 		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
 		if (wacom->features->pressure_max > 255)
 			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
@@ -128,7 +127,7 @@
 {
 	unsigned char *data = wacom->data;
 
-	if (data[0] != 2) {
+	if (data[0] != WACOM_REPORT_PENABLED) {
 		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
 		return 0;
 	}
@@ -155,14 +154,16 @@
 {
 	unsigned char *data = wacom->data;
 	int x, y, rw;
+	static int penData = 0;
 
-	if (data[0] != 2) {
+	if (data[0] != WACOM_REPORT_PENABLED) {
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 		return 0;
 	}
 
 	if (data[1] & 0x80) {
 		/* in prox and not a pad data */
+		penData = 1;
 
 		switch ((data[1] >> 5) & 3) {
 
@@ -232,7 +233,11 @@
 	switch (wacom->features->type) {
 	    case WACOM_G4:
 		if (data[7] & 0xf8) {
-			wacom_input_sync(wcombo); /* sync last event */
+			if (penData) {
+				wacom_input_sync(wcombo); /* sync last event */
+				if (!wacom->id[0])
+					penData = 0;
+			}
 			wacom->id[1] = PAD_DEVICE_ID;
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
@@ -242,10 +247,15 @@
 			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
-			wacom_input_sync(wcombo); /* sync last event */
+			if (penData) {
+				wacom_input_sync(wcombo); /* sync last event */
+				if (!wacom->id[0])
+					penData = 0;
+			}
 			wacom->id[1] = 0;
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
 			wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
+			wacom_report_rel(wcombo, REL_WHEEL, 0);
 			wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
 			wacom_report_abs(wcombo, ABS_MISC, 0);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
@@ -253,7 +263,11 @@
 		break;
 	    case WACOM_MO:
 		if ((data[7] & 0xf8) || (data[8] & 0xff)) {
-			wacom_input_sync(wcombo); /* sync last event */
+			if (penData) {
+				wacom_input_sync(wcombo); /* sync last event */
+				if (!wacom->id[0])
+					penData = 0;
+			}
 			wacom->id[1] = PAD_DEVICE_ID;
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
@@ -264,7 +278,11 @@
 			wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]);
 			wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
 		} else if (wacom->id[1]) {
-			wacom_input_sync(wcombo); /* sync last event */
+			if (penData) {
+				wacom_input_sync(wcombo); /* sync last event */
+				if (!wacom->id[0])
+					penData = 0;
+			}
 			wacom->id[1] = 0;
 			wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
 			wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
@@ -432,7 +450,8 @@
 	unsigned int t;
 	int idx = 0, result;
 
-	if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
+	if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD
+		&& data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) {
 		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
                 return 0;
 	}
@@ -442,7 +461,7 @@
 		idx = data[1] & 0x01;
 
 	/* pad packets. Works as a second tool and is always in prox */
-	if (data[0] == 12) {
+	if (data[0] == WACOM_REPORT_INTUOSPAD) {
 		/* initiate the pad as a device */
 		if (wacom->tool[1] != BTN_TOOL_FINGER)
 			wacom->tool[1] = BTN_TOOL_FINGER;
@@ -608,95 +627,163 @@
 	return 1;
 }
 
+
+static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx)
+{
+	wacom_report_abs(wcombo, ABS_X,
+		(data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8));
+	wacom_report_abs(wcombo, ABS_Y,
+		(data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8));
+	wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+	wacom_report_key(wcombo, wacom->tool[idx], 1);
+	if (idx)
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+	else
+		wacom_report_key(wcombo, BTN_TOUCH, 1);
+}
+
+static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx)
+{
+	wacom_report_abs(wcombo, ABS_X, 0);
+	wacom_report_abs(wcombo, ABS_Y, 0);
+	wacom_report_abs(wcombo, ABS_MISC, 0);
+	wacom_report_key(wcombo, wacom->tool[idx], 0);
+	if (idx)
+		wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+	else
+		wacom_report_key(wcombo, BTN_TOUCH, 0);
+	return;
+}
+
+static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
+{
+	char *data = wacom->data;
+	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
+	static int firstFinger = 0;
+	static int secondFinger = 0;
+
+	wacom->tool[0] = BTN_TOOL_DOUBLETAP;
+	wacom->id[0] = TOUCH_DEVICE_ID;
+	wacom->tool[1] = BTN_TOOL_TRIPLETAP;
+
+	if (urb->actual_length != WACOM_PKGLEN_TPC1FG) {
+		switch (data[0]) {
+			case WACOM_REPORT_TPC1FG:
+				wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+				wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+				wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+				wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
+				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+				wacom_report_key(wcombo, wacom->tool[0], 1);
+				break;
+			case WACOM_REPORT_TPC2FG:
+				/* keep this byte to send proper out-prox event */
+				wacom->id[1] = data[1] & 0x03;
+
+				if (data[1] & 0x01) {
+					wacom_tpc_finger_in(wacom, wcombo, data, 0);
+					firstFinger = 1;
+				} else if (firstFinger) {
+					wacom_tpc_touch_out(wacom, wcombo, 0);
+				}
+
+				if (data[1] & 0x02) {
+					/* sync first finger data */
+					if (firstFinger)
+						wacom_input_sync(wcombo);
+
+					wacom_tpc_finger_in(wacom, wcombo, data, 1);
+					secondFinger = 1;
+				} else if (secondFinger) {
+					/* sync first finger data */
+					if (firstFinger)
+						wacom_input_sync(wcombo);
+
+					wacom_tpc_touch_out(wacom, wcombo, 1);
+					secondFinger = 0;
+				}
+				if (!(data[1] & 0x01))
+					firstFinger = 0;
+				break;
+		}
+	} else {
+		wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+		wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+		wacom_report_key(wcombo, BTN_TOUCH, 1);
+		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
+		wacom_report_key(wcombo, wacom->tool[0], 1);
+	}
+	return;
+}
+
 static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
 {
 	char *data = wacom->data;
-	int prox = 0, pressure;
+	int prox = 0, pressure, idx = -1;
 	static int stylusInProx, touchInProx = 1, touchOut;
 	struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
 
 	dbg("wacom_tpc_irq: received report #%d", data[0]);
 
-	if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */
-		if (urb->actual_length == 5) {  /* with touch */
-			prox = data[0] & 0x03;
+	if (urb->actual_length == WACOM_PKGLEN_TPC1FG || /* single touch */
+	    data[0] == WACOM_REPORT_TPC1FG ||		 /* single touch */
+	    data[0] == WACOM_REPORT_TPC2FG) {		 /* 2FG touch */
+		if (urb->actual_length == WACOM_PKGLEN_TPC1FG) {  /* with touch */
+			prox = data[0] & 0x01;
 		} else {  /* with capacity */
-			prox = data[1] & 0x03;
+			if (data[0] == WACOM_REPORT_TPC1FG)
+				/* single touch */
+				prox = data[1] & 0x01;
+			else
+				/* 2FG touch data */
+				prox = data[1] & 0x03;
 		}
 
 		if (!stylusInProx) { /* stylus not in prox */
 			if (prox) {
 				if (touchInProx) {
-					wacom->tool[1] = BTN_TOOL_DOUBLETAP;
-					wacom->id[0] = TOUCH_DEVICE_ID;
-					if (urb->actual_length != 5) {
-						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
-						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
-						wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
-						wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6]));
-					} else {
-						wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
-						wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
-						wacom_report_key(wcombo, BTN_TOUCH, 1);
-					}
-					wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-					wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
+					wacom_tpc_touch_in(wacom, wcombo);
 					touchOut = 1;
 					return 1;
 				}
 			} else {
-				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-				wacom_report_key(wcombo, wacom->tool[1], prox & 0x01);
-				wacom_report_key(wcombo, BTN_TOUCH, 0);
+				/* 2FGT out-prox */
+				if (data[0] == WACOM_REPORT_TPC2FG) {
+					idx = (wacom->id[1] & 0x01) - 1;
+					if (idx == 0) {
+						wacom_tpc_touch_out(wacom, wcombo, idx);
+						/* sync first finger event */
+						if (wacom->id[1] & 0x02)
+							wacom_input_sync(wcombo);
+					}
+					idx = (wacom->id[1] & 0x02) - 1;
+					if (idx == 1)
+						wacom_tpc_touch_out(wacom, wcombo, idx);
+				} else /* one finger touch */
+					wacom_tpc_touch_out(wacom, wcombo, 0);
 				touchOut = 0;
 				touchInProx = 1;
 				return 1;
 			}
 		} else if (touchOut || !prox) { /* force touch out-prox */
-			wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID);
-			wacom_report_key(wcombo, wacom->tool[1], 0);
-			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom_tpc_touch_out(wacom, wcombo, 0);
 			touchOut = 0;
 			touchInProx = 1;
 			return 1;
 		}
-	} else if (data[0] == 2) { /* Penabled */
+	} else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
 		prox = data[1] & 0x20;
 
 		touchInProx = 0;
 
-		wacom->id[0] = ERASER_DEVICE_ID;
-
-		/*
-		 * if going from out of proximity into proximity select between the eraser
-		 * and the pen based on the state of the stylus2 button, choose eraser if
-		 * pressed else choose pen. if not a proximity change from out to in, send
-		 * an out of proximity for previous tool then a in for new tool.
-		 */
 		if (prox) { /* in prox */
-			if (!wacom->tool[0]) {
+			if (!wacom->id[0]) {
 				/* Going into proximity select tool */
-				wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-				if (wacom->tool[1] == BTN_TOOL_PEN)
+				wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+				if (wacom->tool[0] == BTN_TOOL_PEN)
 					wacom->id[0] = STYLUS_DEVICE_ID;
-			} else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) {
-				/*
-				 * was entered with stylus2 pressed
-				 * report out proximity for previous tool
-				*/
-				wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
-				wacom_report_key(wcombo, wacom->tool[1], 0);
-				wacom_input_sync(wcombo);
-
-				/* set new tool */
-				wacom->tool[1] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
-				return 0;
-			}
-			if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-				/* Unknown tool selected default to pen tool */
-				wacom->tool[1] = BTN_TOOL_PEN;
-				wacom->id[0] = STYLUS_DEVICE_ID;
+				else
+					wacom->id[0] = ERASER_DEVICE_ID;
 			}
 			wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
 			wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
@@ -706,17 +793,21 @@
 			if (pressure < 0)
 				pressure = wacom->features->pressure_max + pressure + 1;
 			wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
-			wacom_report_key(wcombo, BTN_TOUCH, pressure);
+			wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
 		} else {
+			wacom_report_abs(wcombo, ABS_X, 0);
+			wacom_report_abs(wcombo, ABS_Y, 0);
 			wacom_report_abs(wcombo, ABS_PRESSURE, 0);
 			wacom_report_key(wcombo, BTN_STYLUS, 0);
 			wacom_report_key(wcombo, BTN_STYLUS2, 0);
 			wacom_report_key(wcombo, BTN_TOUCH, 0);
+			wacom->id[0] = 0;
+			/* pen is out so touch can be enabled now */
+			touchInProx = 1;
 		}
-		wacom_report_key(wcombo, wacom->tool[1], prox);
+		wacom_report_key(wcombo, wacom->tool[0], prox);
 		wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
 		stylusInProx = prox;
-		wacom->tool[0] = prox;
 		return 1;
 	}
 	return 0;
@@ -751,6 +842,7 @@
 			return wacom_intuos_irq(wacom_wac, wcombo);
 
 		case TABLETPC:
+		case TABLETPC2FG:
 			return wacom_tpc_irq(wacom_wac, wcombo);
 
 		default:
@@ -791,9 +883,17 @@
 			input_dev_i4s(input_dev, wacom_wac);
 			input_dev_i(input_dev, wacom_wac);
 			break;
+		case TABLETPC2FG:
+			input_dev_tpc2fg(input_dev, wacom_wac);
+			/* fall through */
+		case TABLETPC:
+			input_dev_tpc(input_dev, wacom_wac);
+			if (wacom_wac->features->device_type != BTN_TOOL_PEN)
+				break;  /* no need to process stylus stuff */
+
+			/* fall through */
 		case PL:
 		case PTU:
-		case TABLETPC:
 			input_dev_pl(input_dev, wacom_wac);
 			/* fall through */
 		case PENPARTNER:
@@ -804,66 +904,69 @@
 }
 
 static struct wacom_features wacom_features[] = {
-	{ "Wacom Penpartner",    7,   5040,  3780,  255,  0, PENPARTNER },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire3",     8,  10208,  7424,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 63, GRAPHIRE },
-	{ "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 63, WACOM_G4 },
-	{ "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 63, WACOM_G4 },
-	{ "Wacom BambooFun 4x5", 9,  14760,  9225,  511, 63, WACOM_MO },
-	{ "Wacom BambooFun 6x8", 9,  21648, 13530,  511, 63, WACOM_MO },
-	{ "Wacom Bamboo1 Medium",8,  16704, 12064,  511, 63, GRAPHIRE },
-	{ "Wacom Volito",        8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom PenStation2",   8,   3250,  2320,  255, 63, GRAPHIRE },
-	{ "Wacom Volito2 4x5",   8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom Volito2 2x3",   8,   3248,  2320,  511, 63, GRAPHIRE },
-	{ "Wacom PenPartner2",   8,   3250,  2320,  511, 63, GRAPHIRE },
-	{ "Wacom Bamboo",        9,  14760,  9225,  511, 63, WACOM_MO },
-	{ "Wacom Bamboo1",       8,   5104,  3712,  511, 63, GRAPHIRE },
-	{ "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 31, INTUOS },
-	{ "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 31, INTUOS },
-	{ "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 31, INTUOS },
-	{ "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 31, INTUOS },
-	{ "Wacom PL400",         8,   5408,  4056,  255,  0, PL },
-	{ "Wacom PL500",         8,   6144,  4608,  255,  0, PL },
-	{ "Wacom PL600",         8,   6126,  4604,  255,  0, PL },
-	{ "Wacom PL600SX",       8,   6260,  5016,  255,  0, PL },
-	{ "Wacom PL550",         8,   6144,  4608,  511,  0, PL },
-	{ "Wacom PL800",         8,   7220,  5780,  511,  0, PL },
-	{ "Wacom PL700",         8,   6758,  5406,  511,  0, PL },
-	{ "Wacom PL510",         8,   6282,  4762,  511,  0, PL },
-	{ "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
-	{ "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
-	{ "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
-	{ "Wacom DTF720a",       8,   6858,  5506,  511,  0, PL },
-	{ "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
-	{ "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS },
-	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 63, INTUOS3S },
-	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
-	{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
-	{ "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 63, INTUOS3 },
-	{ "Wacom Intuos3 4x6",   10, 31496, 19685, 1023, 63, INTUOS3S },
-	{ "Wacom Intuos4 4x6",   10, 31496, 19685, 2047, 63, INTUOS4S },
-	{ "Wacom Intuos4 6x9",   10, 44704, 27940, 2047, 63, INTUOS4 },
-	{ "Wacom Intuos4 8x13",  10, 65024, 40640, 2047, 63, INTUOS4L },
-	{ "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L },
-	{ "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 63, CINTIQ },
-	{ "Wacom Cintiq 20WSX",  10, 86680, 54180, 1023, 63, WACOM_BEE },
-	{ "Wacom Cintiq 12WX",   10, 53020, 33440, 1023, 63, WACOM_BEE },
-	{ "Wacom DTU1931",        8, 37832, 30305,  511,  0, PL },
-	{ "Wacom ISDv4 90",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom ISDv4 93",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom ISDv4 9A",       8, 26202, 16325,  255,  0, TABLETPC },
-	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,  0, PENPARTNER },
+	{ "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
+	{ "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, WACOM_G4 },
+	{ "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, WACOM_G4 },
+	{ "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
+	{ "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511, 63, WACOM_MO },
+	{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE },
+	{ "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255, 63, GRAPHIRE },
+	{ "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511, 63, GRAPHIRE },
+	{ "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511, 63, GRAPHIRE },
+	{ "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO },
+	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE },
+	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
+	{ "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,  0, PL },
+	{ "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,  0, PL },
+	{ "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,  0, PL },
+	{ "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,  0, PL },
+	{ "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,  0, PL },
+	{ "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,  0, PL },
+	{ "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,  0, PL },
+	{ "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,  0, PL },
+	{ "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL },
+	{ "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
+	{ "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL },
+	{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,  0, PTU },
+	{ "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS },
+	{ "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023, 63, INTUOS3L },
+	{ "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023, 63, INTUOS3 },
+	{ "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023, 63, INTUOS3S },
+	{ "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047, 63, INTUOS4S },
+	{ "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047, 63, INTUOS4 },
+	{ "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047, 63, INTUOS4L },
+	{ "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047, 63, INTUOS4L },
+	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023, 63, CINTIQ },
+	{ "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023, 63, WACOM_BEE },
+	{ "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023, 63, WACOM_BEE },
+	{ "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,  0, PL },
+	{ "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 9F",       WACOM_PKGLEN_PENABLED,  26202, 16325,  255,  0, TABLETPC },
+	{ "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
+	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG },
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS },
 	{ }
 };
 
@@ -927,6 +1030,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 	{ }
 };
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index c10235a..ee01e19 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -9,12 +9,33 @@
 #ifndef WACOM_WAC_H
 #define WACOM_WAC_H
 
+/* maximum packet length for USB devices */
+#define WACOM_PKGLEN_MAX	32
+
+/* packet length for individual models */
+#define WACOM_PKGLEN_PENPRTN	 7
+#define WACOM_PKGLEN_GRAPHIRE	 8
+#define WACOM_PKGLEN_BBFUN 	 9
+#define WACOM_PKGLEN_INTUOS 	10
+#define WACOM_PKGLEN_PENABLED	 8
+#define WACOM_PKGLEN_TPC1FG	 5
+#define WACOM_PKGLEN_TPC2FG 	14
+
+/* device IDs */
 #define STYLUS_DEVICE_ID	0x02
 #define TOUCH_DEVICE_ID		0x03
 #define CURSOR_DEVICE_ID	0x06
 #define ERASER_DEVICE_ID	0x0A
 #define PAD_DEVICE_ID		0x0F
 
+/* wacom data packet report IDs */
+#define WACOM_REPORT_PENABLED		2
+#define WACOM_REPORT_INTUOSREAD		5
+#define WACOM_REPORT_INTUOSWRITE	6
+#define WACOM_REPORT_INTUOSPAD		12
+#define WACOM_REPORT_TPC1FG		6
+#define WACOM_REPORT_TPC2FG		13
+
 enum {
 	PENPARTNER = 0,
 	GRAPHIRE,
@@ -32,6 +53,7 @@
 	WACOM_BEE,
 	WACOM_MO,
 	TABLETPC,
+	TABLETPC2FG,
 	MAX_TYPE
 };
 
@@ -43,8 +65,11 @@
 	int pressure_max;
 	int distance_max;
 	int type;
-	int touch_x_max;
-	int touch_y_max;
+	int device_type;
+	int x_phy;
+	int y_phy;
+	unsigned char unit;
+	unsigned char unitExpo;
 };
 
 struct wacom_wac {
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 32fc8ba..dfafc76 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -450,6 +450,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbtouchscreen.
 
+config TOUCHSCREEN_MC13783
+	tristate "Freescale MC13783 touchscreen input driver"
+	depends on MFD_MC13783
+	help
+	  Say Y here if you have an Freescale MC13783 PMIC on your
+	  board and want to use its touchscreen
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mc13783_ts.
+
 config TOUCHSCREEN_USB_EGALAX
 	default y
 	bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f1f59c9..d61a3b4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
+obj-$(CONFIG_TOUCHSCREEN_MC13783)	+= mc13783_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MCS5000)	+= mcs5000_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
new file mode 100644
index 0000000..be115b3
--- /dev/null
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -0,0 +1,258 @@
+/*
+ * Driver for the Freescale Semiconductor MC13783 touchscreen.
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de/
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#define MC13783_TS_NAME	"mc13783-ts"
+
+#define DEFAULT_SAMPLE_TOLERANCE 300
+
+static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE;
+module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_tolerance,
+		"If the minimal and maximal value read out for one axis (out "
+		"of three) differ by this value (default: "
+		__stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading "
+		"is supposed to be wrong and is discarded.  Set to 0 to "
+		"disable this check.");
+
+struct mc13783_ts_priv {
+	struct input_dev *idev;
+	struct mc13783 *mc13783;
+	struct delayed_work work;
+	struct workqueue_struct *workq;
+	unsigned int sample[4];
+};
+
+static irqreturn_t mc13783_ts_handler(int irq, void *data)
+{
+	struct mc13783_ts_priv *priv = data;
+
+	mc13783_ackirq(priv->mc13783, irq);
+
+	/*
+	 * Kick off reading coordinates. Note that if work happens already
+	 * be queued for future execution (it rearms itself) it will not
+	 * be rescheduled for immediate execution here. However the rearm
+	 * delay is HZ / 50 which is acceptable.
+	 */
+	queue_delayed_work(priv->workq, &priv->work, 0);
+
+	return IRQ_HANDLED;
+}
+
+#define sort3(a0, a1, a2) ({						\
+		if (a0 > a1)						\
+			swap(a0, a1);					\
+		if (a1 > a2)						\
+			swap(a1, a2);					\
+		if (a0 > a1)						\
+			swap(a0, a1);					\
+		})
+
+static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv)
+{
+	struct input_dev *idev = priv->idev;
+	int x0, x1, x2, y0, y1, y2;
+	int cr0, cr1;
+
+	/*
+	 * the values are 10-bit wide only, but the two least significant
+	 * bits are for future 12 bit use and reading yields 0
+	 */
+	x0 = priv->sample[0] & 0xfff;
+	x1 = priv->sample[1] & 0xfff;
+	x2 = priv->sample[2] & 0xfff;
+	y0 = priv->sample[3] & 0xfff;
+	y1 = (priv->sample[0] >> 12) & 0xfff;
+	y2 = (priv->sample[1] >> 12) & 0xfff;
+	cr0 = (priv->sample[2] >> 12) & 0xfff;
+	cr1 = (priv->sample[3] >> 12) & 0xfff;
+
+	dev_dbg(&idev->dev,
+		"x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n",
+		x0, x1, x2, y0, y1, y2, cr0, cr1);
+
+	sort3(x0, x1, x2);
+	sort3(y0, y1, y2);
+
+	cr0 = (cr0 + cr1) / 2;
+
+	if (!cr0 || !sample_tolerance ||
+			(x2 - x0 < sample_tolerance &&
+			 y2 - y0 < sample_tolerance)) {
+		/* report the median coordinate and average pressure */
+		if (cr0) {
+			input_report_abs(idev, ABS_X, x1);
+			input_report_abs(idev, ABS_Y, y1);
+
+			dev_dbg(&idev->dev, "report (%d, %d, %d)\n",
+					x1, y1, 0x1000 - cr0);
+			queue_delayed_work(priv->workq, &priv->work, HZ / 50);
+		} else
+			dev_dbg(&idev->dev, "report release\n");
+
+		input_report_abs(idev, ABS_PRESSURE,
+				cr0 ? 0x1000 - cr0 : cr0);
+		input_report_key(idev, BTN_TOUCH, cr0);
+		input_sync(idev);
+	} else
+		dev_dbg(&idev->dev, "discard event\n");
+}
+
+static void mc13783_ts_work(struct work_struct *work)
+{
+	struct mc13783_ts_priv *priv =
+		container_of(work, struct mc13783_ts_priv, work.work);
+	unsigned int mode = MC13783_ADC_MODE_TS;
+	unsigned int channel = 12;
+
+	if (mc13783_adc_do_conversion(priv->mc13783,
+				mode, channel, priv->sample) == 0)
+		mc13783_ts_report_sample(priv);
+}
+
+static int mc13783_ts_open(struct input_dev *dev)
+{
+	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+	int ret;
+
+	mc13783_lock(priv->mc13783);
+
+	mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
+
+	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+		mc13783_ts_handler, MC13783_TS_NAME, priv);
+	if (ret)
+		goto out;
+
+	ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+			MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+	if (ret)
+		mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+out:
+	mc13783_unlock(priv->mc13783);
+	return ret;
+}
+
+static void mc13783_ts_close(struct input_dev *dev)
+{
+	struct mc13783_ts_priv *priv = input_get_drvdata(dev);
+
+	mc13783_lock(priv->mc13783);
+	mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
+			MC13783_ADC0_TSMOD_MASK, 0);
+	mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+	mc13783_unlock(priv->mc13783);
+
+	cancel_delayed_work_sync(&priv->work);
+}
+
+static int __init mc13783_ts_probe(struct platform_device *pdev)
+{
+	struct mc13783_ts_priv *priv;
+	struct input_dev *idev;
+	int ret = -ENOMEM;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	idev = input_allocate_device();
+	if (!priv || !idev)
+		goto err_free_mem;
+
+	INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
+	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	priv->idev = idev;
+
+	/*
+	 * We need separate workqueue because mc13783_adc_do_conversion
+	 * uses keventd and thus would deadlock.
+	 */
+	priv->workq = create_singlethread_workqueue("mc13783_ts");
+	if (!priv->workq)
+		goto err_free_mem;
+
+	idev->name = MC13783_TS_NAME;
+	idev->dev.parent = &pdev->dev;
+
+	idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0);
+	input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0);
+	input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0);
+
+	idev->open = mc13783_ts_open;
+	idev->close = mc13783_ts_close;
+
+	input_set_drvdata(idev, priv);
+
+	ret = input_register_device(priv->idev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"register input device failed with %d\n", ret);
+		goto err_destroy_wq;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	return 0;
+
+err_destroy_wq:
+	destroy_workqueue(priv->workq);
+err_free_mem:
+	input_free_device(idev);
+	kfree(priv);
+	return ret;
+}
+
+static int __devexit mc13783_ts_remove(struct platform_device *pdev)
+{
+	struct mc13783_ts_priv *priv = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	destroy_workqueue(priv->workq);
+	input_unregister_device(priv->idev);
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver mc13783_ts_driver = {
+	.remove		= __devexit_p(mc13783_ts_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= MC13783_TS_NAME,
+	},
+};
+
+static int __init mc13783_ts_init(void)
+{
+	return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe);
+}
+module_init(mc13783_ts_init);
+
+static void __exit mc13783_ts_exit(void)
+{
+	platform_driver_unregister(&mc13783_ts_driver);
+}
+module_exit(mc13783_ts_exit);
+
+MODULE_DESCRIPTION("MC13783 input touchscreen driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MC13783_TS_NAME);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e4f599f..8a0e1ec 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -229,6 +229,12 @@
 	help
 	  This option enables support for pwm driven LEDs
 
+config LEDS_REGULATOR
+	tristate "REGULATOR driven LED support"
+	depends on LEDS_CLASS && REGULATOR
+	help
+	  This option enables support for regulator driven LEDs.
+
 config LEDS_BD2802
 	tristate "LED driver for BD2802 RGB LED"
 	depends on LEDS_CLASS && I2C
@@ -236,6 +242,33 @@
 	  This option enables support for BD2802GU RGB LED driver chips
 	  accessed via the I2C bus.
 
+config LEDS_INTEL_SS4200
+	tristate "LED driver for Intel NAS SS4200 series"
+	depends on LEDS_CLASS && PCI && DMI
+	help
+	  This option enables support for the Intel SS4200 series of
+	  Network Attached Storage servers.  You may control the hard
+	  drive or power LEDs on the front panel.  Using this driver
+	  can stop the front LED from blinking after startup.
+
+config LEDS_LT3593
+	tristate "LED driver for LT3593 controllers"
+	depends on LEDS_CLASS && GENERIC_GPIO
+	help
+	  This option enables support for LEDs driven by a Linear Technology
+	  LT3593 controller. This controller uses a special one-wire pulse
+	  coding protocol to set the brightness.
+
+config LEDS_ADP5520
+	tristate "LED Support for ADP5520/ADP5501 PMIC"
+	depends on LEDS_CLASS && PMIC_ADP5520
+	help
+	  This option enables support for on-chip LED drivers found
+	  on Analog Devices ADP5520/ADP5501 PMICs.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called leds-adp5520.
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 46d7270..9e63869 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -29,6 +29,10 @@
 obj-$(CONFIG_LEDS_WM831X_STATUS)	+= leds-wm831x-status.o
 obj-$(CONFIG_LEDS_WM8350)		+= leds-wm8350.o
 obj-$(CONFIG_LEDS_PWM)			+= leds-pwm.o
+obj-$(CONFIG_LEDS_REGULATOR)		+= leds-regulator.o
+obj-$(CONFIG_LEDS_INTEL_SS4200)		+= leds-ss4200.o
+obj-$(CONFIG_LEDS_LT3593)		+= leds-lt3593.o
+obj-$(CONFIG_LEDS_ADP5520)		+= leds-adp5520.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
new file mode 100644
index 0000000..a8f3159
--- /dev/null
+++ b/drivers/leds/leds-adp5520.c
@@ -0,0 +1,230 @@
+/*
+ * LEDs driver for Analog Devices ADP5520/ADP5501 MFD PMICs
+ *
+ * Copyright 2009 Analog Devices Inc.
+ *
+ * Loosely derived from leds-da903x:
+ * Copyright (C) 2008 Compulab, Ltd.
+ * 	Mike Rapoport <mike@compulab.co.il>
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * 	Eric Miao <eric.miao@marvell.com>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/adp5520.h>
+
+struct adp5520_led {
+	struct led_classdev	cdev;
+	struct work_struct	work;
+	struct device		*master;
+	enum led_brightness	new_brightness;
+	int			id;
+	int			flags;
+};
+
+static void adp5520_led_work(struct work_struct *work)
+{
+	struct adp5520_led *led = container_of(work, struct adp5520_led, work);
+	adp5520_write(led->master, ADP5520_LED1_CURRENT + led->id - 1,
+			 led->new_brightness >> 2);
+}
+
+static void adp5520_led_set(struct led_classdev *led_cdev,
+			   enum led_brightness value)
+{
+	struct adp5520_led *led;
+
+	led = container_of(led_cdev, struct adp5520_led, cdev);
+	led->new_brightness = value;
+	schedule_work(&led->work);
+}
+
+static int adp5520_led_setup(struct adp5520_led *led)
+{
+	struct device *dev = led->master;
+	int flags = led->flags;
+	int ret = 0;
+
+	switch (led->id) {
+	case FLAG_ID_ADP5520_LED1_ADP5501_LED0:
+		ret |= adp5520_set_bits(dev, ADP5520_LED_TIME,
+					(flags >> ADP5520_FLAG_OFFT_SHIFT) &
+					ADP5520_FLAG_OFFT_MASK);
+		ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+					ADP5520_LED1_EN);
+		break;
+	case FLAG_ID_ADP5520_LED2_ADP5501_LED1:
+		ret |= adp5520_set_bits(dev,  ADP5520_LED_TIME,
+					((flags >> ADP5520_FLAG_OFFT_SHIFT) &
+					ADP5520_FLAG_OFFT_MASK) << 2);
+		ret |= adp5520_clr_bits(dev, ADP5520_LED_CONTROL,
+					 ADP5520_R3_MODE);
+		ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+					ADP5520_LED2_EN);
+		break;
+	case FLAG_ID_ADP5520_LED3_ADP5501_LED2:
+		ret |= adp5520_set_bits(dev,  ADP5520_LED_TIME,
+					((flags >> ADP5520_FLAG_OFFT_SHIFT) &
+					ADP5520_FLAG_OFFT_MASK) << 4);
+		ret |= adp5520_clr_bits(dev, ADP5520_LED_CONTROL,
+					ADP5520_C3_MODE);
+		ret |= adp5520_set_bits(dev, ADP5520_LED_CONTROL,
+					ADP5520_LED3_EN);
+		break;
+	}
+
+	return ret;
+}
+
+static int __devinit adp5520_led_prepare(struct platform_device *pdev)
+{
+	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = pdev->dev.parent;
+	int ret = 0;
+
+	ret |= adp5520_write(dev, ADP5520_LED1_CURRENT, 0);
+	ret |= adp5520_write(dev, ADP5520_LED2_CURRENT, 0);
+	ret |= adp5520_write(dev, ADP5520_LED3_CURRENT, 0);
+	ret |= adp5520_write(dev, ADP5520_LED_TIME, pdata->led_on_time << 6);
+	ret |= adp5520_write(dev, ADP5520_LED_FADE, FADE_VAL(pdata->fade_in,
+		 pdata->fade_out));
+
+	return ret;
+}
+
+static int __devinit adp5520_led_probe(struct platform_device *pdev)
+{
+	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_led *led, *led_dat;
+	struct led_info *cur_led;
+	int ret, i;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "missing platform data\n");
+		return -ENODEV;
+	}
+
+	if (pdata->num_leds > ADP5520_01_MAXLEDS) {
+		dev_err(&pdev->dev, "can't handle more than %d LEDS\n",
+				 ADP5520_01_MAXLEDS);
+		return -EFAULT;
+	}
+
+	led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL);
+	if (led == NULL) {
+		dev_err(&pdev->dev, "failed to alloc memory\n");
+		return -ENOMEM;
+	}
+
+	ret = adp5520_led_prepare(pdev);
+
+	if (ret) {
+		dev_err(&pdev->dev, "failed to write\n");
+		goto err_free;
+	}
+
+	for (i = 0; i < pdata->num_leds; ++i) {
+		cur_led = &pdata->leds[i];
+		led_dat = &led[i];
+
+		led_dat->cdev.name = cur_led->name;
+		led_dat->cdev.default_trigger = cur_led->default_trigger;
+		led_dat->cdev.brightness_set = adp5520_led_set;
+		led_dat->cdev.brightness = LED_OFF;
+
+		if (cur_led->flags & ADP5520_FLAG_LED_MASK)
+			led_dat->flags = cur_led->flags;
+		else
+			led_dat->flags = i + 1;
+
+		led_dat->id = led_dat->flags & ADP5520_FLAG_LED_MASK;
+
+		led_dat->master = pdev->dev.parent;
+		led_dat->new_brightness = LED_OFF;
+
+		INIT_WORK(&led_dat->work, adp5520_led_work);
+
+		ret = led_classdev_register(led_dat->master, &led_dat->cdev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register LED %d\n",
+				led_dat->id);
+			goto err;
+		}
+
+		ret = adp5520_led_setup(led_dat);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to write\n");
+			i++;
+			goto err;
+		}
+	}
+
+	platform_set_drvdata(pdev, led);
+	return 0;
+
+err:
+	if (i > 0) {
+		for (i = i - 1; i >= 0; i--) {
+			led_classdev_unregister(&led[i].cdev);
+			cancel_work_sync(&led[i].work);
+		}
+	}
+
+err_free:
+	kfree(led);
+	return ret;
+}
+
+static int __devexit adp5520_led_remove(struct platform_device *pdev)
+{
+	struct adp5520_leds_platform_data *pdata = pdev->dev.platform_data;
+	struct adp5520_led *led;
+	int i;
+
+	led = platform_get_drvdata(pdev);
+
+	adp5520_clr_bits(led->master, ADP5520_LED_CONTROL,
+		 ADP5520_LED1_EN | ADP5520_LED2_EN | ADP5520_LED3_EN);
+
+	for (i = 0; i < pdata->num_leds; i++) {
+		led_classdev_unregister(&led[i].cdev);
+		cancel_work_sync(&led[i].work);
+	}
+
+	kfree(led);
+	return 0;
+}
+
+static struct platform_driver adp5520_led_driver = {
+	.driver	= {
+		.name	= "adp5520-led",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= adp5520_led_probe,
+	.remove		= __devexit_p(adp5520_led_remove),
+};
+
+static int __init adp5520_led_init(void)
+{
+	return platform_driver_register(&adp5520_led_driver);
+}
+module_init(adp5520_led_init);
+
+static void __exit adp5520_led_exit(void)
+{
+	platform_driver_unregister(&adp5520_led_driver);
+}
+module_exit(adp5520_led_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("LEDS ADP5520(01) Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:adp5520-led");
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c
index 731d4ee..f59ffad 100644
--- a/drivers/leds/leds-alix2.c
+++ b/drivers/leds/leds-alix2.c
@@ -11,11 +11,24 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/string.h>
+#include <linux/pci.h>
 
 static int force = 0;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
 
+#define MSR_LBAR_GPIO		0x5140000C
+#define CS5535_GPIO_SIZE	256
+
+static u32 gpio_base;
+
+static struct pci_device_id divil_pci[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+	{ } /* NULL entry */
+};
+MODULE_DEVICE_TABLE(pci, divil_pci);
+
 struct alix_led {
 	struct led_classdev cdev;
 	unsigned short port;
@@ -30,9 +43,9 @@
 		container_of(led_cdev, struct alix_led, cdev);
 
 	if (brightness)
-		outl(led_dev->on_value, led_dev->port);
+		outl(led_dev->on_value, gpio_base + led_dev->port);
 	else
-		outl(led_dev->off_value, led_dev->port);
+		outl(led_dev->off_value, gpio_base + led_dev->port);
 }
 
 static struct alix_led alix_leds[] = {
@@ -41,7 +54,7 @@
 			.name = "alix:1",
 			.brightness_set = alix_led_set,
 		},
-		.port = 0x6100,
+		.port = 0x00,
 		.on_value = 1 << 22,
 		.off_value = 1 << 6,
 	},
@@ -50,7 +63,7 @@
 			.name = "alix:2",
 			.brightness_set = alix_led_set,
 		},
-		.port = 0x6180,
+		.port = 0x80,
 		.on_value = 1 << 25,
 		.off_value = 1 << 9,
 	},
@@ -59,7 +72,7 @@
 			.name = "alix:3",
 			.brightness_set = alix_led_set,
 		},
-		.port = 0x6180,
+		.port = 0x80,
 		.on_value = 1 << 27,
 		.off_value = 1 << 11,
 	},
@@ -101,64 +114,104 @@
 	},
 };
 
-static int __init alix_present(void)
+static int __init alix_present(unsigned long bios_phys,
+				const char *alix_sig,
+				size_t alix_sig_len)
 {
-	const unsigned long bios_phys = 0x000f0000;
 	const size_t bios_len = 0x00010000;
-	const char alix_sig[] = "PC Engines ALIX.";
-	const size_t alix_sig_len = sizeof(alix_sig) - 1;
-
 	const char *bios_virt;
 	const char *scan_end;
 	const char *p;
-	int ret = 0;
+	char name[64];
 
 	if (force) {
 		printk(KERN_NOTICE "%s: forced to skip BIOS test, "
 		       "assume system has ALIX.2 style LEDs\n",
 		       KBUILD_MODNAME);
-		ret = 1;
-		goto out;
+		return 1;
 	}
 
 	bios_virt = phys_to_virt(bios_phys);
 	scan_end = bios_virt + bios_len - (alix_sig_len + 2);
 	for (p = bios_virt; p < scan_end; p++) {
 		const char *tail;
+		char *a;
 
-		if (memcmp(p, alix_sig, alix_sig_len) != 0) {
+		if (memcmp(p, alix_sig, alix_sig_len) != 0)
 			continue;
-		}
+
+		memcpy(name, p, sizeof(name));
+
+		/* remove the first \0 character from string */
+		a = strchr(name, '\0');
+		if (a)
+			*a = ' ';
+
+		/* cut the string at a newline */
+		a = strchr(name, '\r');
+		if (a)
+			*a = '\0';
 
 		tail = p + alix_sig_len;
-		if ((tail[0] == '2' || tail[0] == '3') && tail[1] == '\0') {
+		if ((tail[0] == '2' || tail[0] == '3')) {
 			printk(KERN_INFO
 			       "%s: system is recognized as \"%s\"\n",
-			       KBUILD_MODNAME, p);
-			ret = 1;
-			break;
+			       KBUILD_MODNAME, name);
+			return 1;
 		}
 	}
 
-out:
-	return ret;
+	return 0;
 }
 
 static struct platform_device *pdev;
 
-static int __init alix_led_init(void)
+static int __init alix_pci_led_init(void)
 {
-	int ret;
+	u32 low, hi;
 
-	if (!alix_present()) {
-		ret = -ENODEV;
-		goto out;
+	if (pci_dev_present(divil_pci) == 0) {
+		printk(KERN_WARNING KBUILD_MODNAME": DIVIL not found\n");
+		return -ENODEV;
 	}
 
-	/* enable output on GPIO for LED 1,2,3 */
-	outl(1 << 6, 0x6104);
-	outl(1 << 9, 0x6184);
-	outl(1 << 11, 0x6184);
+	/* Grab the GPIO I/O range */
+	rdmsr(MSR_LBAR_GPIO, low, hi);
+
+	/* Check the mask and whether GPIO is enabled (sanity check) */
+	if (hi != 0x0000f001) {
+		printk(KERN_WARNING KBUILD_MODNAME": GPIO not enabled\n");
+		return -ENODEV;
+	}
+
+	/* Mask off the IO base address */
+	gpio_base = low & 0x0000ff00;
+
+	if (!request_region(gpio_base, CS5535_GPIO_SIZE, KBUILD_MODNAME)) {
+		printk(KERN_ERR KBUILD_MODNAME": can't allocate I/O for GPIO\n");
+		return -ENODEV;
+	}
+
+	/* Set GPIO function to output */
+	outl(1 << 6, gpio_base + 0x04);
+	outl(1 << 9, gpio_base + 0x84);
+	outl(1 << 11, gpio_base + 0x84);
+
+	return 0;
+}
+
+static int __init alix_led_init(void)
+{
+	int ret = -ENODEV;
+	const char tinybios_sig[] = "PC Engines ALIX.";
+	const char coreboot_sig[] = "PC Engines\0ALIX.";
+
+	if (alix_present(0xf0000, tinybios_sig, sizeof(tinybios_sig) - 1) ||
+	    alix_present(0x500, coreboot_sig, sizeof(coreboot_sig) - 1))
+		ret = alix_pci_led_init();
+
+	if (ret < 0)
+		return ret;
 
 	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
 	if (!IS_ERR(pdev)) {
@@ -168,7 +221,6 @@
 	} else
 		ret = PTR_ERR(pdev);
 
-out:
 	return ret;
 }
 
@@ -176,6 +228,7 @@
 {
 	platform_device_unregister(pdev);
 	platform_driver_unregister(&alix_led_driver);
+	release_region(gpio_base, CS5535_GPIO_SIZE);
 }
 
 module_init(alix_led_init);
diff --git a/drivers/leds/leds-cobalt-qube.c b/drivers/leds/leds-cobalt-qube.c
index 8816806..da5fb01 100644
--- a/drivers/leds/leds-cobalt-qube.c
+++ b/drivers/leds/leds-cobalt-qube.c
@@ -31,7 +31,7 @@
 	.name			= "qube::front",
 	.brightness		= LED_FULL,
 	.brightness_set		= qube_front_led_set,
-	.default_trigger	= "ide-disk",
+	.default_trigger	= "default-on",
 };
 
 static int __devinit cobalt_qube_led_probe(struct platform_device *pdev)
@@ -43,7 +43,7 @@
 	if (!res)
 		return -EBUSY;
 
-	led_port = ioremap(res->start, res->end - res->start + 1);
+	led_port = ioremap(res->start, resource_size(res));
 	if (!led_port)
 		return -ENOMEM;
 
diff --git a/drivers/leds/leds-cobalt-raq.c b/drivers/leds/leds-cobalt-raq.c
index defc212..438d483 100644
--- a/drivers/leds/leds-cobalt-raq.c
+++ b/drivers/leds/leds-cobalt-raq.c
@@ -84,7 +84,7 @@
 	if (!res)
 		return -EBUSY;
 
-	led_port = ioremap(res->start, res->end - res->start + 1);
+	led_port = ioremap(res->start, resource_size(res));
 	if (!led_port)
 		return -ENOMEM;
 
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
new file mode 100644
index 0000000..fee40a8
--- /dev/null
+++ b/drivers/leds/leds-lt3593.c
@@ -0,0 +1,217 @@
+/*
+ * LEDs driver for LT3593 controllers
+ *
+ * See the datasheet at http://cds.linear.com/docs/Datasheet/3593f.pdf
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ *
+ * Based on leds-gpio.c,
+ *
+ *   Copyright (C) 2007 8D Technologies inc.
+ *   Raphael Assenat <raph@8d.com>
+ *   Copyright (C) 2008 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+struct lt3593_led_data {
+	struct led_classdev cdev;
+	unsigned gpio;
+	struct work_struct work;
+	u8 new_level;
+};
+
+static void lt3593_led_work(struct work_struct *work)
+{
+	int pulses;
+	struct lt3593_led_data *led_dat =
+		container_of(work, struct lt3593_led_data, work);
+
+	/*
+	 * The LT3593 resets its internal current level register to the maximum
+	 * level on the first falling edge on the control pin. Each following
+	 * falling edge decreases the current level by 625uA. Up to 32 pulses
+	 * can be sent, so the maximum power reduction is 20mA.
+	 * After a timeout of 128us, the value is taken from the register and
+	 * applied is to the output driver.
+	 */
+
+	if (led_dat->new_level == 0) {
+		gpio_set_value_cansleep(led_dat->gpio, 0);
+		return;
+	}
+
+	pulses = 32 - (led_dat->new_level * 32) / 255;
+
+	if (pulses == 0) {
+		gpio_set_value_cansleep(led_dat->gpio, 0);
+		mdelay(1);
+		gpio_set_value_cansleep(led_dat->gpio, 1);
+		return;
+	}
+
+	gpio_set_value_cansleep(led_dat->gpio, 1);
+
+	while (pulses--) {
+		gpio_set_value_cansleep(led_dat->gpio, 0);
+		udelay(1);
+		gpio_set_value_cansleep(led_dat->gpio, 1);
+		udelay(1);
+	}
+}
+
+static void lt3593_led_set(struct led_classdev *led_cdev,
+	enum led_brightness value)
+{
+	struct lt3593_led_data *led_dat =
+		container_of(led_cdev, struct lt3593_led_data, cdev);
+
+	led_dat->new_level = value;
+	schedule_work(&led_dat->work);
+}
+
+static int __devinit create_lt3593_led(const struct gpio_led *template,
+	struct lt3593_led_data *led_dat, struct device *parent)
+{
+	int ret, state;
+
+	/* skip leds on GPIOs that aren't available */
+	if (!gpio_is_valid(template->gpio)) {
+		printk(KERN_INFO "%s: skipping unavailable LT3593 LED at gpio %d (%s)\n",
+				KBUILD_MODNAME, template->gpio, template->name);
+		return 0;
+	}
+
+	ret = gpio_request(template->gpio, template->name);
+	if (ret < 0)
+		return ret;
+
+	led_dat->cdev.name = template->name;
+	led_dat->cdev.default_trigger = template->default_trigger;
+	led_dat->gpio = template->gpio;
+
+	led_dat->cdev.brightness_set = lt3593_led_set;
+
+	state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
+
+	if (!template->retain_state_suspended)
+		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+
+	ret = gpio_direction_output(led_dat->gpio, state);
+	if (ret < 0)
+		goto err;
+
+	INIT_WORK(&led_dat->work, lt3593_led_work);
+
+	ret = led_classdev_register(parent, &led_dat->cdev);
+	if (ret < 0)
+		goto err;
+
+	printk(KERN_INFO "%s: registered LT3593 LED '%s' at GPIO %d\n",
+		KBUILD_MODNAME, template->name, template->gpio);
+
+	return 0;
+
+err:
+	gpio_free(led_dat->gpio);
+	return ret;
+}
+
+static void delete_lt3593_led(struct lt3593_led_data *led)
+{
+	if (!gpio_is_valid(led->gpio))
+		return;
+
+	led_classdev_unregister(&led->cdev);
+	cancel_work_sync(&led->work);
+	gpio_free(led->gpio);
+}
+
+static int __devinit lt3593_led_probe(struct platform_device *pdev)
+{
+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct lt3593_led_data *leds_data;
+	int i, ret = 0;
+
+	if (!pdata)
+		return -EBUSY;
+
+	leds_data = kzalloc(sizeof(struct lt3593_led_data) * pdata->num_leds,
+				GFP_KERNEL);
+	if (!leds_data)
+		return -ENOMEM;
+
+	for (i = 0; i < pdata->num_leds; i++) {
+		ret = create_lt3593_led(&pdata->leds[i], &leds_data[i],
+				      &pdev->dev);
+		if (ret < 0)
+			goto err;
+	}
+
+	platform_set_drvdata(pdev, leds_data);
+
+	return 0;
+
+err:
+	for (i = i - 1; i >= 0; i--)
+		delete_lt3593_led(&leds_data[i]);
+
+	kfree(leds_data);
+
+	return ret;
+}
+
+static int __devexit lt3593_led_remove(struct platform_device *pdev)
+{
+	int i;
+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct lt3593_led_data *leds_data;
+
+	leds_data = platform_get_drvdata(pdev);
+
+	for (i = 0; i < pdata->num_leds; i++)
+		delete_lt3593_led(&leds_data[i]);
+
+	kfree(leds_data);
+
+	return 0;
+}
+
+static struct platform_driver lt3593_led_driver = {
+	.probe		= lt3593_led_probe,
+	.remove		= __devexit_p(lt3593_led_remove),
+	.driver		= {
+		.name	= "leds-lt3593",
+		.owner	= THIS_MODULE,
+	},
+};
+
+MODULE_ALIAS("platform:leds-lt3593");
+
+static int __init lt3593_led_init(void)
+{
+	return platform_driver_register(&lt3593_led_driver);
+}
+
+static void __exit lt3593_led_exit(void)
+{
+	platform_driver_unregister(&lt3593_led_driver);
+}
+
+module_init(lt3593_led_init);
+module_exit(lt3593_led_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("LED driver for LT3593 controllers");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index cdfdc87..88b1dd0 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -27,7 +27,6 @@
 	struct pwm_device	*pwm;
 	unsigned int 		active_low;
 	unsigned int		period;
-	unsigned int		max_brightness;
 };
 
 static void led_pwm_set(struct led_classdev *led_cdev,
@@ -35,7 +34,7 @@
 {
 	struct led_pwm_data *led_dat =
 		container_of(led_cdev, struct led_pwm_data, cdev);
-	unsigned int max = led_dat->max_brightness;
+	unsigned int max = led_dat->cdev.max_brightness;
 	unsigned int period =  led_dat->period;
 
 	if (brightness == 0) {
@@ -77,10 +76,10 @@
 		led_dat->cdev.name = cur_led->name;
 		led_dat->cdev.default_trigger = cur_led->default_trigger;
 		led_dat->active_low = cur_led->active_low;
-		led_dat->max_brightness = cur_led->max_brightness;
 		led_dat->period = cur_led->pwm_period_ns;
 		led_dat->cdev.brightness_set = led_pwm_set;
 		led_dat->cdev.brightness = LED_OFF;
+		led_dat->cdev.max_brightness = cur_led->max_brightness;
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
 		ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
new file mode 100644
index 0000000..7f00de3
--- /dev/null
+++ b/drivers/leds/leds-regulator.c
@@ -0,0 +1,242 @@
+/*
+ * leds-regulator.c - LED class driver for regulator driven LEDs.
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * Inspired by leds-wm8350 driver.
+ *
+ * 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/err.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+#include <linux/leds-regulator.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#define to_regulator_led(led_cdev) \
+	container_of(led_cdev, struct regulator_led, cdev)
+
+struct regulator_led {
+	struct led_classdev cdev;
+	enum led_brightness value;
+	int enabled;
+	struct mutex mutex;
+	struct work_struct work;
+
+	struct regulator *vcc;
+};
+
+static inline int led_regulator_get_max_brightness(struct regulator *supply)
+{
+	int ret;
+	int voltage = regulator_list_voltage(supply, 0);
+
+	if (voltage <= 0)
+		return 1;
+
+	/* even if regulator can't change voltages,
+	 * we still assume it can change status
+	 * and the LED can be turned on and off.
+	 */
+	ret = regulator_set_voltage(supply, voltage, voltage);
+	if (ret < 0)
+		return 1;
+
+	return regulator_count_voltages(supply);
+}
+
+static int led_regulator_get_voltage(struct regulator *supply,
+		enum led_brightness brightness)
+{
+	if (brightness == 0)
+		return -EINVAL;
+
+	return regulator_list_voltage(supply, brightness - 1);
+}
+
+
+static void regulator_led_enable(struct regulator_led *led)
+{
+	int ret;
+
+	if (led->enabled)
+		return;
+
+	ret = regulator_enable(led->vcc);
+	if (ret != 0) {
+		dev_err(led->cdev.dev, "Failed to enable vcc: %d\n", ret);
+		return;
+	}
+
+	led->enabled = 1;
+}
+
+static void regulator_led_disable(struct regulator_led *led)
+{
+	int ret;
+
+	if (!led->enabled)
+		return;
+
+	ret = regulator_disable(led->vcc);
+	if (ret != 0) {
+		dev_err(led->cdev.dev, "Failed to disable vcc: %d\n", ret);
+		return;
+	}
+
+	led->enabled = 0;
+}
+
+static void regulator_led_set_value(struct regulator_led *led)
+{
+	int voltage;
+	int ret;
+
+	mutex_lock(&led->mutex);
+
+	if (led->value == LED_OFF) {
+		regulator_led_disable(led);
+		goto out;
+	}
+
+	if (led->cdev.max_brightness > 1) {
+		voltage = led_regulator_get_voltage(led->vcc, led->value);
+		dev_dbg(led->cdev.dev, "brightness: %d voltage: %d\n",
+				led->value, voltage);
+
+		ret = regulator_set_voltage(led->vcc, voltage, voltage);
+		if (ret != 0)
+			dev_err(led->cdev.dev, "Failed to set voltage %d: %d\n",
+				voltage, ret);
+	}
+
+	regulator_led_enable(led);
+
+out:
+	mutex_unlock(&led->mutex);
+}
+
+static void led_work(struct work_struct *work)
+{
+	struct regulator_led *led;
+
+	led = container_of(work, struct regulator_led, work);
+	regulator_led_set_value(led);
+}
+
+static void regulator_led_brightness_set(struct led_classdev *led_cdev,
+			   enum led_brightness value)
+{
+	struct regulator_led *led = to_regulator_led(led_cdev);
+
+	led->value = value;
+	schedule_work(&led->work);
+}
+
+static int __devinit regulator_led_probe(struct platform_device *pdev)
+{
+	struct led_regulator_platform_data *pdata = pdev->dev.platform_data;
+	struct regulator_led *led;
+	struct regulator *vcc;
+	int ret = 0;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "no platform data\n");
+		return -ENODEV;
+	}
+
+	vcc = regulator_get_exclusive(&pdev->dev, "vled");
+	if (IS_ERR(vcc)) {
+		dev_err(&pdev->dev, "Cannot get vcc for %s\n", pdata->name);
+		return PTR_ERR(vcc);
+	}
+
+	led = kzalloc(sizeof(*led), GFP_KERNEL);
+	if (led == NULL) {
+		ret = -ENOMEM;
+		goto err_vcc;
+	}
+
+	led->cdev.max_brightness = led_regulator_get_max_brightness(vcc);
+	if (pdata->brightness > led->cdev.max_brightness) {
+		dev_err(&pdev->dev, "Invalid default brightness %d\n",
+				pdata->brightness);
+		ret = -EINVAL;
+		goto err_led;
+	}
+	led->value = pdata->brightness;
+
+	led->cdev.brightness_set = regulator_led_brightness_set;
+	led->cdev.name = pdata->name;
+	led->cdev.flags |= LED_CORE_SUSPENDRESUME;
+	led->vcc = vcc;
+
+	mutex_init(&led->mutex);
+	INIT_WORK(&led->work, led_work);
+
+	platform_set_drvdata(pdev, led);
+
+	ret = led_classdev_register(&pdev->dev, &led->cdev);
+	if (ret < 0) {
+		cancel_work_sync(&led->work);
+		goto err_led;
+	}
+
+	/* to expose the default value to userspace */
+	led->cdev.brightness = led->value;
+
+	/* Set the default led status */
+	regulator_led_set_value(led);
+
+	return 0;
+
+err_led:
+	kfree(led);
+err_vcc:
+	regulator_put(vcc);
+	return ret;
+}
+
+static int __devexit regulator_led_remove(struct platform_device *pdev)
+{
+	struct regulator_led *led = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&led->cdev);
+	cancel_work_sync(&led->work);
+	regulator_led_disable(led);
+	regulator_put(led->vcc);
+	kfree(led);
+	return 0;
+}
+
+static struct platform_driver regulator_led_driver = {
+	.driver = {
+		   .name  = "leds-regulator",
+		   .owner = THIS_MODULE,
+		   },
+	.probe  = regulator_led_probe,
+	.remove = __devexit_p(regulator_led_remove),
+};
+
+static int __init regulator_led_init(void)
+{
+	return platform_driver_register(&regulator_led_driver);
+}
+module_init(regulator_led_init);
+
+static void __exit regulator_led_exit(void)
+{
+	platform_driver_unregister(&regulator_led_driver);
+}
+module_exit(regulator_led_exit);
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("Regulator driven LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-regulator");
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c
new file mode 100644
index 0000000..97f0498
--- /dev/null
+++ b/drivers/leds/leds-ss4200.c
@@ -0,0 +1,556 @@
+/*
+ * SS4200-E Hardware API
+ * Copyright (c) 2009, Intel Corporation.
+ * Copyright IBM Corporation, 2009
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Author: Dave Hansen <dave@sr71.net>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dmi.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+MODULE_AUTHOR("Rodney Girod <rgirod@confocus.com>, Dave Hansen <dave@sr71.net>");
+MODULE_DESCRIPTION("Intel NAS/Home Server ICH7 GPIO Driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * ICH7 LPC/GPIO PCI Config register offsets
+ */
+#define PMBASE		0x040
+#define GPIO_BASE	0x048
+#define GPIO_CTRL	0x04c
+#define GPIO_EN		0x010
+
+/*
+ * The ICH7 GPIO register block is 64 bytes in size.
+ */
+#define ICH7_GPIO_SIZE	64
+
+/*
+ * Define register offsets within the ICH7 register block.
+ */
+#define GPIO_USE_SEL	0x000
+#define GP_IO_SEL	0x004
+#define GP_LVL		0x00c
+#define GPO_BLINK	0x018
+#define GPI_INV		0x030
+#define GPIO_USE_SEL2	0x034
+#define GP_IO_SEL2	0x038
+#define GP_LVL2		0x03c
+
+/*
+ * PCI ID of the Intel ICH7 LPC Device within which the GPIO block lives.
+ */
+static struct pci_device_id ich7_lpc_pci_id[] =
+{
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30) },
+	{ } /* NULL entry */
+};
+
+MODULE_DEVICE_TABLE(pci, ich7_lpc_pci_id);
+
+static int __init ss4200_led_dmi_callback(const struct dmi_system_id *id)
+{
+	pr_info("detected '%s'\n", id->ident);
+	return 1;
+}
+
+static unsigned int __initdata nodetect;
+module_param_named(nodetect, nodetect, bool, 0);
+MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
+
+/*
+ * struct nas_led_whitelist - List of known good models
+ *
+ * Contains the known good models this driver is compatible with.
+ * When adding a new model try to be as strict as possible. This
+ * makes it possible to keep the false positives (the model is
+ * detected as working, but in reality it is not) as low as
+ * possible.
+ */
+static struct dmi_system_id __initdata nas_led_whitelist[] = {
+	{
+		.callback = ss4200_led_dmi_callback,
+		.ident = "Intel SS4200-E",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SS4200-E"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
+		}
+	},
+};
+
+/*
+ * Base I/O address assigned to the Power Management register block
+ */
+static u32 g_pm_io_base;
+
+/*
+ * Base I/O address assigned to the ICH7 GPIO register block
+ */
+static u32 nas_gpio_io_base;
+
+/*
+ * When we successfully register a region, we are returned a resource.
+ * We use these to identify which regions we need to release on our way
+ * back out.
+ */
+static struct resource *gp_gpio_resource;
+
+struct nasgpio_led {
+	char *name;
+	u32 gpio_bit;
+	struct led_classdev led_cdev;
+};
+
+/*
+ * gpio_bit(s) are the ICH7 GPIO bit assignments
+ */
+static struct nasgpio_led nasgpio_leds[] = {
+	{ .name = "hdd1:blue:sata",	.gpio_bit = 0 },
+	{ .name = "hdd1:amber:sata",	.gpio_bit = 1 },
+	{ .name = "hdd2:blue:sata",	.gpio_bit = 2 },
+	{ .name = "hdd2:amber:sata",	.gpio_bit = 3 },
+	{ .name = "hdd3:blue:sata",	.gpio_bit = 4 },
+	{ .name = "hdd3:amber:sata",	.gpio_bit = 5 },
+	{ .name = "hdd4:blue:sata",	.gpio_bit = 6 },
+	{ .name = "hdd4:amber:sata",	.gpio_bit = 7 },
+	{ .name = "power:blue:power",	.gpio_bit = 27},
+	{ .name = "power:amber:power",  .gpio_bit = 28},
+};
+
+#define NAS_RECOVERY	0x00000400	/* GPIO10 */
+
+static struct nasgpio_led *
+led_classdev_to_nasgpio_led(struct led_classdev *led_cdev)
+{
+	return container_of(led_cdev, struct nasgpio_led, led_cdev);
+}
+
+static struct nasgpio_led *get_led_named(char *name)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
+		if (strcmp(nasgpio_leds[i].name, name))
+			continue;
+		return &nasgpio_leds[i];
+	}
+	return NULL;
+}
+
+/*
+ * This protects access to the gpio ports.
+ */
+static DEFINE_SPINLOCK(nasgpio_gpio_lock);
+
+/*
+ * There are two gpio ports, one for blinking and the other
+ * for power.  @port tells us if we're doing blinking or
+ * power control.
+ *
+ * Caller must hold nasgpio_gpio_lock
+ */
+static void __nasgpio_led_set_attr(struct led_classdev *led_cdev,
+				   u32 port, u32 value)
+{
+	struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
+	u32 gpio_out;
+
+	gpio_out = inl(nas_gpio_io_base + port);
+	if (value)
+		gpio_out |= (1<<led->gpio_bit);
+	else
+		gpio_out &= ~(1<<led->gpio_bit);
+
+	outl(gpio_out, nas_gpio_io_base + port);
+}
+
+static void nasgpio_led_set_attr(struct led_classdev *led_cdev,
+				 u32 port, u32 value)
+{
+	spin_lock(&nasgpio_gpio_lock);
+	__nasgpio_led_set_attr(led_cdev, port, value);
+	spin_unlock(&nasgpio_gpio_lock);
+}
+
+u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port)
+{
+	struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
+	u32 gpio_in;
+
+	spin_lock(&nasgpio_gpio_lock);
+	gpio_in = inl(nas_gpio_io_base + port);
+	spin_unlock(&nasgpio_gpio_lock);
+	if (gpio_in & (1<<led->gpio_bit))
+		return 1;
+	return 0;
+}
+
+/*
+ * There is actual brightness control in the hardware,
+ * but it is via smbus commands and not implemented
+ * in this driver.
+ */
+static void nasgpio_led_set_brightness(struct led_classdev *led_cdev,
+				       enum led_brightness brightness)
+{
+	u32 setting = 0;
+	if (brightness >= LED_HALF)
+		setting = 1;
+	/*
+	 * Hold the lock across both operations.  This ensures
+	 * consistency so that both the "turn off blinking"
+	 * and "turn light off" operations complete as a set.
+	 */
+	spin_lock(&nasgpio_gpio_lock);
+	/*
+	 * LED class documentation asks that past blink state
+	 * be disabled when brightness is turned to zero.
+	 */
+	if (brightness == 0)
+		__nasgpio_led_set_attr(led_cdev, GPO_BLINK, 0);
+	__nasgpio_led_set_attr(led_cdev, GP_LVL, setting);
+	spin_unlock(&nasgpio_gpio_lock);
+}
+
+static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
+				 unsigned long *delay_on,
+				 unsigned long *delay_off)
+{
+	u32 setting = 1;
+	if (!(*delay_on == 0 && *delay_off == 0) &&
+	    !(*delay_on == 500 && *delay_off == 500))
+		return -EINVAL;
+	/*
+	 * These are very approximate.
+	 */
+	*delay_on = 500;
+	*delay_off = 500;
+
+	nasgpio_led_set_attr(led_cdev, GPO_BLINK, setting);
+
+	return 0;
+}
+
+
+/*
+ * Initialize the ICH7 GPIO registers for NAS usage.  The BIOS should have
+ * already taken care of this, but we will do so in a non destructive manner
+ * so that we have what we need whether the BIOS did it or not.
+ */
+static int __devinit ich7_gpio_init(struct device *dev)
+{
+	int i;
+	u32 config_data = 0;
+	u32 all_nas_led = 0;
+
+	for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
+		all_nas_led |= (1<<nasgpio_leds[i].gpio_bit);
+
+	spin_lock(&nasgpio_gpio_lock);
+	/*
+	 * We need to enable all of the GPIO lines used by the NAS box,
+	 * so we will read the current Use Selection and add our usage
+	 * to it.  This should be benign with regard to the original
+	 * BIOS configuration.
+	 */
+	config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
+	dev_dbg(dev, ": Data read from GPIO_USE_SEL = 0x%08x\n", config_data);
+	config_data |= all_nas_led + NAS_RECOVERY;
+	outl(config_data, nas_gpio_io_base + GPIO_USE_SEL);
+	config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
+	dev_dbg(dev, ": GPIO_USE_SEL = 0x%08x\n\n", config_data);
+
+	/*
+	 * The LED GPIO outputs need to be configured for output, so we
+	 * will ensure that all LED lines are cleared for output and the
+	 * RECOVERY line ready for input.  This too should be benign with
+	 * regard to BIOS configuration.
+	 */
+	config_data = inl(nas_gpio_io_base + GP_IO_SEL);
+	dev_dbg(dev, ": Data read from GP_IO_SEL = 0x%08x\n",
+					config_data);
+	config_data &= ~all_nas_led;
+	config_data |= NAS_RECOVERY;
+	outl(config_data, nas_gpio_io_base + GP_IO_SEL);
+	config_data = inl(nas_gpio_io_base + GP_IO_SEL);
+	dev_dbg(dev, ": GP_IO_SEL = 0x%08x\n", config_data);
+
+	/*
+	 * In our final system, the BIOS will initialize the state of all
+	 * of the LEDs.  For now, we turn them all off (or Low).
+	 */
+	config_data = inl(nas_gpio_io_base + GP_LVL);
+	dev_dbg(dev, ": Data read from GP_LVL = 0x%08x\n", config_data);
+	/*
+	 * In our final system, the BIOS will initialize the blink state of all
+	 * of the LEDs.  For now, we turn blink off for all of them.
+	 */
+	config_data = inl(nas_gpio_io_base + GPO_BLINK);
+	dev_dbg(dev, ": Data read from GPO_BLINK = 0x%08x\n", config_data);
+
+	/*
+	 * At this moment, I am unsure if anything needs to happen with GPI_INV
+	 */
+	config_data = inl(nas_gpio_io_base + GPI_INV);
+	dev_dbg(dev, ": Data read from GPI_INV = 0x%08x\n", config_data);
+
+	spin_unlock(&nasgpio_gpio_lock);
+	return 0;
+}
+
+static void ich7_lpc_cleanup(struct device *dev)
+{
+	/*
+	 * If we were given exclusive use of the GPIO
+	 * I/O Address range, we must return it.
+	 */
+	if (gp_gpio_resource) {
+		dev_dbg(dev, ": Releasing GPIO I/O addresses\n");
+		release_region(nas_gpio_io_base, ICH7_GPIO_SIZE);
+		gp_gpio_resource = NULL;
+	}
+}
+
+/*
+ * The OS has determined that the LPC of the Intel ICH7 Southbridge is present
+ * so we can retrive the required operational information and prepare the GPIO.
+ */
+static struct pci_dev *nas_gpio_pci_dev;
+static int __devinit ich7_lpc_probe(struct pci_dev *dev,
+				    const struct pci_device_id *id)
+{
+	int status;
+	u32 gc = 0;
+
+	status = pci_enable_device(dev);
+	if (status) {
+		dev_err(&dev->dev, "pci_enable_device failed\n");
+		return -EIO;
+	}
+
+	nas_gpio_pci_dev = dev;
+	status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
+	if (status)
+		goto out;
+	g_pm_io_base &= 0x00000ff80;
+
+	status = pci_read_config_dword(dev, GPIO_CTRL, &gc);
+	if (!(GPIO_EN & gc)) {
+		status = -EEXIST;
+		dev_info(&dev->dev,
+			   "ERROR: The LPC GPIO Block has not been enabled.\n");
+		goto out;
+	}
+
+	status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base);
+	if (0 > status) {
+		dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
+		goto out;
+	}
+	dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);
+	nas_gpio_io_base &= 0x00000ffc0;
+
+	/*
+	 * Insure that we have exclusive access to the GPIO I/O address range.
+	 */
+	gp_gpio_resource = request_region(nas_gpio_io_base, ICH7_GPIO_SIZE,
+					  KBUILD_MODNAME);
+	if (NULL == gp_gpio_resource) {
+		dev_info(&dev->dev,
+			 "ERROR Unable to register GPIO I/O addresses.\n");
+		status = -1;
+		goto out;
+	}
+
+	/*
+	 * Initialize the GPIO for NAS/Home Server Use
+	 */
+	ich7_gpio_init(&dev->dev);
+
+out:
+	if (status) {
+		ich7_lpc_cleanup(&dev->dev);
+		pci_disable_device(dev);
+	}
+	return status;
+}
+
+static void ich7_lpc_remove(struct pci_dev *dev)
+{
+	ich7_lpc_cleanup(&dev->dev);
+	pci_disable_device(dev);
+}
+
+/*
+ * pci_driver structure passed to the PCI modules
+ */
+static struct pci_driver nas_gpio_pci_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = ich7_lpc_pci_id,
+	.probe = ich7_lpc_probe,
+	.remove = ich7_lpc_remove,
+};
+
+static struct led_classdev *get_classdev_for_led_nr(int nr)
+{
+	struct nasgpio_led *nas_led = &nasgpio_leds[nr];
+	struct led_classdev *led = &nas_led->led_cdev;
+	return led;
+}
+
+
+static void set_power_light_amber_noblink(void)
+{
+	struct nasgpio_led *amber = get_led_named("power:amber:power");
+	struct nasgpio_led *blue = get_led_named("power:blue:power");
+
+	if (!amber || !blue)
+		return;
+	/*
+	 * LED_OFF implies disabling future blinking
+	 */
+	pr_debug("setting blue off and amber on\n");
+
+	nasgpio_led_set_brightness(&blue->led_cdev, LED_OFF);
+	nasgpio_led_set_brightness(&amber->led_cdev, LED_FULL);
+}
+
+static ssize_t nas_led_blink_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct led_classdev *led = dev_get_drvdata(dev);
+	int blinking = 0;
+	if (nasgpio_led_get_attr(led, GPO_BLINK))
+		blinking = 1;
+	return sprintf(buf, "%u\n", blinking);
+}
+
+static ssize_t nas_led_blink_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	int ret;
+	struct led_classdev *led = dev_get_drvdata(dev);
+	unsigned long blink_state;
+
+	ret = strict_strtoul(buf, 10, &blink_state);
+	if (ret)
+		return ret;
+
+	nasgpio_led_set_attr(led, GPO_BLINK, blink_state);
+
+	return size;
+}
+
+static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
+
+static int register_nasgpio_led(int led_nr)
+{
+	int ret;
+	struct nasgpio_led *nas_led = &nasgpio_leds[led_nr];
+	struct led_classdev *led = get_classdev_for_led_nr(led_nr);
+
+	led->name = nas_led->name;
+	led->brightness = LED_OFF;
+	if (nasgpio_led_get_attr(led, GP_LVL))
+		led->brightness = LED_FULL;
+	led->brightness_set = nasgpio_led_set_brightness;
+	led->blink_set = nasgpio_led_set_blink;
+	ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
+	if (ret)
+		return ret;
+	ret = device_create_file(led->dev, &dev_attr_blink);
+	if (ret)
+		led_classdev_unregister(led);
+	return ret;
+}
+
+static void unregister_nasgpio_led(int led_nr)
+{
+	struct led_classdev *led = get_classdev_for_led_nr(led_nr);
+	led_classdev_unregister(led);
+	device_remove_file(led->dev, &dev_attr_blink);
+}
+/*
+ * module load/initialization
+ */
+static int __init nas_gpio_init(void)
+{
+	int i;
+	int ret = 0;
+	int nr_devices = 0;
+
+	nr_devices = dmi_check_system(nas_led_whitelist);
+	if (nodetect) {
+		pr_info("skipping hardware autodetection\n");
+		pr_info("Please send 'dmidecode' output to dave@sr71.net\n");
+		nr_devices++;
+	}
+
+	if (nr_devices <= 0) {
+		pr_info("no LED devices found\n");
+		return -ENODEV;
+	}
+
+	pr_info("registering PCI driver\n");
+	ret = pci_register_driver(&nas_gpio_pci_driver);
+	if (ret)
+		return ret;
+	for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
+		ret = register_nasgpio_led(i);
+		if (ret)
+			goto out_err;
+	}
+	/*
+	 * When the system powers on, the BIOS leaves the power
+	 * light blue and blinking.  This will turn it solid
+	 * amber once the driver is loaded.
+	 */
+	set_power_light_amber_noblink();
+	return 0;
+out_err:
+	for (; i >= 0; i--)
+		unregister_nasgpio_led(i);
+	pci_unregister_driver(&nas_gpio_pci_driver);
+	return ret;
+}
+
+/*
+ * module unload
+ */
+static void __exit nas_gpio_exit(void)
+{
+	int i;
+	pr_info("Unregistering driver\n");
+	for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
+		unregister_nasgpio_led(i);
+	pci_unregister_driver(&nas_gpio_pci_driver);
+}
+
+module_init(nas_gpio_init);
+module_exit(nas_gpio_exit);
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
new file mode 100644
index 0000000..4dde7d1
--- /dev/null
+++ b/drivers/media/IR/Kconfig
@@ -0,0 +1,9 @@
+config IR_CORE
+	tristate
+	depends on INPUT
+	default INPUT
+
+config VIDEO_IR
+	tristate
+	depends on IR_CORE
+	default IR_CORE
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
new file mode 100644
index 0000000..df5ddb4
--- /dev/null
+++ b/drivers/media/IR/Makefile
@@ -0,0 +1,5 @@
+ir-common-objs  := ir-functions.o ir-keymaps.o
+ir-core-objs	:= ir-keytable.o
+
+obj-$(CONFIG_IR_CORE) += ir-core.o
+obj-$(CONFIG_VIDEO_IR) += ir-common.o
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/IR/ir-functions.c
similarity index 92%
rename from drivers/media/common/ir-functions.c
rename to drivers/media/IR/ir-functions.c
index e616f62..776a136 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/IR/ir-functions.c
@@ -34,9 +34,6 @@
 module_param(repeat, int, 0444);
 MODULE_PARM_DESC(repeat,"auto-repeat for IR keys (default: on)");
 
-int media_ir_debug;    /* media_ir_debug level (0,1,2) */
-module_param_named(debug, media_ir_debug, int, 0644);
-
 /* -------------------------------------------------------------------------- */
 
 static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@@ -55,25 +52,10 @@
 /* -------------------------------------------------------------------------- */
 
 int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
-		   int ir_type, struct ir_scancode_table *ir_codes)
+		   int ir_type)
 {
 	ir->ir_type = ir_type;
 
-	ir->keytable.size = ir_roundup_tablesize(ir_codes->size);
-	ir->keytable.scan = kzalloc(ir->keytable.size *
-				    sizeof(struct ir_scancode), GFP_KERNEL);
-	if (!ir->keytable.scan)
-		return -ENOMEM;
-
-	IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
-		ir->keytable.size,
-		ir->keytable.size * sizeof(ir->keytable.scan));
-
-	ir_copy_table(&ir->keytable, ir_codes);
-	ir_set_keycode_table(dev, &ir->keytable);
-
-	clear_bit(0, dev->keybit);
-	set_bit(EV_KEY, dev->evbit);
 	if (repeat)
 		set_bit(EV_REP, dev->evbit);
 
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/IR/ir-keymaps.c
similarity index 97%
rename from drivers/media/common/ir-keymaps.c
rename to drivers/media/IR/ir-keymaps.c
index 328c973..9bbe6b1 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/IR/ir-keymaps.c
@@ -1847,76 +1847,6 @@
 };
 EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new_table);
 
-/*
- * Hauppauge:the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- *
- * This table contains the complete RC5 code, instead of just the data part
- */
-static struct ir_scancode ir_codes_rc5_hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-
-	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x1e0b, KEY_RED },		/* red button */
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },		/* Videos */
-	{ 0x1e19, KEY_AUDIO },		/* Music */
-	/* 0x1e1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1e1a, KEY_MHP },
-
-	{ 0x1e1b, KEY_EPG },		/* Guide */
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1e1f, KEY_EXIT },		/* back/exit */
-	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x1e25, KEY_ENTER },		/* OK */
-	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x1e29, KEY_BLUE },		/* blue key */
-	{ 0x1e2e, KEY_GREEN },		/* green button */
-	{ 0x1e30, KEY_PAUSE },		/* pause */
-	{ 0x1e32, KEY_REWIND },		/* backward << */
-	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },		/* recording */
-	{ 0x1e38, KEY_YELLOW },		/* yellow key */
-	{ 0x1e3b, KEY_SELECT },		/* top right button */
-	{ 0x1e3c, KEY_ZOOM },		/* full */
-	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
-};
-
-struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = {
-	.scan = ir_codes_rc5_hauppauge_new,
-	.size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new),
-};
-EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table);
-
 static struct ir_scancode ir_codes_npgtech[] = {
 	{ 0x1d, KEY_SWITCHVIDEOMODE },	/* switch inputs */
 	{ 0x2a, KEY_FRONT },
@@ -3314,3 +3244,152 @@
 };
 EXPORT_SYMBOL_GPL(ir_codes_gadmei_rm008z_table);
 
+/*************************************************************
+ *		COMPLETE SCANCODE TABLES
+ * Instead of just a partial scancode, the tables bellow
+ * contains the complete scancode and the receiver protocol
+ *************************************************************/
+
+/*
+ * Hauppauge:the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ *
+ * This table contains the complete RC5 code, instead of just the data part
+ */
+static struct ir_scancode ir_codes_rc5_hauppauge_new[] = {
+	/* Keys 0 to 9 */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e01, KEY_1 },
+	{ 0x1e02, KEY_2 },
+	{ 0x1e03, KEY_3 },
+	{ 0x1e04, KEY_4 },
+	{ 0x1e05, KEY_5 },
+	{ 0x1e06, KEY_6 },
+	{ 0x1e07, KEY_7 },
+	{ 0x1e08, KEY_8 },
+	{ 0x1e09, KEY_9 },
+
+	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
+	{ 0x1e0b, KEY_RED },		/* red button */
+	{ 0x1e0c, KEY_RADIO },
+	{ 0x1e0d, KEY_MENU },
+	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
+	{ 0x1e0f, KEY_MUTE },
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e18, KEY_VIDEO },		/* Videos */
+	{ 0x1e19, KEY_AUDIO },		/* Music */
+	/* 0x1e1a: Pictures - presume this means
+	   "Multimedia Home Platform" -
+	   no "PICTURES" key in input.h
+	 */
+	{ 0x1e1a, KEY_MHP },
+
+	{ 0x1e1b, KEY_EPG },		/* Guide */
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
+	{ 0x1e1f, KEY_EXIT },		/* back/exit */
+	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
+	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1e25, KEY_ENTER },		/* OK */
+	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
+	{ 0x1e29, KEY_BLUE },		/* blue key */
+	{ 0x1e2e, KEY_GREEN },		/* green button */
+	{ 0x1e30, KEY_PAUSE },		/* pause */
+	{ 0x1e32, KEY_REWIND },		/* backward << */
+	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e36, KEY_STOP },
+	{ 0x1e37, KEY_RECORD },		/* recording */
+	{ 0x1e38, KEY_YELLOW },		/* yellow key */
+	{ 0x1e3b, KEY_SELECT },		/* top right button */
+	{ 0x1e3c, KEY_ZOOM },		/* full */
+	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
+};
+
+struct ir_scancode_table ir_codes_rc5_hauppauge_new_table = {
+	.scan = ir_codes_rc5_hauppauge_new,
+	.size = ARRAY_SIZE(ir_codes_rc5_hauppauge_new),
+	.ir_type = IR_TYPE_RC5,
+};
+EXPORT_SYMBOL_GPL(ir_codes_rc5_hauppauge_new_table);
+
+/* Terratec Cinergy Hybrid T USB XS FM
+   Mauro Carvalho Chehab <mchehab@redhat.com>
+ */
+static struct ir_scancode ir_codes_nec_terratec_cinergy_xs[] = {
+	{ 0x1441, KEY_HOME},
+	{ 0x1401, KEY_POWER2},
+
+	{ 0x1442, KEY_MENU},		/* DVD menu */
+	{ 0x1443, KEY_SUBTITLE},
+	{ 0x1444, KEY_TEXT},		/* Teletext */
+	{ 0x1445, KEY_DELETE},
+
+	{ 0x1402, KEY_1},
+	{ 0x1403, KEY_2},
+	{ 0x1404, KEY_3},
+	{ 0x1405, KEY_4},
+	{ 0x1406, KEY_5},
+	{ 0x1407, KEY_6},
+	{ 0x1408, KEY_7},
+	{ 0x1409, KEY_8},
+	{ 0x140a, KEY_9},
+	{ 0x140c, KEY_0},
+
+	{ 0x140b, KEY_TUNER},		/* AV */
+	{ 0x140d, KEY_MODE},		/* A.B */
+
+	{ 0x1446, KEY_TV},
+	{ 0x1447, KEY_DVD},
+	{ 0x1449, KEY_VIDEO},
+	{ 0x144a, KEY_RADIO},		/* Music */
+	{ 0x144b, KEY_CAMERA},		/* PIC */
+
+	{ 0x1410, KEY_UP},
+	{ 0x1411, KEY_LEFT},
+	{ 0x1412, KEY_OK},
+	{ 0x1413, KEY_RIGHT},
+	{ 0x1414, KEY_DOWN},
+
+	{ 0x140f, KEY_EPG},
+	{ 0x1416, KEY_INFO},
+	{ 0x144d, KEY_BACKSPACE},
+
+	{ 0x141c, KEY_VOLUMEUP},
+	{ 0x141e, KEY_VOLUMEDOWN},
+
+	{ 0x144c, KEY_PLAY},
+	{ 0x141d, KEY_MUTE},
+
+	{ 0x141b, KEY_CHANNELUP},
+	{ 0x141f, KEY_CHANNELDOWN},
+
+	{ 0x1417, KEY_RED},
+	{ 0x1418, KEY_GREEN},
+	{ 0x1419, KEY_YELLOW},
+	{ 0x141a, KEY_BLUE},
+
+	{ 0x1458, KEY_RECORD},
+	{ 0x1448, KEY_STOP},
+	{ 0x1440, KEY_PAUSE},
+
+	{ 0x1454, KEY_LAST},
+	{ 0x144e, KEY_REWIND},
+	{ 0x144f, KEY_FASTFORWARD},
+	{ 0x145c, KEY_NEXT},
+};
+struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table = {
+	.scan = ir_codes_nec_terratec_cinergy_xs,
+	.size = ARRAY_SIZE(ir_codes_nec_terratec_cinergy_xs),
+	.ir_type = IR_TYPE_NEC,
+};
+EXPORT_SYMBOL_GPL(ir_codes_nec_terratec_cinergy_xs_table);
+
diff --git a/drivers/media/common/ir-keytable.c b/drivers/media/IR/ir-keytable.c
similarity index 81%
rename from drivers/media/common/ir-keytable.c
rename to drivers/media/IR/ir-keytable.c
index 26ce5bc..bff7a53 100644
--- a/drivers/media/common/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -1,10 +1,19 @@
 /* ir-register.c - handle IR scancode->keycode tables
  *
  * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@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 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.
  */
 
-#include <linux/usb/input.h>
 
+#include <linux/usb/input.h>
 #include <media/ir-common.h>
 
 #define IR_TAB_MIN_SIZE	32
@@ -72,6 +81,7 @@
 
 	return n_elems;
 }
+EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
 
 /**
  * ir_copy_table() - copies a keytable, discarding the unused entries
@@ -100,6 +110,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(ir_copy_table);
 
 /**
  * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
@@ -114,7 +125,8 @@
 			 int scancode, int *keycode)
 {
 	int elem;
-	struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
+	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 
 	elem = ir_seek_table(rc_tab, scancode);
 	if (elem >= 0) {
@@ -136,7 +148,6 @@
 	return 0;
 }
 
-
 /**
  * ir_is_resize_needed() - Check if the table needs rezise
  * @table:		keycode table that may need to resize
@@ -286,7 +297,8 @@
 			 int scancode, int keycode)
 {
 	int rc = 0;
-	struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
+	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 	struct ir_scancode *keymap = rc_tab->scan;
 	unsigned long flags;
 
@@ -360,7 +372,8 @@
  */
 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
 {
-	struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
+	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 	struct ir_scancode *keymap = rc_tab->scan;
 	int elem;
 
@@ -378,9 +391,10 @@
 	/* Reports userspace that an unknown keycode were got */
 	return KEY_RESERVED;
 }
+EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
 
 /**
- * ir_set_keycode_table() - sets the IR keycode table and add the handlers
+ * ir_input_register() - sets the IR keycode table and add the handlers
  *			    for keymap table get/set
  * @input_dev:	the struct input_dev descriptor of the device
  * @rc_tab:	the struct ir_scancode_table table of scancode/keymap
@@ -389,17 +403,34 @@
  * an IR.
  * It should be called before registering the IR device.
  */
-int ir_set_keycode_table(struct input_dev *input_dev,
-			 struct ir_scancode_table *rc_tab)
+int ir_input_register(struct input_dev *input_dev,
+		      struct ir_scancode_table *rc_tab)
 {
-	struct ir_scancode *keymap = rc_tab->scan;
-	int i;
-
-	spin_lock_init(&rc_tab->lock);
+	struct ir_input_dev *ir_dev;
+	struct ir_scancode  *keymap    = rc_tab->scan;
+	int i, rc;
 
 	if (rc_tab->scan == NULL || !rc_tab->size)
 		return -EINVAL;
 
+	ir_dev = kzalloc(sizeof(*ir_dev), GFP_KERNEL);
+	if (!ir_dev)
+		return -ENOMEM;
+
+	spin_lock_init(&rc_tab->lock);
+
+	ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
+	ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
+				    sizeof(struct ir_scancode), GFP_KERNEL);
+	if (!ir_dev->rc_tab.scan)
+		return -ENOMEM;
+
+	IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
+		ir_dev->rc_tab.size,
+		ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));
+
+	ir_copy_table(&ir_dev->rc_tab, rc_tab);
+
 	/* set the bits for the keys */
 	IR_dprintk(1, "key map size: %d\n", rc_tab->size);
 	for (i = 0; i < rc_tab->size; i++) {
@@ -407,23 +438,48 @@
 			i, keymap[i].keycode);
 		set_bit(keymap[i].keycode, input_dev->keybit);
 	}
+	clear_bit(0, input_dev->keybit);
+
+	set_bit(EV_KEY, input_dev->evbit);
 
 	input_dev->getkeycode = ir_getkeycode;
 	input_dev->setkeycode = ir_setkeycode;
-	input_set_drvdata(input_dev, rc_tab);
+	input_set_drvdata(input_dev, ir_dev);
 
-	return 0;
+	rc = input_register_device(input_dev);
+	if (rc < 0) {
+		kfree(rc_tab->scan);
+		kfree(ir_dev);
+		input_set_drvdata(input_dev, NULL);
+	}
+
+	return rc;
 }
+EXPORT_SYMBOL_GPL(ir_input_register);
 
-void ir_input_free(struct input_dev *dev)
+void ir_input_unregister(struct input_dev *dev)
 {
-	struct ir_scancode_table *rc_tab = input_get_drvdata(dev);
+	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+	struct ir_scancode_table *rc_tab;
+
+	if (!ir_dev)
+		return;
 
 	IR_dprintk(1, "Freed keycode table\n");
 
+	rc_tab = &ir_dev->rc_tab;
 	rc_tab->size = 0;
 	kfree(rc_tab->scan);
 	rc_tab->scan = NULL;
-}
-EXPORT_SYMBOL_GPL(ir_input_free);
 
+	kfree(ir_dev);
+	input_unregister_device(dev);
+}
+EXPORT_SYMBOL_GPL(ir_input_unregister);
+
+int ir_core_debug;    /* ir_debug level (0,1,2) */
+EXPORT_SYMBOL_GPL(ir_core_debug);
+module_param_named(debug, ir_core_debug, int, 0644);
+
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index ba69bee..a28541b 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -99,6 +99,7 @@
 comment "Multimedia drivers"
 
 source "drivers/media/common/Kconfig"
+source "drivers/media/IR/Kconfig"
 
 #
 # Tuner drivers for DVB and V4L
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 09a829d..499b081 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y += common/ video/
+obj-y += common/ IR/ video/
 
 obj-$(CONFIG_VIDEO_DEV) += radio/
 obj-$(CONFIG_DVB_CORE)  += dvb/
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index 169b337..e3ec963 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,8 +1,6 @@
 saa7146-objs    := saa7146_i2c.o saa7146_core.o
 saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
-ir-common-objs  := ir-functions.o ir-keymaps.o ir-keytable.o
 
 obj-y += tuners/
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
 obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
-obj-$(CONFIG_VIDEO_IR) += ir-common.o
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 620f655..7364b96 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -1,7 +1,5 @@
 #include <media/saa7146_vv.h>
 
-#define BOARD_CAN_DO_VBI(dev)   (dev->revision != 0 && dev->vv_data->vbi_minor != -1)
-
 /****************************************************************************/
 /* resource management functions, shamelessly stolen from saa7134 driver */
 
@@ -194,43 +192,24 @@
 
 static int fops_open(struct file *file)
 {
-	unsigned int minor = video_devdata(file)->minor;
-	struct saa7146_dev *h = NULL, *dev = NULL;
-	struct list_head *list;
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_dev *dev = video_drvdata(file);
 	struct saa7146_fh *fh = NULL;
 	int result = 0;
 
-	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	enum v4l2_buf_type type;
 
-	DEB_EE(("file:%p, minor:%d\n", file, minor));
+	DEB_EE(("file:%p, dev:%s\n", file, video_device_node_name(vdev)));
 
 	if (mutex_lock_interruptible(&saa7146_devices_lock))
 		return -ERESTARTSYS;
 
-	list_for_each(list,&saa7146_devices) {
-		h = list_entry(list, struct saa7146_dev, item);
-		if( NULL == h->vv_data ) {
-			DEB_D(("device %p has not registered video devices.\n",h));
-			continue;
-		}
-		DEB_D(("trying: %p @ major %d,%d\n",h,h->vv_data->video_minor,h->vv_data->vbi_minor));
-
-		if (h->vv_data->video_minor == minor) {
-			dev = h;
-		}
-		if (h->vv_data->vbi_minor == minor) {
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-			dev = h;
-		}
-	}
-	if (NULL == dev) {
-		DEB_S(("no such video device.\n"));
-		result = -ENODEV;
-		goto out;
-	}
-
 	DEB_D(("using: %p\n",dev));
 
+	type = vdev->vfl_type == VFL_TYPE_GRABBER
+	     ? V4L2_BUF_TYPE_VIDEO_CAPTURE
+	     : V4L2_BUF_TYPE_VBI_CAPTURE;
+
 	/* check if an extension is registered */
 	if( NULL == dev->ext ) {
 		DEB_S(("no extension registered for this device.\n"));
@@ -474,9 +453,6 @@
 	   configuration data) */
 	dev->ext_vv_data = ext_vv;
 
-	vv->video_minor = -1;
-	vv->vbi_minor = -1;
-
 	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
 	if( NULL == vv->d_clipping.cpu_addr ) {
 		ERR(("out of memory. aborting.\n"));
@@ -515,7 +491,6 @@
 int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 			    char *name, int type)
 {
-	struct saa7146_vv *vv = dev->vv_data;
 	struct video_device *vfd;
 	int err;
 	int i;
@@ -543,15 +518,8 @@
 		return err;
 	}
 
-	if( VFL_TYPE_GRABBER == type ) {
-		vv->video_minor = vfd->minor;
-		INFO(("%s: registered device video%d [v4l2]\n",
-			dev->name, vfd->num));
-	} else {
-		vv->vbi_minor = vfd->minor;
-		INFO(("%s: registered device vbi%d [v4l2]\n",
-			dev->name, vfd->num));
-	}
+	INFO(("%s: registered device %s [v4l2]\n",
+		dev->name, video_device_node_name(vfd)));
 
 	*vid = vfd;
 	return 0;
@@ -560,16 +528,8 @@
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
-	struct saa7146_vv *vv = dev->vv_data;
-
 	DEB_EE(("dev:%p\n",dev));
 
-	if ((*vid)->vfl_type == VFL_TYPE_GRABBER) {
-		vv->video_minor = -1;
-	} else {
-		vv->vbi_minor = -1;
-	}
-
 	video_unregister_device(*vid);
 	*vid = NULL;
 
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 53e3f2a..f0f483a 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -589,7 +589,7 @@
 	snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
 		"pci-%s/ir0", pci_name(dm1105->pdev));
 
-	err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes);
+	err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type);
 	if (err < 0) {
 		input_free_device(input_dev);
 		return err;
@@ -611,20 +611,14 @@
 
 	INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
 
-	err = input_register_device(input_dev);
-	if (err) {
-		ir_input_free(input_dev);
-		input_free_device(input_dev);
-		return err;
-	}
+	err = ir_input_register(input_dev, ir_codes);
 
-	return 0;
+	return err;
 }
 
 void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
 {
-	ir_input_free(dm1105->ir.input_dev);
-	input_unregister_device(dm1105->ir.input_dev);
+	ir_input_unregister(dm1105->ir.input_dev);
 }
 
 static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb)
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 2dee1bf..1b24989 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -265,9 +265,13 @@
 	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
 	select DVB_MT312 if !DVB_FE_CUSTOMISE
 	select DVB_ZL10039 if !DVB_FE_CUSTOMISE
+	select DVB_DS3000 if !DVB_FE_CUSTOMISE
+	select DVB_STB6100 if !DVB_FE_CUSTOMISE
+	select DVB_STV6110 if !DVB_FE_CUSTOMISE
+	select DVB_STV0900 if !DVB_FE_CUSTOMISE
 	help
-	  Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers
-	  and the TeVii S650, S630.
+	  Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
+	  receivers.
 
 config DVB_USB_CINERGY_T2
 	tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
index 8b544fe..495a905 100644
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -20,20 +20,22 @@
 #define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args)
 #define deb_data(args...)   dprintk(dvb_usb_dib0700_debug,0x08,args)
 
-#define REQUEST_I2C_READ     0x2
-#define REQUEST_I2C_WRITE    0x3
-#define REQUEST_POLL_RC      0x4 /* deprecated in firmware v1.20 */
-#define REQUEST_JUMPRAM      0x8
-#define REQUEST_SET_CLOCK    0xB
-#define REQUEST_SET_GPIO     0xC
-#define REQUEST_ENABLE_VIDEO 0xF
+#define REQUEST_SET_USB_XFER_LEN    0x0 /* valid only for firmware version */
+					/* higher than 1.21 */
+#define REQUEST_I2C_READ            0x2
+#define REQUEST_I2C_WRITE           0x3
+#define REQUEST_POLL_RC             0x4 /* deprecated in firmware v1.20 */
+#define REQUEST_JUMPRAM             0x8
+#define REQUEST_SET_CLOCK           0xB
+#define REQUEST_SET_GPIO            0xC
+#define REQUEST_ENABLE_VIDEO        0xF
 	// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
 	// 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
 	// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
-#define REQUEST_SET_RC       0x11
-#define REQUEST_NEW_I2C_READ 0x12
-#define REQUEST_NEW_I2C_WRITE 0x13
-#define REQUEST_GET_VERSION  0x15
+#define REQUEST_SET_RC              0x11
+#define REQUEST_NEW_I2C_READ        0x12
+#define REQUEST_NEW_I2C_WRITE       0x13
+#define REQUEST_GET_VERSION         0x15
 
 struct dib0700_state {
 	u8 channel_state;
@@ -44,6 +46,8 @@
 	u8 is_dib7000pc;
 	u8 fw_use_new_i2c_api;
 	u8 disable_streaming_master_mode;
+    u32 fw_version;
+    u32 nb_packet_buffer_size;
 };
 
 extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
index db7f7f7..0d3c9a9 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -17,6 +17,14 @@
 module_param(dvb_usb_dib0700_ir_proto, int, 0644);
 MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
 
+static int nb_packet_buffer_size = 21;
+module_param(nb_packet_buffer_size, int, 0644);
+MODULE_PARM_DESC(nb_packet_buffer_size,
+	"Set the dib0700 driver data buffer size. This parameter "
+	"corresponds to the number of TS packets. The actual size of "
+	"the data buffer corresponds to this parameter "
+	"multiplied by 188 (default: 21)");
+
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 
@@ -28,10 +36,14 @@
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
 				  b, sizeof(b), USB_CTRL_GET_TIMEOUT);
-	*hwversion  = (b[0] << 24)  | (b[1] << 16)  | (b[2] << 8)  | b[3];
-	*romversion = (b[4] << 24)  | (b[5] << 16)  | (b[6] << 8)  | b[7];
-	*ramversion = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
-	*fwtype     = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
+	if (hwversion != NULL)
+		*hwversion  = (b[0] << 24)  | (b[1] << 16)  | (b[2] << 8)  | b[3];
+	if (romversion != NULL)
+		*romversion = (b[4] << 24)  | (b[5] << 16)  | (b[6] << 8)  | b[7];
+	if (ramversion != NULL)
+		*ramversion = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
+	if (fwtype != NULL)
+		*fwtype     = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15];
 	return ret;
 }
 
@@ -97,6 +109,27 @@
 	return dib0700_ctrl_wr(d,buf,3);
 }
 
+static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
+{
+    struct dib0700_state *st = d->priv;
+    u8 b[3];
+    int ret;
+
+    if (st->fw_version >= 0x10201) {
+	b[0] = REQUEST_SET_USB_XFER_LEN;
+	b[1] = (nb_ts_packets >> 8)&0xff;
+	b[2] = nb_ts_packets & 0xff;
+
+	deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
+
+	ret = dib0700_ctrl_wr(d, b, 3);
+    } else {
+	deb_info("this firmware does not allow to change the USB xfer len\n");
+	ret = -EIO;
+    }
+    return ret;
+}
+
 /*
  * I2C master xfer function (supported in 1.20 firmware)
  */
@@ -328,7 +361,9 @@
 int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
 {
 	struct hexline hx;
-	int pos = 0, ret, act_len;
+	int pos = 0, ret, act_len, i, adap_num;
+	u8 b[16];
+	u32 fw_version;
 
 	u8 buf[260];
 
@@ -364,6 +399,34 @@
 	} else
 		ret = -EIO;
 
+	/* the number of ts packet has to be at least 1 */
+	if (nb_packet_buffer_size < 1)
+		nb_packet_buffer_size = 1;
+
+	/* get the fimware version */
+	usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+				  REQUEST_GET_VERSION,
+				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+				  b, sizeof(b), USB_CTRL_GET_TIMEOUT);
+	fw_version = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
+
+	/* set the buffer size - DVB-USB is allocating URB buffers
+	 * only after the firwmare download was successful */
+	for (i = 0; i < dib0700_device_count; i++) {
+		for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
+				adap_num++) {
+			if (fw_version >= 0x10201)
+				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
+			else {
+				/* for fw version older than 1.20.1,
+				 * the buffersize has to be n times 512 */
+				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
+				if (dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize < 512)
+					dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 512;
+			}
+		}
+	}
+
 	return ret;
 }
 
@@ -371,6 +434,18 @@
 {
 	struct dib0700_state *st = adap->dev->priv;
 	u8 b[4];
+	int ret;
+
+	if ((onoff != 0) && (st->fw_version >= 0x10201)) {
+		/* for firmware later than 1.20.1,
+		 * the USB xfer length can be set  */
+		ret = dib0700_set_usb_xfer_len(adap->dev,
+			st->nb_packet_buffer_size);
+		if (ret < 0) {
+			deb_info("can not set the USB xfer len\n");
+			return ret;
+		}
+	}
 
 	b[0] = REQUEST_ENABLE_VIDEO;
 	b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
@@ -415,9 +490,21 @@
 
 	for (i = 0; i < dib0700_device_count; i++)
 		if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
-					&dev, adapter_nr) == 0)
-		{
+		    &dev, adapter_nr) == 0) {
+			struct dib0700_state *st = dev->priv;
+			u32 hwversion, romversion, fw_version, fwtype;
+
+			dib0700_get_version(dev, &hwversion, &romversion,
+				&fw_version, &fwtype);
+
+			deb_info("Firmware version: %x, %d, 0x%x, %d\n",
+				hwversion, romversion, fw_version, fwtype);
+
+			st->fw_version = fw_version;
+			st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
+
 			dib0700_rc_setup(dev);
+
 			return 0;
 		}
 
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 684146f..44972d0 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -18,6 +18,7 @@
 #include "xc5000.h"
 #include "s5h1411.h"
 #include "dib0070.h"
+#include "dib0090.h"
 #include "lgdt3305.h"
 #include "mxl5007t.h"
 
@@ -130,93 +131,95 @@
 /* MT226x */
 static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
 	{
-		BAND_UHF, // band_caps
+		BAND_UHF,
 
 		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
 		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
+		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
+	    | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
-		1130,  // inv_gain
-		21,  // time_stabiliz
+		1130,
+		21,
 
-		0,  // alpha_level
-		118,  // thlock
+		0,
+		118,
 
-		0,     // wbd_inv
-		3530,  // wbd_ref
-		1,     // wbd_sel
-		0,     // wbd_alpha
+		0,
+		3530,
+		1,
+		0,
 
-		65535,  // agc1_max
-		33770,  // agc1_min
-		65535,  // agc2_max
-		23592,  // agc2_min
+		65535,
+		33770,
+		65535,
+		23592,
 
-		0,    // agc1_pt1
-		62,   // agc1_pt2
-		255,  // agc1_pt3
-		64,   // agc1_slope1
-		64,   // agc1_slope2
-		132,  // agc2_pt1
-		192,  // agc2_pt2
-		80,   // agc2_slope1
-		80,   // agc2_slope2
+		0,
+		62,
+		255,
+		64,
+		64,
+		132,
+		192,
+		80,
+		80,
 
-		17,  // alpha_mant
-		27,  // alpha_exp
-		23,  // beta_mant
-		51,  // beta_exp
+		17,
+		27,
+		23,
+		51,
 
-		1,  // perform_agc_softsplit
+		1,
 	}, {
-		BAND_VHF | BAND_LBAND, // band_caps
+		BAND_VHF | BAND_LBAND,
 
 		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
 		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
+	    | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
 
-		2372, // inv_gain
-		21,   // time_stabiliz
+		2372,
+		21,
 
-		0,    // alpha_level
-		118,  // thlock
+		0,
+		118,
 
-		0,    // wbd_inv
-		3530, // wbd_ref
-		1,     // wbd_sel
-		0,    // wbd_alpha
+		0,
+		3530,
+		1,
+		0,
 
-		65535, // agc1_max
-		0,     // agc1_min
-		65535, // agc2_max
-		23592, // agc2_min
+		65535,
+		0,
+		65535,
+		23592,
 
-		0,    // agc1_pt1
-		128,  // agc1_pt2
-		128,  // agc1_pt3
-		128,  // agc1_slope1
-		0,    // agc1_slope2
-		128,  // agc2_pt1
-		253,  // agc2_pt2
-		81,   // agc2_slope1
-		0,    // agc2_slope2
+		0,
+		128,
+		128,
+		128,
+		0,
+		128,
+		253,
+		81,
+		0,
 
-		17,  // alpha_mant
-		27,  // alpha_exp
-		23,  // beta_mant
-		51,  // beta_exp
+		17,
+		27,
+		23,
+		51,
 
-		1,  // perform_agc_softsplit
+		1,
 	}
 };
 
 static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
-	60000, 30000, // internal, sampling
-	1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
-	0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
-	(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
-	0, // ifreq
-	20452225, // timf
+	60000, 30000,
+	1, 8, 3, 1, 0,
+	0, 0, 1, 1, 2,
+	(3 << 14) | (1 << 12) | (524 << 0),
+	0,
+	20452225,
 };
 
 static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
@@ -605,17 +608,17 @@
 		}
 		break;
 	default:
-		if (actlen != sizeof(buf)) {
-			/* We didn't get back the 6 byte message we expected */
-			err("Unexpected RC response size [%d]", actlen);
-			return -1;
-		}
+	if (actlen != sizeof(buf)) {
+		/* We didn't get back the 6 byte message we expected */
+		err("Unexpected RC response size [%d]", actlen);
+		return -1;
+	}
 
-		poll_reply.report_id  = buf[0];
-		poll_reply.data_state = buf[1];
+	poll_reply.report_id  = buf[0];
+	poll_reply.data_state = buf[1];
 		poll_reply.system     = (buf[2] << 8) | buf[3];
-		poll_reply.data       = buf[4];
-		poll_reply.not_data   = buf[5];
+	poll_reply.data       = buf[4];
+	poll_reply.not_data   = buf[5];
 
 		break;
 	}
@@ -632,7 +635,7 @@
 	/* Find the key in the map */
 	for (i = 0; i < d->props.rc_key_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
-		    rc5_data(&keymap[i]) == poll_reply.data) {
+			rc5_data(&keymap[i]) == poll_reply.data) {
 			*event = keymap[i].event;
 			found = 1;
 			break;
@@ -641,8 +644,8 @@
 
 	if (found == 0) {
 		err("Unknown remote controller key: %04x %02x %02x",
-		    poll_reply.system,
-		    poll_reply.data, poll_reply.not_data);
+			poll_reply.system,
+			poll_reply.data, poll_reply.not_data);
 		d->last_event = 0;
 		return 0;
 	}
@@ -933,47 +936,48 @@
 
 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
 static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
-	BAND_UHF | BAND_VHF,       // band_caps
+	BAND_UHF | BAND_VHF,
 
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
 	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
 
-	712,  // inv_gain
-	41,  // time_stabiliz
+	712,
+	41,
 
-	0,  // alpha_level
-	118,  // thlock
+	0,
+	118,
 
-	0,     // wbd_inv
-	4095,  // wbd_ref
-	0,     // wbd_sel
-	0,     // wbd_alpha
+	0,
+	4095,
+	0,
+	0,
 
-	42598,  // agc1_max
-	17694,  // agc1_min
-	45875,  // agc2_max
-	2621,  // agc2_min
-	0,  // agc1_pt1
-	76,  // agc1_pt2
-	139,  // agc1_pt3
-	52,  // agc1_slope1
-	59,  // agc1_slope2
-	107,  // agc2_pt1
-	172,  // agc2_pt2
-	57,  // agc2_slope1
-	70,  // agc2_slope2
+	42598,
+	17694,
+	45875,
+	2621,
+	0,
+	76,
+	139,
+	52,
+	59,
+	107,
+	172,
+	57,
+	70,
 
-	21,  // alpha_mant
-	25,  // alpha_exp
-	28,  // beta_mant
-	48,  // beta_exp
+	21,
+	25,
+	28,
+	48,
 
-	1,  // perform_agc_softsplit
-	{  0,     // split_min
-	   107,   // split_max
-	   51800, // global_split_min
-	   24700  // global_split_max
+	1,
+	{  0,
+	   107,
+	   51800,
+	   24700
 	},
 };
 
@@ -982,54 +986,55 @@
 
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
 	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
+	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
 
-	712, // inv_gain
-	41,  // time_stabiliz
+	712,
+	41,
 
-	0,   // alpha_level
-	118, // thlock
+	0,
+	118,
 
-	0,    // wbd_inv
-	4095, // wbd_ref
-	0,    // wbd_sel
-	0,    // wbd_alpha
+	0,
+	4095,
+	0,
+	0,
 
-	42598, // agc1_max
-	16384, // agc1_min
-	42598, // agc2_max
-	    0, // agc2_min
+	42598,
+	16384,
+	42598,
+	    0,
 
-	  0,   // agc1_pt1
-	137,   // agc1_pt2
-	255,   // agc1_pt3
+	  0,
+	137,
+	255,
 
-	  0,   // agc1_slope1
-	255,   // agc1_slope2
+	  0,
+	255,
 
-	0,     // agc2_pt1
-	0,     // agc2_pt2
+	0,
+	0,
 
-	 0,    // agc2_slope1
-	41,    // agc2_slope2
+	 0,
+	41,
 
-	15, // alpha_mant
-	25, // alpha_exp
+	15,
+	25,
 
-	28, // beta_mant
-	48, // beta_exp
+	28,
+	48,
 
-	0, // perform_agc_softsplit
+	0,
 };
 
 static struct dibx000_bandwidth_config stk7700p_pll_config = {
-	60000, 30000, // internal, sampling
-	1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
-	0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
-	(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
-	60258167, // ifreq
-	20452225, // timf
-	30000000, // xtal
+	60000, 30000,
+	1, 8, 3, 1, 0,
+	0, 0, 1, 1, 0,
+	(3 << 14) | (1 << 12) | (524 << 0),
+	60258167,
+	20452225,
+	30000000,
 };
 
 static struct dib7000m_config stk7700p_dib7000m_config = {
@@ -1115,41 +1120,42 @@
 	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
 	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), // setup
+	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
-	600, // inv_gain
-	10,  // time_stabiliz
+	600,
+	10,
 
-	0,  // alpha_level
-	118,  // thlock
+	0,
+	118,
 
-	0,     // wbd_inv
-	3530,  // wbd_ref
-	1,     // wbd_sel
-	5,     // wbd_alpha
+	0,
+	3530,
+	1,
+	5,
 
-	65535,  // agc1_max
-		0,  // agc1_min
+	65535,
+		0,
 
-	65535,  // agc2_max
-	0,      // agc2_min
+	65535,
+	0,
 
-	0,      // agc1_pt1
-	40,     // agc1_pt2
-	183,    // agc1_pt3
-	206,    // agc1_slope1
-	255,    // agc1_slope2
-	72,     // agc2_pt1
-	152,    // agc2_pt2
-	88,     // agc2_slope1
-	90,     // agc2_slope2
+	0,
+	40,
+	183,
+	206,
+	255,
+	72,
+	152,
+	88,
+	90,
 
-	17,  // alpha_mant
-	27,  // alpha_exp
-	23,  // beta_mant
-	51,  // beta_exp
+	17,
+	27,
+	23,
+	51,
 
-	0,  // perform_agc_softsplit
+	0,
 };
 
 static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
@@ -1276,13 +1282,13 @@
 }
 
 static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
-	60000, 15000, // internal, sampling
-	1, 20, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
-	0, 0, 1, 1, 2, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
-	(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
-	(0 << 25) | 0, // ifreq = 0.000000 MHz
-	20452225, // timf
-	12000000, // xtal_hz
+	60000, 15000,
+	1, 20, 3, 1, 0,
+	0, 0, 1, 1, 2,
+	(3 << 14) | (1 << 12) | (524 << 0),
+	(0 << 25) | 0,
+	20452225,
+	12000000,
 };
 
 static struct dib7000p_config dib7070p_dib7000p_config = {
@@ -1476,12 +1482,12 @@
 	}
 };
 
-static int dib807x_tuner_reset(struct dvb_frontend *fe, int onoff)
+static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
 {
 	return dib8000_set_gpio(fe, 5, 0, !onoff);
 }
 
-static int dib807x_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
 {
 	return dib8000_set_gpio(fe, 0, 0, onoff);
 }
@@ -1494,8 +1500,8 @@
 static struct dib0070_config dib807x_dib0070_config[2] = {
 	{
 		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib807x_tuner_reset,
-		.sleep = dib807x_tuner_sleep,
+		.reset = dib80xx_tuner_reset,
+		.sleep = dib80xx_tuner_sleep,
 		.clock_khz = 12000,
 		.clock_pad_drive = 4,
 		.vga_filter = 1,
@@ -1508,8 +1514,8 @@
 		.freq_offset_khz_vhf = -100,
 	}, {
 		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib807x_tuner_reset,
-		.sleep = dib807x_tuner_sleep,
+		.reset = dib80xx_tuner_reset,
+		.sleep = dib80xx_tuner_sleep,
 		.clock_khz = 12000,
 		.clock_pad_drive = 2,
 		.vga_filter = 1,
@@ -1566,12 +1572,14 @@
 	return 0;
 }
 
-static int stk807x_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
+static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
+	u16 pid, int onoff)
 {
     return dib8000_pid_filter(adapter->fe, index, pid, onoff);
 }
 
-static int stk807x_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
+static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
+	int onoff)
 {
     return dib8000_pid_filter_ctrl(adapter->fe, onoff);
 }
@@ -1624,7 +1632,7 @@
 	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
 
 	/* initialize IC 0 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x80);
+	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80);
 
 	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
 			      &dib807x_dib8000_config[0]);
@@ -1635,7 +1643,7 @@
 static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
 {
 	/* initialize IC 1 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x82);
+	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82);
 
 	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
 			      &dib807x_dib8000_config[1]);
@@ -1643,6 +1651,245 @@
 	return adap->fe == NULL ? -ENODEV : 0;
 }
 
+/* STK8096GP */
+struct dibx000_agc_config dib8090_agc_config[2] = {
+    {
+	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
+     * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+     * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+
+	787,
+	10,
+
+	0,
+	118,
+
+	0,
+	3530,
+	1,
+	5,
+
+	65535,
+	0,
+
+	65535,
+	0,
+
+	0,
+	32,
+	114,
+	143,
+	144,
+	114,
+	227,
+	116,
+	117,
+
+	28,
+	26,
+	31,
+	51,
+
+	0,
+    },
+    {
+	BAND_CBAND,
+	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
+     * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+     * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+
+	787,
+	10,
+
+	0,
+	118,
+
+	0,
+	3530,
+	1,
+	5,
+
+	0,
+	0,
+
+	65535,
+	0,
+
+	0,
+	32,
+	114,
+	143,
+	144,
+	114,
+	227,
+	116,
+	117,
+
+	28,
+	26,
+	31,
+	51,
+
+	0,
+    }
+};
+
+static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
+    54000, 13500,
+    1, 18, 3, 1, 0,
+    0, 0, 1, 1, 2,
+    (3 << 14) | (1 << 12) | (599 << 0),
+    (0 << 25) | 0,
+    20199727,
+    12000000,
+};
+
+static int dib8090_get_adc_power(struct dvb_frontend *fe)
+{
+    return dib8000_get_adc_power(fe, 1);
+}
+
+static struct dib8000_config dib809x_dib8000_config = {
+    .output_mpeg2_in_188_bytes = 1,
+
+    .agc_config_count = 2,
+    .agc = dib8090_agc_config,
+    .agc_control = dib0090_dcc_freq,
+    .pll = &dib8090_pll_config_12mhz,
+    .tuner_is_baseband = 1,
+
+    .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
+    .gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
+    .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
+
+    .hostbus_diversity = 1,
+    .div_cfg = 0x31,
+    .output_mode = OUTMODE_MPEG2_FIFO,
+    .drives = 0x2d98,
+    .diversity_delay = 144,
+    .refclksel = 3,
+};
+
+static struct dib0090_config dib809x_dib0090_config = {
+    .io.pll_bypass = 1,
+    .io.pll_range = 1,
+    .io.pll_prediv = 1,
+    .io.pll_loopdiv = 20,
+    .io.adc_clock_ratio = 8,
+    .io.pll_int_loop_filt = 0,
+    .io.clock_khz = 12000,
+    .reset = dib80xx_tuner_reset,
+    .sleep = dib80xx_tuner_sleep,
+    .clkouttobamse = 1,
+    .analog_output = 1,
+    .i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
+    .wbd_vhf_offset = 100,
+    .wbd_cband_offset = 450,
+    .use_pwm_agc = 1,
+    .clkoutdrive = 1,
+    .get_adc_power = dib8090_get_adc_power,
+	.freq_offset_khz_uhf = 0,
+	.freq_offset_khz_vhf = -143,
+};
+
+static int dib8096_set_param_override(struct dvb_frontend *fe,
+		struct dvb_frontend_parameters *fep)
+{
+    struct dvb_usb_adapter *adap = fe->dvb->priv;
+    struct dib0700_adapter_state *state = adap->priv;
+    u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+    u16 offset;
+    int ret = 0;
+    enum frontend_tune_state tune_state = CT_SHUTDOWN;
+    u16 ltgain, rf_gain_limit;
+
+    ret = state->set_param_save(fe, fep);
+    if (ret < 0)
+	return ret;
+
+    switch (band) {
+    case BAND_VHF:
+	    offset = 100;
+	    break;
+    case BAND_UHF:
+	    offset = 550;
+	    break;
+    default:
+	    offset = 0;
+	    break;
+    }
+    offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
+    dib8000_set_wbd_ref(fe, offset);
+
+
+    if (band == BAND_CBAND) {
+	deb_info("tuning in CBAND - soft-AGC startup\n");
+	/* TODO specific wbd target for dib0090 - needed for startup ? */
+	dib0090_set_tune_state(fe, CT_AGC_START);
+	do {
+		ret = dib0090_gain_control(fe);
+		msleep(ret);
+		tune_state = dib0090_get_tune_state(fe);
+		if (tune_state == CT_AGC_STEP_0)
+			dib8000_set_gpio(fe, 6, 0, 1);
+		else if (tune_state == CT_AGC_STEP_1) {
+			dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
+			if (rf_gain_limit == 0)
+				dib8000_set_gpio(fe, 6, 0, 0);
+		}
+	} while (tune_state < CT_AGC_STOP);
+	dib0090_pwm_gain_reset(fe);
+	dib8000_pwm_agc_reset(fe);
+	dib8000_set_tune_state(fe, CT_DEMOD_START);
+    } else {
+	deb_info("not tuning in CBAND - standard AGC startup\n");
+	dib0090_pwm_gain_reset(fe);
+    }
+
+    return 0;
+}
+
+static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
+{
+    struct dib0700_adapter_state *st = adap->priv;
+    struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+
+    if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+	return -ENODEV;
+
+    st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+    adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+    return 0;
+}
+
+static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	dib0700_ctrl_clock(adap->dev, 72, 1);
+
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
+
+	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config);
+
+	return adap->fe == NULL ?  -ENODEV : 0;
+}
 
 /* STK7070PD */
 static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
@@ -1929,14 +2176,17 @@
 	{ USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_STK7700D) },
 /* 55 */{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_STK7700D_2) },
 	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73A) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73ESE) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV282E) },
+	{ USB_DEVICE(USB_VID_PCTV,	USB_PID_PINNACLE_PCTV73ESE) },
+	{ USB_DEVICE(USB_VID_PCTV,	USB_PID_PINNACLE_PCTV282E) },
 	{ USB_DEVICE(USB_VID_DIBCOM,	USB_PID_DIBCOM_STK7770P) },
 /* 60 */{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_XXS_2) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XPVR) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XP) },
 	{ USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) },
 	{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
+/* 65 */{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73ESE) },
+	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV282E) },
+	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK8096GP) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -2238,11 +2488,11 @@
 				{ NULL },
 			},
 			{   "Pinnacle PCTV 73e SE",
-				{ &dib0700_usb_id_table[57], NULL },
+				{ &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL },
 				{ NULL },
 			},
 			{   "Pinnacle PCTV 282e",
-				{ &dib0700_usb_id_table[58], NULL },
+				{ &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL },
 				{ NULL },
 			},
 		},
@@ -2471,8 +2721,8 @@
 			{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
-				.pid_filter = stk807x_pid_filter,
-				.pid_filter_ctrl = stk807x_pid_filter_ctrl,
+				.pid_filter = stk80xx_pid_filter,
+				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
 				.frontend_attach  = stk807x_frontend_attach,
 				.tuner_attach     = dib807x_tuner_attach,
 
@@ -2510,8 +2760,8 @@
 			{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
-				.pid_filter = stk807x_pid_filter,
-				.pid_filter_ctrl = stk807x_pid_filter_ctrl,
+				.pid_filter = stk80xx_pid_filter,
+				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
 				.frontend_attach  = stk807xpvr_frontend_attach0,
 				.tuner_attach     = dib807x_tuner_attach,
 
@@ -2523,8 +2773,8 @@
 			{
 				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 				.pid_filter_count = 32,
-				.pid_filter = stk807x_pid_filter,
-				.pid_filter_ctrl = stk807x_pid_filter_ctrl,
+				.pid_filter = stk80xx_pid_filter,
+				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
 				.frontend_attach  = stk807xpvr_frontend_attach1,
 				.tuner_attach     = dib807x_tuner_attach,
 
@@ -2547,6 +2797,37 @@
 		.rc_key_map       = dib0700_rc_keys,
 		.rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
 		.rc_query         = dib0700_rc_query
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = stk80xx_pid_filter,
+				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
+				.frontend_attach  = stk809x_frontend_attach,
+				.tuner_attach     = dib809x_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom STK8096GP reference design",
+				{ &dib0700_usb_id_table[67], NULL },
+				{ NULL },
+			},
+		},
+
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = dib0700_rc_keys,
+		.rc_key_map_size  = ARRAY_SIZE(dib0700_rc_keys),
+		.rc_query         = dib0700_rc_query
 	},
 };
 
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index da34979..9143b56 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -142,8 +142,13 @@
 		} else if ((msg[i].flags & I2C_M_RD) == 0) {
 			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
 				break;
-		} else
-			break;
+		} else if (msg[i].addr != 0x50) {
+			/* 0x50 is the address of the eeprom - we need to protect it
+			 * from dibusb's bad i2c implementation: reads without
+			 * writing the offset before are forbidden */
+			if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0)
+				break;
+		}
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -243,6 +248,12 @@
 
 int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
 {
+	if (adap->dev->udev->descriptor.idVendor  == USB_VID_LITEON &&
+			adap->dev->udev->descriptor.idProduct ==
+			USB_PID_LITEON_DVB_T_WARM) {
+		msleep(1000);
+	}
+
 	if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS,  &mod3000p_dib3000p_config)) != NULL ||
 		(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
 		if (adap->priv != NULL) {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index f1602d4..bc3581d 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -47,6 +47,7 @@
 #define USB_VID_MSI_2				0x1462
 #define USB_VID_OPERA1				0x695c
 #define USB_VID_PINNACLE			0x2304
+#define USB_VID_PCTV				0x2013
 #define USB_VID_PIXELVIEW			0x1554
 #define USB_VID_TECHNOTREND			0x0b48
 #define USB_VID_TERRATEC			0x0ccd
@@ -101,6 +102,7 @@
 #define USB_PID_DIBCOM_STK7070PD			0x1ebe
 #define USB_PID_DIBCOM_STK807XP				0x1f90
 #define USB_PID_DIBCOM_STK807XPVR			0x1f98
+#define USB_PID_DIBCOM_STK8096GP                        0x1fa0
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
 #define USB_PID_DIBCOM_STK7770P				0x1e80
 #define USB_PID_DPOSH_M9206_COLD			0x9206
@@ -211,6 +213,7 @@
 #define USB_PID_PINNACLE_PCTV801E_SE			0x023b
 #define USB_PID_PINNACLE_PCTV73A			0x0243
 #define USB_PID_PINNACLE_PCTV73ESE			0x0245
+#define USB_PID_PINNACLE_PCTV74E			0x0246
 #define USB_PID_PINNACLE_PCTV282E			0x0248
 #define USB_PID_PIXELVIEW_SBTVD				0x5010
 #define USB_PID_PCTV_200E				0x020e
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 5bb9479..64132c0 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -20,6 +20,11 @@
 #include "tda1002x.h"
 #include "mt312.h"
 #include "zl10039.h"
+#include "ds3000.h"
+#include "stv0900.h"
+#include "stv6110.h"
+#include "stb6100.h"
+#include "stb6100_proc.h"
 
 #ifndef USB_PID_DW2102
 #define USB_PID_DW2102 0x2102
@@ -37,12 +42,20 @@
 #define USB_PID_CINERGY_S 0x0064
 #endif
 
+#ifndef USB_PID_TEVII_S630
+#define USB_PID_TEVII_S630 0xd630
+#endif
+
 #ifndef USB_PID_TEVII_S650
 #define USB_PID_TEVII_S650 0xd650
 #endif
 
-#ifndef USB_PID_TEVII_S630
-#define USB_PID_TEVII_S630 0xd630
+#ifndef USB_PID_TEVII_S660
+#define USB_PID_TEVII_S660 0xd660
+#endif
+
+#ifndef USB_PID_PROF_1100
+#define USB_PID_PROF_1100 0xb012
 #endif
 
 #define DW210X_READ_MSG 0
@@ -55,6 +68,10 @@
 #define DW2102_VOLTAGE_CTRL (0x1800)
 #define DW2102_RC_QUERY (0x1a00)
 
+#define	err_str "did not find the firmware file. (%s) " \
+		"Please see linux/Documentation/dvb/ for more details " \
+		"on firmware-problems."
+
 struct dvb_usb_rc_keys_table {
 	struct dvb_usb_rc_key *rc_keys;
 	int rc_keys_size;
@@ -71,6 +88,12 @@
 module_param_named(keymap, ir_keymap, int, 0644);
 MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs  ...");
 
+/* demod probe */
+static int demod_probe = 1;
+module_param_named(demod, demod_probe, int, 0644);
+MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
+			"4=stv0903+stb6100(or-able)).");
+
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
@@ -183,7 +206,7 @@
 	switch (num) {
 	case 2:
 		/* read si2109 register by number */
-		buf6[0] = 0xd0;
+		buf6[0] = msg[0].addr << 1;
 		buf6[1] = msg[0].len;
 		buf6[2] = msg[0].buf[0];
 		ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@@ -198,7 +221,7 @@
 		switch (msg[0].addr) {
 		case 0x68:
 			/* write to si2109 register */
-			buf6[0] = 0xd0;
+			buf6[0] = msg[0].addr << 1;
 			buf6[1] = msg[0].len;
 			memcpy(buf6 + 2, msg[0].buf, msg[0].len);
 			ret = dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
@@ -239,7 +262,7 @@
 		/* read */
 		/* first write first register number */
 		u8 ibuf[msg[1].len + 2], obuf[3];
-		obuf[0] = 0xd0;
+		obuf[0] = msg[0].addr << 1;
 		obuf[1] = msg[0].len;
 		obuf[2] = msg[0].buf[0];
 		ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@@ -256,7 +279,7 @@
 		case 0x68: {
 			/* write to register */
 			u8 obuf[msg[0].len + 2];
-			obuf[0] = 0xd0;
+			obuf[0] = msg[0].addr << 1;
 			obuf[1] = msg[0].len;
 			memcpy(obuf + 2, msg[0].buf, msg[0].len);
 			ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@@ -266,7 +289,7 @@
 		case 0x61: {
 			/* write to tuner */
 			u8 obuf[msg[0].len + 2];
-			obuf[0] = 0xc2;
+			obuf[0] = msg[0].addr << 1;
 			obuf[1] = msg[0].len;
 			memcpy(obuf + 2, msg[0].buf, msg[0].len);
 			ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
@@ -301,78 +324,78 @@
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int ret = 0;
-	int len, i;
+	int len, i, j;
 
 	if (!d)
 		return -ENODEV;
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
 
-	switch (num) {
-	case 2: {
-		/* read */
-		/* first write first register number */
-		u8 ibuf[msg[1].len + 2], obuf[3];
-		obuf[0] = 0xaa;
-		obuf[1] = msg[0].len;
-		obuf[2] = msg[0].buf[0];
-		ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
-				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-		/* second read registers */
-		ret = dw210x_op_rw(d->udev, 0xc3, 0xab , 0,
-				ibuf, msg[1].len + 2, DW210X_READ_MSG);
-		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
-
-		break;
-	}
-	case 1:
-		switch (msg[0].addr) {
-		case 0x55: {
-			if (msg[0].buf[0] == 0xf7) {
-				/* firmware */
-				/* Write in small blocks */
-				u8 obuf[19];
-				obuf[0] = 0xaa;
-				obuf[1] = 0x11;
-				obuf[2] = 0xf7;
-				len = msg[0].len - 1;
-				i = 1;
-				do {
-					memcpy(obuf + 3, msg[0].buf + i, (len > 16 ? 16 : len));
-					ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
-						obuf, (len > 16 ? 16 : len) + 3, DW210X_WRITE_MSG);
-					i += 16;
-					len -= 16;
-				} while (len > 0);
-			} else {
-				/* write to register */
-				u8 obuf[msg[0].len + 2];
-				obuf[0] = 0xaa;
-				obuf[1] = msg[0].len;
-				memcpy(obuf + 2, msg[0].buf, msg[0].len);
-				ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
-						obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-			}
-			break;
-		}
+	for (j = 0; j < num; j++) {
+		switch (msg[j].addr) {
 		case(DW2102_RC_QUERY): {
 			u8 ibuf[2];
 			ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
 					ibuf, 2, DW210X_READ_MSG);
-			memcpy(msg[0].buf, ibuf , 2);
+			memcpy(msg[j].buf, ibuf , 2);
 			break;
 		}
 		case(DW2102_VOLTAGE_CTRL): {
 			u8 obuf[2];
 			obuf[0] = 0x30;
-			obuf[1] = msg[0].buf[0];
+			obuf[1] = msg[j].buf[0];
 			ret = dw210x_op_rw(d->udev, 0xb2, 0, 0,
 					obuf, 2, DW210X_WRITE_MSG);
 			break;
 		}
+		/*case 0x55: cx24116
+		case 0x6a: stv0903
+		case 0x68: ds3000, stv0903
+		case 0x60: ts2020, stv6110, stb6100 */
+		default: {
+			if (msg[j].flags == I2C_M_RD) {
+				/* read registers */
+				u8  ibuf[msg[j].len + 2];
+				ret = dw210x_op_rw(d->udev, 0xc3,
+						(msg[j].addr << 1) + 1, 0,
+						ibuf, msg[j].len + 2,
+						DW210X_READ_MSG);
+				memcpy(msg[j].buf, ibuf + 2, msg[j].len);
+			mdelay(10);
+			} else if (((msg[j].buf[0] == 0xb0) &&
+						(msg[j].addr == 0x68)) ||
+						((msg[j].buf[0] == 0xf7) &&
+						(msg[j].addr == 0x55))) {
+				/* write firmware */
+				u8 obuf[19];
+				obuf[0] = msg[j].addr << 1;
+				obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
+				obuf[2] = msg[j].buf[0];
+				len = msg[j].len - 1;
+				i = 1;
+				do {
+					memcpy(obuf + 3, msg[j].buf + i,
+							(len > 16 ? 16 : len));
+					ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+						obuf, (len > 16 ? 16 : len) + 3,
+						DW210X_WRITE_MSG);
+					i += 16;
+					len -= 16;
+				} while (len > 0);
+			} else {
+				/* write registers */
+				u8 obuf[msg[j].len + 2];
+				obuf[0] = msg[j].addr << 1;
+				obuf[1] = msg[j].len;
+				memcpy(obuf + 2, msg[j].buf, msg[j].len);
+				ret = dw210x_op_rw(d->udev, 0xc2, 0, 0,
+						obuf, msg[j].len + 2,
+						DW210X_WRITE_MSG);
+			}
+			break;
+		}
 		}
 
-		break;
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -442,63 +465,85 @@
 	return num;
 }
 
-static int s630_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 								int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int ret = 0;
+	int len, i, j;
 
 	if (!d)
 		return -ENODEV;
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
 
-	switch (num) {
-	case 2: { /* read */
-		u8 ibuf[msg[1].len], obuf[3];
-		obuf[0] = msg[1].len;
-		obuf[1] = (msg[0].addr << 1);
-		obuf[2] = msg[0].buf[0];
-
-		ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
-					obuf, 3, DW210X_WRITE_MSG);
-		msleep(5);
-		ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
-					ibuf, msg[1].len, DW210X_READ_MSG);
-		memcpy(msg[1].buf, ibuf, msg[1].len);
-		break;
-	}
-	case 1:
-		switch (msg[0].addr) {
-		case 0x60:
-		case 0x0e: {
-			/* write to zl10313, zl10039 register, */
-			u8 obuf[msg[0].len + 2];
-			obuf[0] = msg[0].len + 1;
-			obuf[1] = (msg[0].addr << 1);
-			memcpy(obuf + 2, msg[0].buf, msg[0].len);
-			ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
-					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-			break;
-		}
+	for (j = 0; j < num; j++) {
+		switch (msg[j].addr) {
 		case (DW2102_RC_QUERY): {
 			u8 ibuf[4];
 			ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
 					ibuf, 4, DW210X_READ_MSG);
-			msg[0].buf[0] = ibuf[3];
+			memcpy(msg[j].buf, ibuf + 1, 2);
 			break;
 		}
 		case (DW2102_VOLTAGE_CTRL): {
 			u8 obuf[2];
-			obuf[0] = 0x03;
-			obuf[1] = msg[0].buf[0];
+			obuf[0] = 3;
+			obuf[1] = msg[j].buf[0];
 			ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
 					obuf, 2, DW210X_WRITE_MSG);
 			break;
 		}
+		/*case 0x55: cx24116
+		case 0x6a: stv0903
+		case 0x68: ds3000, stv0903
+		case 0x60: ts2020, stv6110, stb6100
+		case 0xa0: eeprom */
+		default: {
+			if (msg[j].flags == I2C_M_RD) {
+				/* read registers */
+				u8 ibuf[msg[j].len];
+				ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
+						ibuf, msg[j].len,
+						DW210X_READ_MSG);
+				memcpy(msg[j].buf, ibuf, msg[j].len);
+				break;
+			} else if ((msg[j].buf[0] == 0xb0) &&
+						(msg[j].addr == 0x68)) {
+				/* write firmware */
+				u8 obuf[19];
+				obuf[0] = (msg[j].len > 16 ?
+						18 : msg[j].len + 1);
+				obuf[1] = msg[j].addr << 1;
+				obuf[2] = msg[j].buf[0];
+				len = msg[j].len - 1;
+				i = 1;
+				do {
+					memcpy(obuf + 3, msg[j].buf + i,
+							(len > 16 ? 16 : len));
+					ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
+						obuf, (len > 16 ? 16 : len) + 3,
+						DW210X_WRITE_MSG);
+					i += 16;
+					len -= 16;
+				} while (len > 0);
+			} else {
+				/* write registers */
+				u8 obuf[msg[j].len + 2];
+				obuf[0] = msg[j].len + 1;
+				obuf[1] = (msg[j].addr << 1);
+				memcpy(obuf + 2, msg[j].buf, msg[j].len);
+				ret = dw210x_op_rw(d->udev,
+						(num > 1 ? 0x90 : 0x80), 0, 0,
+						obuf, msg[j].len + 2,
+						DW210X_WRITE_MSG);
+				break;
+			}
+			break;
+		}
 		}
 
-		break;
+		msleep(3);
 	}
 
 	mutex_unlock(&d->i2c_mutex);
@@ -535,8 +580,8 @@
 	.functionality = dw210x_i2c_func,
 };
 
-static struct i2c_algorithm s630_i2c_algo = {
-	.master_xfer = s630_i2c_transfer,
+static struct i2c_algorithm s6x0_i2c_algo = {
+	.master_xfer = s6x0_i2c_transfer,
 	.functionality = dw210x_i2c_func,
 };
 
@@ -564,25 +609,34 @@
 	return 0;
 };
 
-static int s630_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
 {
 	int i, ret;
-	u8 buf[3], eeprom[256], eepromline[16];
+	u8 ibuf[] = { 0 }, obuf[] = { 0 };
+	u8 eeprom[256], eepromline[16];
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0xa0 >> 1,
+			.flags = 0,
+			.buf = obuf,
+			.len = 1,
+		}, {
+			.addr = 0xa0 >> 1,
+			.flags = I2C_M_RD,
+			.buf = ibuf,
+			.len = 1,
+		}
+	};
 
 	for (i = 0; i < 256; i++) {
-		buf[0] = 1;
-		buf[1] = 0xa0;
-		buf[2] = i;
-		ret = dw210x_op_rw(d->udev, 0x90, 0, 0,
-					buf, 3, DW210X_WRITE_MSG);
-		ret = dw210x_op_rw(d->udev, 0x91, 0, 0,
-					buf, 1, DW210X_READ_MSG);
-		if (ret < 0) {
+		obuf[0] = i;
+		ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
+		if (ret != 2) {
 			err("read eeprom failed.");
 			return -1;
 		} else {
-			eepromline[i % 16] = buf[0];
-			eeprom[i] = buf[0];
+			eepromline[i % 16] = ibuf[0];
+			eeprom[i] = ibuf[0];
 		}
 
 		if ((i % 16) == 15) {
@@ -644,19 +698,104 @@
 	.demod_address = 0x0e,
 };
 
+static struct ds3000_config dw2104_ds3000_config = {
+	.demod_address = 0x68,
+};
+
+static struct stv0900_config dw2104a_stv0900_config = {
+	.demod_address = 0x6a,
+	.demod_mode = 0,
+	.xtal = 27000000,
+	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+	.diseqc_mode = 2,/* 2/3 PWM */
+	.tun1_maddress = 0,/* 0x60 */
+	.tun1_adc = 0,/* 2 Vpp */
+	.path1_mode = 3,
+};
+
+static struct stb6100_config dw2104a_stb6100_config = {
+	.tuner_address = 0x60,
+	.refclock = 27000000,
+};
+
+static struct stv0900_config dw2104_stv0900_config = {
+	.demod_address = 0x68,
+	.demod_mode = 0,
+	.xtal = 8000000,
+	.clkmode = 3,
+	.diseqc_mode = 2,
+	.tun1_maddress = 0,
+	.tun1_adc = 1,/* 1 Vpp */
+	.path1_mode = 3,
+};
+
+static struct stv6110_config dw2104_stv6110_config = {
+	.i2c_address = 0x60,
+	.mclk = 16000000,
+	.clk_div = 1,
+};
+
 static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
 {
-	if ((d->fe = dvb_attach(cx24116_attach, &dw2104_config,
-			&d->dev->i2c_adap)) != NULL) {
+	struct dvb_tuner_ops *tuner_ops = NULL;
+
+	if (demod_probe & 4) {
+		d->fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
+				&d->dev->i2c_adap, 0);
+		if (d->fe != NULL) {
+			if (dvb_attach(stb6100_attach, d->fe,
+					&dw2104a_stb6100_config,
+					&d->dev->i2c_adap)) {
+				tuner_ops = &d->fe->ops.tuner_ops;
+				tuner_ops->set_frequency = stb6100_set_freq;
+				tuner_ops->get_frequency = stb6100_get_freq;
+				tuner_ops->set_bandwidth = stb6100_set_bandw;
+				tuner_ops->get_bandwidth = stb6100_get_bandw;
+				d->fe->ops.set_voltage = dw210x_set_voltage;
+				info("Attached STV0900+STB6100!\n");
+				return 0;
+			}
+		}
+	}
+
+	if (demod_probe & 2) {
+		d->fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
+				&d->dev->i2c_adap, 0);
+		if (d->fe != NULL) {
+			if (dvb_attach(stv6110_attach, d->fe,
+					&dw2104_stv6110_config,
+					&d->dev->i2c_adap)) {
+				d->fe->ops.set_voltage = dw210x_set_voltage;
+				info("Attached STV0900+STV6110A!\n");
+				return 0;
+			}
+		}
+	}
+
+	if (demod_probe & 1) {
+		d->fe = dvb_attach(cx24116_attach, &dw2104_config,
+				&d->dev->i2c_adap);
+		if (d->fe != NULL) {
+			d->fe->ops.set_voltage = dw210x_set_voltage;
+			info("Attached cx24116!\n");
+			return 0;
+		}
+	}
+
+	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+			&d->dev->i2c_adap);
+	if (d->fe != NULL) {
 		d->fe->ops.set_voltage = dw210x_set_voltage;
-		info("Attached cx24116!\n");
+		info("Attached DS3000!\n");
 		return 0;
 	}
+
 	return -EIO;
 }
 
 static struct dvb_usb_device_properties dw2102_properties;
 static struct dvb_usb_device_properties dw2104_properties;
+static struct dvb_usb_device_properties s6x0_properties;
 
 static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
 {
@@ -670,14 +809,17 @@
 			return 0;
 		}
 	}
+
 	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
-		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
 		d->fe = dvb_attach(stv0288_attach, &earda_config,
 					&d->dev->i2c_adap);
 		if (d->fe != NULL) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached stv0288!\n");
-			return 0;
+			if (dvb_attach(stb6000_attach, d->fe, 0x61,
+					&d->dev->i2c_adap)) {
+				d->fe->ops.set_voltage = dw210x_set_voltage;
+				info("Attached stv0288!\n");
+				return 0;
+			}
 		}
 	}
 
@@ -705,15 +847,38 @@
 	return -EIO;
 }
 
-static int s630_frontend_attach(struct dvb_usb_adapter *d)
+static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
 {
 	d->fe = dvb_attach(mt312_attach, &zl313_config,
-				&d->dev->i2c_adap);
+			&d->dev->i2c_adap);
+	if (d->fe != NULL) {
+		if (dvb_attach(zl10039_attach, d->fe, 0x60,
+				&d->dev->i2c_adap)) {
+			d->fe->ops.set_voltage = dw210x_set_voltage;
+			info("Attached zl100313+zl10039!\n");
+			return 0;
+		}
+	}
+
+	d->fe = dvb_attach(stv0288_attach, &earda_config,
+			&d->dev->i2c_adap);
+	if (d->fe != NULL) {
+		if (dvb_attach(stb6000_attach, d->fe, 0x61,
+				&d->dev->i2c_adap)) {
+			d->fe->ops.set_voltage = dw210x_set_voltage;
+			info("Attached stv0288+stb6000!\n");
+			return 0;
+		}
+	}
+
+	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
+			&d->dev->i2c_adap);
 	if (d->fe != NULL) {
 		d->fe->ops.set_voltage = dw210x_set_voltage;
-		info("Attached zl10313!\n");
+		info("Attached ds3000+ds2020!\n");
 		return 0;
 	}
+
 	return -EIO;
 }
 
@@ -724,14 +889,6 @@
 	return 0;
 }
 
-static int dw2102_earda_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(stb6000_attach, adap->fe, 0x61,
-		&adap->dev->i2c_adap);
-
-	return 0;
-}
-
 static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -740,14 +897,6 @@
 	return 0;
 }
 
-static int s630_zl10039_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(zl10039_attach, adap->fe, 0x60,
-		&adap->dev->i2c_adap);
-
-	return 0;
-}
-
 static struct dvb_usb_rc_key dw210x_rc_keys[] = {
 	{ 0xf80a, KEY_Q },		/*power*/
 	{ 0xf80c, KEY_M },		/*mute*/
@@ -922,6 +1071,8 @@
 	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
 	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
 	{USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
+	{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
+	{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
 	{ }
 };
 
@@ -935,15 +1086,13 @@
 	u8 reset;
 	u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
 	const struct firmware *fw;
-	const char *filename = "dvb-usb-dw2101.fw";
+	const char *fw_2101 = "dvb-usb-dw2101.fw";
 
 	switch (dev->descriptor.idProduct) {
 	case 0x2101:
-		ret = request_firmware(&fw, filename, &dev->dev);
+		ret = request_firmware(&fw, fw_2101, &dev->dev);
 		if (ret != 0) {
-			err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details "
-			"on firmware-problems.", filename);
+			err(err_str, fw_2101);
 			return ret;
 		}
 		break;
@@ -983,6 +1132,11 @@
 		}
 		/* init registers */
 		switch (dev->descriptor.idProduct) {
+		case USB_PID_PROF_1100:
+			s6x0_properties.rc_key_map = tbs_rc_keys;
+			s6x0_properties.rc_key_map_size =
+					ARRAY_SIZE(tbs_rc_keys);
+			break;
 		case USB_PID_TEVII_S650:
 			dw2104_properties.rc_key_map = tevii_rc_keys;
 			dw2104_properties.rc_key_map_size =
@@ -1021,7 +1175,6 @@
 						DW210X_READ_MSG);
 				if (reset16[2] == 0x11) {
 					dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
-					dw2102_properties.adapter->tuner_attach = &dw2102_earda_tuner_attach;
 					break;
 				}
 			}
@@ -1184,13 +1337,13 @@
 	}
 };
 
-static struct dvb_usb_device_properties s630_properties = {
+static struct dvb_usb_device_properties s6x0_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.firmware = "dvb-usb-s630.fw",
 	.no_reconnect = 1,
 
-	.i2c_algo = &s630_i2c_algo,
+	.i2c_algo = &s6x0_i2c_algo,
 	.rc_key_map = tevii_rc_keys,
 	.rc_key_map_size = ARRAY_SIZE(tevii_rc_keys),
 	.rc_interval = 150,
@@ -1199,12 +1352,12 @@
 	.generic_bulk_ctrl_endpoint = 0x81,
 	.num_adapters = 1,
 	.download_firmware = dw2102_load_firmware,
-	.read_mac_address = s630_read_mac_address,
+	.read_mac_address = s6x0_read_mac_address,
 	.adapter = {
 		{
-			.frontend_attach = s630_frontend_attach,
+			.frontend_attach = s6x0_frontend_attach,
 			.streaming_ctrl = NULL,
-			.tuner_attach = s630_zl10039_tuner_attach,
+			.tuner_attach = NULL,
 			.stream = {
 				.type = USB_BULK,
 				.count = 8,
@@ -1217,12 +1370,20 @@
 			},
 		}
 	},
-	.num_device_descs = 1,
+	.num_device_descs = 3,
 	.devices = {
 		{"TeVii S630 USB",
 			{&dw2102_table[6], NULL},
 			{NULL},
 		},
+		{"Prof 1100 USB ",
+			{&dw2102_table[7], NULL},
+			{NULL},
+		},
+		{"TeVii S660 USB",
+			{&dw2102_table[8], NULL},
+			{NULL},
+		},
 	}
 };
 
@@ -1235,10 +1396,10 @@
 			THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, &dw3101_properties,
 			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &s630_properties,
-			THIS_MODULE, NULL, adapter_nr)) {
+	    0 == dvb_usb_device_init(intf, &s6x0_properties,
+			THIS_MODULE, NULL, adapter_nr))
 		return 0;
-	}
+
 	return -ENODEV;
 }
 
@@ -1269,6 +1430,7 @@
 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
 MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
 				" DVB-C 3101 USB2.0,"
-				" TeVii S600, S630, S650 USB2.0 devices");
+				" TeVii S600, S630, S650, S660 USB2.0,"
+				" Prof 1100 USB2.0 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c
index 9cbbe42..ebb7b9f 100644
--- a/drivers/media/dvb/dvb-usb/friio-fe.c
+++ b/drivers/media/dvb/dvb-usb/friio-fe.c
@@ -134,11 +134,13 @@
 	deb_fe("%s: freq=%d, step=%d\n", __func__, freq,
 	       state->frontend.ops.info.frequency_stepsize);
 	/* freq -> oscilator frequency conversion. */
-	/* freq: 473,000,000 + n*6,000,000 (no 1/7MHz shift to center freq) */
-	/* add 400[1/7 MHZ] = 57.142857MHz.   57MHz for the IF,  */
-	/*                                   1/7MHz for center freq shift */
+	/* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */
 	f = freq / state->frontend.ops.info.frequency_stepsize;
-	f += 400;
+	/* add 399[1/7 MHZ] = 57MHz for the IF  */
+	f += 399;
+	/* add center frequency shift if necessary */
+	if (f % 7 == 0)
+		f++;
 	pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */
 	pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1;
 	pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F;
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
index 20eadf9..7a7f1b2 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -146,8 +146,8 @@
 
 	switch (c->delivery_system) {
 	case SYS_DVBS:
-		/* Only QPSK is supported for DVB-S */
-		if (c->modulation != QPSK) {
+		/* Allow QPSK and 8PSK (even for DVB-S) */
+		if (c->modulation != QPSK && c->modulation != PSK_8) {
 			deb_fe("%s: unsupported modulation selected (%d)\n",
 				__func__, c->modulation);
 			return -EOPNOTSUPP;
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 58aac01..a3b8b697 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -526,6 +526,15 @@
 	  This device is only used inside a SiP called together with a
 	  demodulator for now.
 
+config DVB_TUNER_DIB0090
+	tristate "DiBcom DiB0090 silicon base-band tuner"
+	depends on I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A driver for the silicon baseband tuner DiB0090 from DiBcom.
+	  This device is only used inside a SiP called together with a
+	  demodulator for now.
+
 comment "SEC control devices for DVB-S"
 	depends on DVB_CORE
 
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 8234825..47575cc 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -55,6 +55,7 @@
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
 obj-$(CONFIG_DVB_TDA8261) += tda8261.o
 obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
+obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
index 2dc2723..24268ef 100644
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ b/drivers/media/dvb/frontends/au8522_decoder.c
@@ -62,7 +62,7 @@
    The values are as follows from left to right
    0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
 */
-struct au8522_register_config filter_coef[] = {
+static const struct au8522_register_config filter_coef[] = {
 	{AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
 	{AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
 	{AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
@@ -104,7 +104,7 @@
    0="SIF" 1="ATVRF/ATVRF13"
    Note: the "ATVRF/ATVRF13" mode has never been tested
 */
-struct au8522_register_config lpfilter_coef[] = {
+static const struct au8522_register_config lpfilter_coef[] = {
 	{0x060b, {0x21, 0x0b} },
 	{0x060c, {0xad, 0xad} },
 	{0x060d, {0x70, 0xf0} },
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index 2be17b9..0d12763 100644
--- a/drivers/media/dvb/frontends/dib0070.c
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -49,21 +49,6 @@
 #define DIB0070_P1G  0x03
 #define DIB0070S_P1A 0x02
 
-enum frontend_tune_state {
-	CT_TUNER_START = 10,
-	CT_TUNER_STEP_0,
-	CT_TUNER_STEP_1,
-	CT_TUNER_STEP_2,
-	CT_TUNER_STEP_3,
-	CT_TUNER_STEP_4,
-	CT_TUNER_STEP_5,
-	CT_TUNER_STEP_6,
-	CT_TUNER_STEP_7,
-	CT_TUNER_STOP,
-};
-
-#define FE_CALLBACK_TIME_NEVER 0xffffffff
-
 struct dib0070_state {
 	struct i2c_adapter *i2c;
 	struct dvb_frontend *fe;
@@ -71,10 +56,10 @@
 	u16 wbd_ff_offset;
 	u8 revision;
 
-	enum frontend_tune_state tune_state;
-	u32 current_rf;
+    enum frontend_tune_state tune_state;
+    u32 current_rf;
 
-	/* for the captrim binary search */
+    /* for the captrim binary search */
 	s8 step;
 	u16 adc_diff;
 
@@ -85,7 +70,7 @@
 	const struct dib0070_tuning *current_tune_table_index;
 	const struct dib0070_lna_match *lna_match;
 
-	u8 wbd_gain_current;
+    u8  wbd_gain_current;
 	u16 wbd_offset_3_3[2];
 };
 
@@ -93,8 +78,8 @@
 {
 	u8 b[2];
 	struct i2c_msg msg[2] = {
-		{.addr = state->cfg->i2c_address,.flags = 0,.buf = &reg,.len = 1},
-		{.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2},
+		{ .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+		{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b,  .len = 2 },
 	};
 	if (i2c_transfer(state->i2c, msg, 2) != 2) {
 		printk(KERN_WARNING "DiB0070 I2C read failed\n");
@@ -106,7 +91,7 @@
 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
 {
 	u8 b[3] = { reg, val >> 8, val & 0xff };
-	struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 };
+	struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
 	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
 		printk(KERN_WARNING "DiB0070 I2C write failed\n");
 		return -EREMOTEIO;
@@ -124,30 +109,30 @@
 
 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
 {
-	struct dib0070_state *state = fe->tuner_priv;
-	u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
+    struct dib0070_state *state = fe->tuner_priv;
+    u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
 
-	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000)
-		tmp |= (0 << 14);
-	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000)
-		tmp |= (1 << 14);
-	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000)
-		tmp |= (2 << 14);
-	else
-		tmp |= (3 << 14);
+    if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
+	tmp |= (0 << 14);
+    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
+	tmp |= (1 << 14);
+    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
+	tmp |= (2 << 14);
+    else
+	tmp |= (3 << 14);
 
-	dib0070_write_reg(state, 0x02, tmp);
+    dib0070_write_reg(state, 0x02, tmp);
 
-	/* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
-	if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
-		u16 value = dib0070_read_reg(state, 0x17);
+    /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
+    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
+	u16 value = dib0070_read_reg(state, 0x17);
 
-		dib0070_write_reg(state, 0x17, value & 0xfffc);
-		tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
-		dib0070_write_reg(state, 0x01, tmp | (60 << 9));
+	dib0070_write_reg(state, 0x17, value & 0xfffc);
+	tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
+	dib0070_write_reg(state, 0x01, tmp | (60 << 9));
 
-		dib0070_write_reg(state, 0x17, value);
-	}
+	dib0070_write_reg(state, 0x17, value);
+    }
 	return 0;
 }
 
@@ -160,14 +145,14 @@
 	if (*tune_state == CT_TUNER_STEP_0) {
 
 		dib0070_write_reg(state, 0x0f, 0xed10);
-		dib0070_write_reg(state, 0x17, 0x0034);
+		dib0070_write_reg(state, 0x17,    0x0034);
 
 		dib0070_write_reg(state, 0x18, 0x0032);
 		state->step = state->captrim = state->fcaptrim = 64;
 		state->adc_diff = 3000;
 		ret = 20;
 
-		*tune_state = CT_TUNER_STEP_1;
+	*tune_state = CT_TUNER_STEP_1;
 	} else if (*tune_state == CT_TUNER_STEP_1) {
 		state->step /= 2;
 		dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
@@ -178,7 +163,7 @@
 
 		adc = dib0070_read_reg(state, 0x19);
 
-		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024);
+		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
 
 		if (adc >= 400) {
 			adc -= 400;
@@ -193,6 +178,8 @@
 			state->adc_diff = adc;
 			state->fcaptrim = state->captrim;
 
+
+
 		}
 		state->captrim += (step_sign * state->step);
 
@@ -213,7 +200,7 @@
 static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
 {
 	struct dib0070_state *state = fe->tuner_priv;
-	u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+    u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
 	dprintk("CTRL_LO5: 0x%x", lo5);
 	return dib0070_write_reg(state, 0x15, lo5);
 }
@@ -227,99 +214,99 @@
 		dib0070_write_reg(state, 0x1a, 0x0000);
 	} else {
 		dib0070_write_reg(state, 0x1b, 0x4112);
-		if (state->cfg->vga_filter != 0) {
-			dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
-			dprintk("vga filter register is set to %x", state->cfg->vga_filter);
-		} else
-			dib0070_write_reg(state, 0x1a, 0x0009);
+	if (state->cfg->vga_filter != 0) {
+		dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
+		dprintk("vga filter register is set to %x", state->cfg->vga_filter);
+	} else
+		dib0070_write_reg(state, 0x1a, 0x0009);
 	}
 }
 
 EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
 struct dib0070_tuning {
-	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
-	u8 switch_trim;
-	u8 vco_band;
-	u8 hfdiv;
-	u8 vco_multi;
-	u8 presc;
-	u8 wbdmux;
-	u16 tuner_enable;
+    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+    u8 switch_trim;
+    u8 vco_band;
+    u8 hfdiv;
+    u8 vco_multi;
+    u8 presc;
+    u8 wbdmux;
+    u16 tuner_enable;
 };
 
 struct dib0070_lna_match {
-	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
-	u8 lna_band;
+    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+    u8 lna_band;
 };
 
 static const struct dib0070_tuning dib0070s_tuning_table[] = {
-	{570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800},	/* UHF */
-	{700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800},
-	{863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800},
-	{1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},	/* LBAND */
-	{1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
-	{2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400},
-	{0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000},	/* SBAND */
+    {     570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
+    {     700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
+    {     863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
+    {    1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
+    {    1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+    {    2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+    { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
 };
 
 static const struct dib0070_tuning dib0070_tuning_table[] = {
-	{115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000},	/* FM below 92MHz cannot be tuned */
-	{179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000},	/* VHF */
-	{189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000},
-	{250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000},
-	{569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800},	/* UHF */
-	{699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800},
-	{863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800},
-	{0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400},	/* LBAND or everything higher than UHF */
+    {     115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
+    {     179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
+    {     189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
+    {     250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
+    {     569999, 2, 1, 5,  6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
+    {     699999, 2, 0, 1,  4, 2, 2, 0x4000 | 0x0800 },
+    {     863999, 2, 1, 1,  4, 2, 2, 0x4000 | 0x0800 },
+    { 0xffffffff, 0, 1, 0,  2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
 };
 
 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
-	{180000, 0},		/* VHF */
-	{188000, 1},
-	{196400, 2},
-	{250000, 3},
-	{550000, 0},		/* UHF */
-	{590000, 1},
-	{666000, 3},
-	{864000, 5},
-	{1500000, 0},		/* LBAND or everything higher than UHF */
-	{1600000, 1},
-	{2000000, 3},
-	{0xffffffff, 7},
+    {     180000, 0 }, /* VHF */
+    {     188000, 1 },
+    {     196400, 2 },
+    {     250000, 3 },
+    {     550000, 0 }, /* UHF */
+    {     590000, 1 },
+    {     666000, 3 },
+    {     864000, 5 },
+    {    1500000, 0 }, /* LBAND or everything higher than UHF */
+    {    1600000, 1 },
+    {    2000000, 3 },
+    { 0xffffffff, 7 },
 };
 
 static const struct dib0070_lna_match dib0070_lna[] = {
-	{180000, 0},		/* VHF */
-	{188000, 1},
-	{196400, 2},
-	{250000, 3},
-	{550000, 2},		/* UHF */
-	{650000, 3},
-	{750000, 5},
-	{850000, 6},
-	{864000, 7},
-	{1500000, 0},		/* LBAND or everything higher than UHF */
-	{1600000, 1},
-	{2000000, 3},
-	{0xffffffff, 7},
+    {     180000, 0 }, /* VHF */
+    {     188000, 1 },
+    {     196400, 2 },
+    {     250000, 3 },
+    {     550000, 2 }, /* UHF */
+    {     650000, 3 },
+    {     750000, 5 },
+    {     850000, 6 },
+    {     864000, 7 },
+    {    1500000, 0 }, /* LBAND or everything higher than UHF */
+    {    1600000, 1 },
+    {    2000000, 3 },
+    { 0xffffffff, 7 },
 };
 
-#define LPF	100		// define for the loop filter 100kHz by default 16-07-06
+#define LPF	100
 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
 {
-	struct dib0070_state *state = fe->tuner_priv;
+    struct dib0070_state *state = fe->tuner_priv;
 
-	const struct dib0070_tuning *tune;
-	const struct dib0070_lna_match *lna_match;
+    const struct dib0070_tuning *tune;
+    const struct dib0070_lna_match *lna_match;
 
-	enum frontend_tune_state *tune_state = &state->tune_state;
-	int ret = 10;		/* 1ms is the default delay most of the time */
+    enum frontend_tune_state *tune_state = &state->tune_state;
+    int ret = 10; /* 1ms is the default delay most of the time */
 
-	u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
-	u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
+    u8  band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
+    u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
 
 #ifdef CONFIG_SYS_ISDBT
-	if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
+    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
 		if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
 		     && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
 		    || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
@@ -328,172 +315,180 @@
 			&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
 			freq += 850;
 #endif
+    if (state->current_rf != freq) {
+
+	switch (state->revision) {
+	case DIB0070S_P1A:
+	    tune = dib0070s_tuning_table;
+	    lna_match = dib0070_lna;
+	    break;
+	default:
+	    tune = dib0070_tuning_table;
+	    if (state->cfg->flip_chip)
+		lna_match = dib0070_lna_flip_chip;
+	    else
+		lna_match = dib0070_lna;
+	    break;
+	}
+	while (freq > tune->max_freq) /* find the right one */
+	    tune++;
+	while (freq > lna_match->max_freq) /* find the right one */
+	    lna_match++;
+
+	state->current_tune_table_index = tune;
+	state->lna_match = lna_match;
+    }
+
+    if (*tune_state == CT_TUNER_START) {
+	dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
 	if (state->current_rf != freq) {
+		u8 REFDIV;
+		u32 FBDiv, Rest, FREF, VCOF_kHz;
+		u8 Den;
+
+		state->current_rf = freq;
+		state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
+
+
+		dib0070_write_reg(state, 0x17, 0x30);
+
+
+		VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
+
+		switch (band) {
+		case BAND_VHF:
+			REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
+			break;
+		case BAND_FM:
+			REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
+			break;
+		default:
+			REFDIV = (u8) (state->cfg->clock_khz  / 10000);
+			break;
+		}
+		FREF = state->cfg->clock_khz / REFDIV;
+
+
 
 		switch (state->revision) {
 		case DIB0070S_P1A:
-			tune = dib0070s_tuning_table;
-			lna_match = dib0070_lna;
+			FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
+			Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
 			break;
+
+		case DIB0070_P1G:
+		case DIB0070_P1F:
 		default:
-			tune = dib0070_tuning_table;
-			if (state->cfg->flip_chip)
-				lna_match = dib0070_lna_flip_chip;
-			else
-				lna_match = dib0070_lna;
+			FBDiv = (freq / (FREF / 2));
+			Rest  = 2 * freq - FBDiv * FREF;
 			break;
 		}
-		while (freq > tune->max_freq)	/* find the right one */
-			tune++;
-		while (freq > lna_match->max_freq)	/* find the right one */
-			lna_match++;
 
-		state->current_tune_table_index = tune;
-		state->lna_match = lna_match;
-	}
+		if (Rest < LPF)
+			Rest = 0;
+		else if (Rest < 2 * LPF)
+			Rest = 2 * LPF;
+		else if (Rest > (FREF - LPF)) {
+			Rest = 0;
+			FBDiv += 1;
+		} else if (Rest > (FREF - 2 * LPF))
+			Rest = FREF - 2 * LPF;
+		Rest = (Rest * 6528) / (FREF / 10);
 
-	if (*tune_state == CT_TUNER_START) {
-		dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
-		if (state->current_rf != freq) {
-			u8 REFDIV;
-			u32 FBDiv, Rest, FREF, VCOF_kHz;
-			u8 Den;
-
-			state->current_rf = freq;
-			state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
-
-			dib0070_write_reg(state, 0x17, 0x30);
-
-			VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
-
-			switch (band) {
-			case BAND_VHF:
-				REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
-				break;
-			case BAND_FM:
-				REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
-				break;
-			default:
-				REFDIV = (u8) (state->cfg->clock_khz / 10000);
-				break;
-			}
-			FREF = state->cfg->clock_khz / REFDIV;
-
-			switch (state->revision) {
-			case DIB0070S_P1A:
-				FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
-				Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
-				break;
-
-			case DIB0070_P1G:
-			case DIB0070_P1F:
-			default:
-				FBDiv = (freq / (FREF / 2));
-				Rest = 2 * freq - FBDiv * FREF;
-				break;
-			}
-
-			if (Rest < LPF)
-				Rest = 0;
-			else if (Rest < 2 * LPF)
-				Rest = 2 * LPF;
-			else if (Rest > (FREF - LPF)) {
-				Rest = 0;
-				FBDiv += 1;
-			} else if (Rest > (FREF - 2 * LPF))
-				Rest = FREF - 2 * LPF;
-			Rest = (Rest * 6528) / (FREF / 10);
-
-			Den = 1;
-			if (Rest > 0) {
-				state->lo4 |= (1 << 14) | (1 << 12);
-				Den = 255;
-			}
-
-			dib0070_write_reg(state, 0x11, (u16) FBDiv);
-			dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
-			dib0070_write_reg(state, 0x13, (u16) Rest);
-
-			if (state->revision == DIB0070S_P1A) {
-
-				if (band == BAND_SBAND) {
-					dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
-					dib0070_write_reg(state, 0x1d, 0xFFFF);
-				} else
-					dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
-			}
-
-			dib0070_write_reg(state, 0x20,
-					  0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
-
-			dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
-			dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
-			dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
-			dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
-			dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
-			dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
-
-			*tune_state = CT_TUNER_STEP_0;
-		} else {	/* we are already tuned to this frequency - the configuration is correct  */
-			ret = 50;	/* wakeup time */
-			*tune_state = CT_TUNER_STEP_5;
+		Den = 1;
+		if (Rest > 0) {
+			state->lo4 |= (1 << 14) | (1 << 12);
+			Den = 255;
 		}
-	} else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
 
-		ret = dib0070_captrim(state, tune_state);
 
-	} else if (*tune_state == CT_TUNER_STEP_4) {
-		const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
-		if (tmp != NULL) {
-			while (freq / 1000 > tmp->freq)	/* find the right one */
-				tmp++;
-			dib0070_write_reg(state, 0x0f,
-					  (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state->
-																current_tune_table_index->
-																wbdmux << 0));
-			state->wbd_gain_current = tmp->wbd_gain_val;
-		} else {
+		dib0070_write_reg(state, 0x11, (u16)FBDiv);
+		dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
+		dib0070_write_reg(state, 0x13, (u16) Rest);
+
+		if (state->revision == DIB0070S_P1A) {
+
+			if (band == BAND_SBAND) {
+				dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+				dib0070_write_reg(state, 0x1d, 0xFFFF);
+			} else
+				dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+		}
+
+		dib0070_write_reg(state, 0x20,
+			0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
+
+		dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
+		dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
+		dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
+		dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
+		dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
+		dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
+
+		*tune_state = CT_TUNER_STEP_0;
+	} else { /* we are already tuned to this frequency - the configuration is correct  */
+		ret = 50; /* wakeup time */
+		*tune_state = CT_TUNER_STEP_5;
+	}
+    } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
+
+	ret = dib0070_captrim(state, tune_state);
+
+    } else if (*tune_state == CT_TUNER_STEP_4) {
+	const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+	if (tmp != NULL) {
+		while (freq/1000 > tmp->freq) /* find the right one */
+			tmp++;
+		dib0070_write_reg(state, 0x0f,
+			(0 << 15) | (1 << 14) | (3 << 12)
+			| (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
+			| (state->current_tune_table_index->wbdmux << 0));
+		state->wbd_gain_current = tmp->wbd_gain_val;
+	} else {
 			dib0070_write_reg(state, 0x0f,
 					  (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
 														wbdmux << 0));
-			state->wbd_gain_current = 6;
-		}
+	    state->wbd_gain_current = 6;
+	}
 
-		dib0070_write_reg(state, 0x06, 0x3fff);
+	dib0070_write_reg(state, 0x06, 0x3fff);
 		dib0070_write_reg(state, 0x07,
 				  (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
-		dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
-		dib0070_write_reg(state, 0x0d, 0x0d80);
+	dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
+	dib0070_write_reg(state, 0x0d, 0x0d80);
 
-		dib0070_write_reg(state, 0x18, 0x07ff);
-		dib0070_write_reg(state, 0x17, 0x0033);
 
-		*tune_state = CT_TUNER_STEP_5;
-	} else if (*tune_state == CT_TUNER_STEP_5) {
-		dib0070_set_bandwidth(fe, ch);
-		*tune_state = CT_TUNER_STOP;
-	} else {
-		ret = FE_CALLBACK_TIME_NEVER;	/* tuner finished, time to call again infinite */
-	}
-	return ret;
+	dib0070_write_reg(state, 0x18,   0x07ff);
+	dib0070_write_reg(state, 0x17, 0x0033);
+
+
+	*tune_state = CT_TUNER_STEP_5;
+    } else if (*tune_state == CT_TUNER_STEP_5) {
+	dib0070_set_bandwidth(fe, ch);
+	*tune_state = CT_TUNER_STOP;
+    } else {
+	ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
+    }
+    return ret;
 }
 
+
 static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
-	struct dib0070_state *state = fe->tuner_priv;
-	uint32_t ret;
+    struct dib0070_state *state = fe->tuner_priv;
+    uint32_t ret;
 
-	state->tune_state = CT_TUNER_START;
+    state->tune_state = CT_TUNER_START;
 
-	do {
-		ret = dib0070_tune_digital(fe, p);
-		if (ret != FE_CALLBACK_TIME_NEVER)
-			msleep(ret / 10);
-		else
-			break;
-	} while (state->tune_state != CT_TUNER_STOP);
+    do {
+	ret = dib0070_tune_digital(fe, p);
+	if (ret != FE_CALLBACK_TIME_NEVER)
+		msleep(ret/10);
+	else
+	    break;
+    } while (state->tune_state != CT_TUNER_STOP);
 
-	return 0;
+    return 0;
 }
 
 static int dib0070_wakeup(struct dvb_frontend *fe)
@@ -512,92 +507,113 @@
 	return 0;
 }
 
-static const u16 dib0070_p1f_defaults[] = {
+u8 dib0070_get_rf_output(struct dvb_frontend *fe)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
+}
+EXPORT_SYMBOL(dib0070_get_rf_output);
+
+int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
+	if (no > 3)
+		no = 3;
+	if (no < 1)
+		no = 1;
+	return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
+}
+EXPORT_SYMBOL(dib0070_set_rf_output);
+
+static const u16 dib0070_p1f_defaults[] =
+
+{
 	7, 0x02,
-	0x0008,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0002,
-	0x0100,
+		0x0008,
+		0x0000,
+		0x0000,
+		0x0000,
+		0x0000,
+		0x0002,
+		0x0100,
 
 	3, 0x0d,
-	0x0d80,
-	0x0001,
-	0x0000,
+		0x0d80,
+		0x0001,
+		0x0000,
 
 	4, 0x11,
-	0x0000,
-	0x0103,
-	0x0000,
-	0x0000,
+		0x0000,
+		0x0103,
+		0x0000,
+		0x0000,
 
 	3, 0x16,
-	0x0004 | 0x0040,
-	0x0030,
-	0x07ff,
+		0x0004 | 0x0040,
+		0x0030,
+		0x07ff,
 
 	6, 0x1b,
-	0x4112,
-	0xff00,
-	0xc07f,
-	0x0000,
-	0x0180,
-	0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
+		0x4112,
+		0xff00,
+		0xc07f,
+		0x0000,
+		0x0180,
+		0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
 
 	0,
 };
 
 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
 {
-	u16 tuner_en = dib0070_read_reg(state, 0x20);
-	u16 offset;
+    u16 tuner_en = dib0070_read_reg(state, 0x20);
+    u16 offset;
 
-	dib0070_write_reg(state, 0x18, 0x07ff);
-	dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
-	dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
-	msleep(9);
-	offset = dib0070_read_reg(state, 0x19);
-	dib0070_write_reg(state, 0x20, tuner_en);
-	return offset;
+    dib0070_write_reg(state, 0x18, 0x07ff);
+    dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
+    dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
+    msleep(9);
+    offset = dib0070_read_reg(state, 0x19);
+    dib0070_write_reg(state, 0x20, tuner_en);
+    return offset;
 }
 
 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
 {
-	u8 gain;
-	for (gain = 6; gain < 8; gain++) {
-		state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
-		dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]);
-	}
+    u8 gain;
+    for (gain = 6; gain < 8; gain++) {
+	state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
+	dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
+    }
 }
 
 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
 {
-	struct dib0070_state *state = fe->tuner_priv;
-	const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
-	u32 freq = fe->dtv_property_cache.frequency / 1000;
+    struct dib0070_state *state = fe->tuner_priv;
+    const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+    u32 freq = fe->dtv_property_cache.frequency/1000;
 
-	if (tmp != NULL) {
-		while (freq / 1000 > tmp->freq)	/* find the right one */
-			tmp++;
-		state->wbd_gain_current = tmp->wbd_gain_val;
+    if (tmp != NULL) {
+	while (freq/1000 > tmp->freq) /* find the right one */
+	    tmp++;
+	state->wbd_gain_current = tmp->wbd_gain_val;
 	} else
-		state->wbd_gain_current = 6;
+	state->wbd_gain_current = 6;
 
-	return state->wbd_offset_3_3[state->wbd_gain_current - 6];
+    return state->wbd_offset_3_3[state->wbd_gain_current - 6];
 }
-
 EXPORT_SYMBOL(dib0070_wbd_offset);
 
 #define pgm_read_word(w) (*w)
 static int dib0070_reset(struct dvb_frontend *fe)
 {
-	struct dib0070_state *state = fe->tuner_priv;
+    struct dib0070_state *state = fe->tuner_priv;
 	u16 l, r, *n;
 
 	HARD_RESET(state);
 
+
 #ifndef FORCE_SBAND_TUNER
 	if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
 		state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
@@ -605,7 +621,7 @@
 #else
 #warning forcing SBAND
 #endif
-	state->revision = DIB0070S_P1A;
+		state->revision = DIB0070S_P1A;
 
 	/* P1F or not */
 	dprintk("Revision: %x", state->revision);
@@ -620,7 +636,7 @@
 	while (l) {
 		r = pgm_read_word(n++);
 		do {
-			dib0070_write_reg(state, (u8) r, pgm_read_word(n++));
+			dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
 			r++;
 		} while (--l);
 		l = pgm_read_word(n++);
@@ -633,6 +649,7 @@
 	else
 		r = 2;
 
+
 	r |= state->cfg->osc_buffer_state << 3;
 
 	dib0070_write_reg(state, 0x10, r);
@@ -643,16 +660,24 @@
 		dib0070_write_reg(state, 0x02, r | (1 << 5));
 	}
 
-	if (state->revision == DIB0070S_P1A)
-		dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
-	else
+    if (state->revision == DIB0070S_P1A)
+	dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+    else
 		dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
 
 	dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
 
-	dib0070_wbd_offset_calibration(state);
+    dib0070_wbd_offset_calibration(state);
 
-	return 0;
+    return 0;
+}
+
+static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+
+    *frequency = 1000 * state->current_rf;
+    return 0;
 }
 
 static int dib0070_release(struct dvb_frontend *fe)
@@ -664,18 +689,18 @@
 
 static const struct dvb_tuner_ops dib0070_ops = {
 	.info = {
-		 .name = "DiBcom DiB0070",
-		 .frequency_min = 45000000,
-		 .frequency_max = 860000000,
-		 .frequency_step = 1000,
-		 },
-	.release = dib0070_release,
+		.name           = "DiBcom DiB0070",
+		.frequency_min  =  45000000,
+		.frequency_max  = 860000000,
+		.frequency_step =      1000,
+	},
+	.release       = dib0070_release,
 
-	.init = dib0070_wakeup,
-	.sleep = dib0070_sleep,
-	.set_params = dib0070_tune,
+	.init          = dib0070_wakeup,
+	.sleep         = dib0070_sleep,
+	.set_params    = dib0070_tune,
 
-//      .get_frequency = dib0070_get_frequency,
+	.get_frequency = dib0070_get_frequency,
 //      .get_bandwidth = dib0070_get_bandwidth
 };
 
@@ -687,7 +712,7 @@
 
 	state->cfg = cfg;
 	state->i2c = i2c;
-	state->fe = fe;
+	state->fe  = fe;
 	fe->tuner_priv = state;
 
 	if (dib0070_reset(fe) != 0)
@@ -699,12 +724,11 @@
 	fe->tuner_priv = state;
 	return fe;
 
- free_mem:
+free_mem:
 	kfree(state);
 	fe->tuner_priv = NULL;
 	return NULL;
 }
-
 EXPORT_SYMBOL(dib0070_attach);
 
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index eec9e52..45c31fa 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -52,6 +52,8 @@
 extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
 extern u16 dib0070_wbd_offset(struct dvb_frontend *);
 extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
+extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
+extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
 #else
 static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
 {
@@ -62,7 +64,7 @@
 static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
+	return 0;
 }
 
 static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
new file mode 100644
index 0000000..6145527
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -0,0 +1,1522 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-9 DiBcom (http://www.dibcom.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This code is more or less generated from another driver, please
+ * excuse some codingstyle oddities.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib0090.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { \
+	if (debug) { \
+		printk(KERN_DEBUG "DiB0090: "); \
+		printk(args); \
+		printk("\n"); \
+	} \
+} while (0)
+
+#define CONFIG_SYS_ISDBT
+#define CONFIG_BAND_CBAND
+#define CONFIG_BAND_VHF
+#define CONFIG_BAND_UHF
+#define CONFIG_DIB0090_USE_PWM_AGC
+
+#define EN_LNA0      0x8000
+#define EN_LNA1      0x4000
+#define EN_LNA2      0x2000
+#define EN_LNA3      0x1000
+#define EN_MIX0      0x0800
+#define EN_MIX1      0x0400
+#define EN_MIX2      0x0200
+#define EN_MIX3      0x0100
+#define EN_IQADC     0x0040
+#define EN_PLL       0x0020
+#define EN_TX        0x0010
+#define EN_BB        0x0008
+#define EN_LO        0x0004
+#define EN_BIAS      0x0001
+
+#define EN_IQANA     0x0002
+#define EN_DIGCLK    0x0080	/* not in the 0x24 reg, only in 0x1b */
+#define EN_CRYSTAL   0x0002
+
+#define EN_UHF		 0x22E9
+#define EN_VHF		 0x44E9
+#define EN_LBD		 0x11E9
+#define EN_SBD		 0x44E9
+#define EN_CAB		 0x88E9
+
+#define pgm_read_word(w) (*w)
+
+struct dc_calibration;
+
+struct dib0090_tuning {
+	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u8 switch_trim;
+	u8 lna_tune;
+	u8 lna_bias;
+	u16 v2i;
+	u16 mix;
+	u16 load;
+	u16 tuner_enable;
+};
+
+struct dib0090_pll {
+	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u8 vco_band;
+	u8 hfdiv_code;
+	u8 hfdiv;
+	u8 topresc;
+};
+
+struct dib0090_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	const struct dib0090_config *config;
+
+	u8 current_band;
+	u16 revision;
+	enum frontend_tune_state tune_state;
+	u32 current_rf;
+
+	u16 wbd_offset;
+	s16 wbd_target;		/* in dB */
+
+	s16 rf_gain_limit;	/* take-over-point: where to split between bb and rf gain */
+	s16 current_gain;	/* keeps the currently programmed gain */
+	u8 agc_step;		/* new binary search */
+
+	u16 gain[2];		/* for channel monitoring */
+
+	const u16 *rf_ramp;
+	const u16 *bb_ramp;
+
+	/* for the software AGC ramps */
+	u16 bb_1_def;
+	u16 rf_lt_def;
+	u16 gain_reg[4];
+
+	/* for the captrim/dc-offset search */
+	s8 step;
+	s16 adc_diff;
+	s16 min_adc_diff;
+
+	s8 captrim;
+	s8 fcaptrim;
+
+	const struct dc_calibration *dc;
+	u16 bb6, bb7;
+
+	const struct dib0090_tuning *current_tune_table_index;
+	const struct dib0090_pll *current_pll_table_index;
+
+	u8 tuner_is_tuned;
+	u8 agc_freeze;
+
+	u8 reset;
+};
+
+static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+{
+	u8 b[2];
+	struct i2c_msg msg[2] = {
+		{.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
+		{.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
+	};
+	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		return 0;
+	}
+	return (b[0] << 8) | b[1];
+}
+
+static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+{
+	u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
+	struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+#define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
+#define ADC_TARGET -220
+#define GAIN_ALPHA 5
+#define WBD_ALPHA 6
+#define LPF	100
+static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
+{
+	do {
+		dib0090_write_reg(state, r++, *b++);
+	} while (--c);
+}
+
+static u16 dib0090_identify(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u16 v;
+
+	v = dib0090_read_reg(state, 0x1a);
+
+#ifdef FIRMWARE_FIREFLY
+	/* pll is not locked locked */
+	if (!(v & 0x800))
+		dprintk("FE%d : Identification : pll is not yet locked", fe->id);
+#endif
+
+	/* without PLL lock info */
+	v &= 0x3ff;
+	dprintk("P/V: %04x:", v);
+
+	if ((v >> 8) & 0xf)
+		dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
+	else
+		return 0xff;
+
+	v &= 0xff;
+	if (((v >> 5) & 0x7) == 0x1)
+		dprintk("FE%d : MP001 : 9090/8096", fe->id);
+	else if (((v >> 5) & 0x7) == 0x4)
+		dprintk("FE%d : MP005 : Single Sband", fe->id);
+	else if (((v >> 5) & 0x7) == 0x6)
+		dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id);
+	else if (((v >> 5) & 0x7) == 0x7)
+		dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id);
+	else
+		return 0xff;
+
+	/* revision only */
+	if ((v & 0x1f) == 0x3)
+		dprintk("FE%d : P1-D/E/F detected", fe->id);
+	else if ((v & 0x1f) == 0x1)
+		dprintk("FE%d : P1C detected", fe->id);
+	else if ((v & 0x1f) == 0x0) {
+#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
+		dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id);
+		dib0090_p1b_register(fe);
+#else
+		dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id);
+		return 0xff;
+#endif
+	}
+
+	return v;
+}
+
+static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	HARD_RESET(state);
+
+	dib0090_write_reg(state, 0x24, EN_PLL);
+	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+
+	/* adcClkOutRatio=8->7, release reset */
+	dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
+	if (cfg->clkoutdrive != 0)
+		dib0090_write_reg(state, 0x23,
+				  (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg->
+																	   clkouttobamse
+																	   << 4) | (0
+																		    <<
+																		    2)
+				  | (0));
+	else
+		dib0090_write_reg(state, 0x23,
+				  (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg->
+															    clkouttobamse << 4) | (0
+																		   <<
+																		   2)
+				  | (0));
+
+	/* enable pll, de-activate reset, ratio: 2/1 = 60MHz */
+	dib0090_write_reg(state, 0x21,
+			  (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv));
+
+}
+
+static int dib0090_wakeup(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (state->config->sleep)
+		state->config->sleep(fe, 0);
+	return 0;
+}
+
+static int dib0090_sleep(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (state->config->sleep)
+		state->config->sleep(fe, 1);
+	return 0;
+}
+
+extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (fast)
+		dib0090_write_reg(state, 0x04, 0);
+	else
+		dib0090_write_reg(state, 0x04, 1);
+}
+EXPORT_SYMBOL(dib0090_dcc_freq);
+
+static const u16 rf_ramp_pwm_cband[] = {
+	0,			/* max RF gain in 10th of dB */
+	0,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	0,			/* ramp_max = maximum X used on the ramp */
+	(0 << 10) | 0,		/* 0x2c, LNA 1 = 0dB */
+	(0 << 10) | 0,		/* 0x2d, LNA 1 */
+	(0 << 10) | 0,		/* 0x2e, LNA 2 = 0dB */
+	(0 << 10) | 0,		/* 0x2f, LNA 2 */
+	(0 << 10) | 0,		/* 0x30, LNA 3 = 0dB */
+	(0 << 10) | 0,		/* 0x31, LNA 3 */
+	(0 << 10) | 0,		/* GAIN_4_1, LNA 4 = 0dB */
+	(0 << 10) | 0,		/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_vhf[] = {
+	412,			/* max RF gain in 10th of dB */
+	132, 307, 127,		/* LNA1,  13.2dB */
+	105, 412, 255,		/* LNA2,  10.5dB */
+	50, 50, 127,		/* LNA3,  5dB */
+	125, 175, 127,		/* LNA4,  12.5dB */
+	0, 0, 127,		/* CBAND, 0dB */
+};
+
+static const u16 rf_ramp_uhf[] = {
+	412,			/* max RF gain in 10th of dB */
+	132, 307, 127,		/* LNA1  : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
+	105, 412, 255,		/* LNA2  : 10.5 dB */
+	50, 50, 127,		/* LNA3  :  5.0 dB */
+	125, 175, 127,		/* LNA4  : 12.5 dB */
+	0, 0, 127,		/* CBAND :  0.0 dB */
+};
+
+static const u16 rf_ramp_cband[] = {
+	332,			/* max RF gain in 10th of dB */
+	132, 252, 127,		/* LNA1,  dB */
+	80, 332, 255,		/* LNA2,  dB */
+	0, 0, 127,		/* LNA3,  dB */
+	0, 0, 127,		/* LNA4,  dB */
+	120, 120, 127,		/* LT1 CBAND */
+};
+
+static const u16 rf_ramp_pwm_vhf[] = {
+	404,			/* max RF gain in 10th of dB */
+	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	1011,			/* ramp_max = maximum X used on the ramp */
+	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
+	(0 << 10) | 756,	/* 0x2d, LNA 1 */
+	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
+	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
+	(16 << 10) | 290,	/* 0x30, LNA 3 = 5dB */
+	(0 << 10) | 417,	/* 0x31, LNA 3 */
+	(7 << 10) | 0,		/* GAIN_4_1, LNA 4 = 12.5dB */
+	(0 << 10) | 290,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf[] = {
+	404,			/* max RF gain in 10th of dB */
+	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	1011,			/* ramp_max = maximum X used on the ramp */
+	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
+	(0 << 10) | 756,	/* 0x2d, LNA 1 */
+	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
+	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
+	(16 << 10) | 0,		/* 0x30, LNA 3 = 5dB */
+	(0 << 10) | 127,	/* 0x31, LNA 3 */
+	(7 << 10) | 127,	/* GAIN_4_1, LNA 4 = 12.5dB */
+	(0 << 10) | 417,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 bb_ramp_boost[] = {
+	550,			/* max BB gain in 10th of dB */
+	260, 260, 26,		/* BB1, 26dB */
+	290, 550, 29,		/* BB2, 29dB */
+};
+
+static const u16 bb_ramp_pwm_normal[] = {
+	500,			/* max RF gain in 10th of dB */
+	8,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
+	400,
+	(2 << 9) | 0,		/* 0x35 = 21dB */
+	(0 << 9) | 168,		/* 0x36 */
+	(2 << 9) | 168,		/* 0x37 = 29dB */
+	(0 << 9) | 400,		/* 0x38 */
+};
+
+struct slope {
+	int16_t range;
+	int16_t slope;
+};
+static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
+{
+	u8 i;
+	u16 rest;
+	u16 ret = 0;
+	for (i = 0; i < num; i++) {
+		if (val > slopes[i].range)
+			rest = slopes[i].range;
+		else
+			rest = val;
+		ret += (rest * slopes[i].slope) / slopes[i].range;
+		val -= rest;
+	}
+	return ret;
+}
+
+static const struct slope dib0090_wbd_slopes[3] = {
+	{66, 120},		/* -64,-52: offset -   65 */
+	{600, 170},		/* -52,-35: 65     -  665 */
+	{170, 250},		/* -45,-10: 665    - 835 */
+};
+
+static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
+{
+	wbd &= 0x3ff;
+	if (wbd < state->wbd_offset)
+		wbd = 0;
+	else
+		wbd -= state->wbd_offset;
+	/* -64dB is the floor */
+	return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
+}
+
+static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
+{
+	u16 offset = 250;
+
+	/* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
+
+	if (state->current_band == BAND_VHF)
+		offset = 650;
+#ifndef FIRMWARE_FIREFLY
+	if (state->current_band == BAND_VHF)
+		offset = state->config->wbd_vhf_offset;
+	if (state->current_band == BAND_CBAND)
+		offset = state->config->wbd_cband_offset;
+#endif
+
+	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
+	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
+}
+
+static const int gain_reg_addr[4] = {
+	0x08, 0x0a, 0x0f, 0x01
+};
+
+static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
+{
+	u16 rf, bb, ref;
+	u16 i, v, gain_reg[4] = { 0 }, gain;
+	const u16 *g;
+
+	if (top_delta < -511)
+		top_delta = -511;
+	if (top_delta > 511)
+		top_delta = 511;
+
+	if (force) {
+		top_delta *= (1 << WBD_ALPHA);
+		gain_delta *= (1 << GAIN_ALPHA);
+	}
+
+	if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))	/* overflow */
+		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
+	else
+		state->rf_gain_limit += top_delta;
+
+	if (state->rf_gain_limit < 0)	/*underflow */
+		state->rf_gain_limit = 0;
+
+	/* use gain as a temporary variable and correct current_gain */
+	gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
+	if (gain_delta >= ((s16) gain - state->current_gain))	/* overflow */
+		state->current_gain = gain;
+	else
+		state->current_gain += gain_delta;
+	/* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
+	if (state->current_gain < 0)
+		state->current_gain = 0;
+
+	/* now split total gain to rf and bb gain */
+	gain = state->current_gain >> GAIN_ALPHA;
+
+	/* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
+	if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
+		rf = state->rf_gain_limit >> WBD_ALPHA;
+		bb = gain - rf;
+		if (bb > state->bb_ramp[0])
+			bb = state->bb_ramp[0];
+	} else {		/* high signal level -> all gains put on RF */
+		rf = gain;
+		bb = 0;
+	}
+
+	state->gain[0] = rf;
+	state->gain[1] = bb;
+
+	/* software ramp */
+	/* Start with RF gains */
+	g = state->rf_ramp + 1;	/* point on RF LNA1 max gain */
+	ref = rf;
+	for (i = 0; i < 7; i++) {	/* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
+		if (g[0] == 0 || ref < (g[1] - g[0]))	/* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
+			v = 0;	/* force the gain to write for the current amp to be null */
+		else if (ref >= g[1])	/* Gain to set is higher than the high working point of this amp */
+			v = g[2];	/* force this amp to be full gain */
+		else		/* compute the value to set to this amp because we are somewhere in his range */
+			v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
+
+		if (i == 0)	/* LNA 1 reg mapping */
+			gain_reg[0] = v;
+		else if (i == 1)	/* LNA 2 reg mapping */
+			gain_reg[0] |= v << 7;
+		else if (i == 2)	/* LNA 3 reg mapping */
+			gain_reg[1] = v;
+		else if (i == 3)	/* LNA 4 reg mapping */
+			gain_reg[1] |= v << 7;
+		else if (i == 4)	/* CBAND LNA reg mapping */
+			gain_reg[2] = v | state->rf_lt_def;
+		else if (i == 5)	/* BB gain 1 reg mapping */
+			gain_reg[3] = v << 3;
+		else if (i == 6)	/* BB gain 2 reg mapping */
+			gain_reg[3] |= v << 8;
+
+		g += 3;		/* go to next gain bloc */
+
+		/* When RF is finished, start with BB */
+		if (i == 4) {
+			g = state->bb_ramp + 1;	/* point on BB gain 1 max gain */
+			ref = bb;
+		}
+	}
+	gain_reg[3] |= state->bb_1_def;
+	gain_reg[3] |= ((bb % 10) * 100) / 125;
+
+#ifdef DEBUG_AGC
+	dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
+		gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
+#endif
+
+	/* Write the amplifier regs */
+	for (i = 0; i < 4; i++) {
+		v = gain_reg[i];
+		if (force || state->gain_reg[i] != v) {
+			state->gain_reg[i] = v;
+			dib0090_write_reg(state, gain_reg_addr[i], v);
+		}
+	}
+}
+
+static void dib0090_set_boost(struct dib0090_state *state, int onoff)
+{
+	state->bb_1_def &= 0xdfff;
+	state->bb_1_def |= onoff << 13;
+}
+
+static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
+{
+	state->rf_ramp = cfg;
+}
+
+static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
+{
+	state->rf_ramp = cfg;
+
+	dib0090_write_reg(state, 0x2a, 0xffff);
+
+	dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
+
+	dib0090_write_regs(state, 0x2c, cfg + 3, 6);
+	dib0090_write_regs(state, 0x3e, cfg + 9, 2);
+}
+
+static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
+{
+	state->bb_ramp = cfg;
+	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
+}
+
+static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
+{
+	state->bb_ramp = cfg;
+
+	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
+
+	dib0090_write_reg(state, 0x33, 0xffff);
+	dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
+	dib0090_write_regs(state, 0x35, cfg + 3, 4);
+}
+
+void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	/* reset the AGC */
+
+	if (state->config->use_pwm_agc) {
+#ifdef CONFIG_BAND_SBAND
+		if (state->current_band == BAND_SBAND) {
+			dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
+			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_CBAND
+		if (state->current_band == BAND_CBAND) {
+			dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
+			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+		} else
+#endif
+#ifdef CONFIG_BAND_VHF
+		if (state->current_band == BAND_VHF) {
+			dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
+			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+		} else
+#endif
+		{
+			dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
+			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+		}
+
+		if (state->rf_ramp[0] != 0)
+			dib0090_write_reg(state, 0x32, (3 << 11));
+		else
+			dib0090_write_reg(state, 0x32, (0 << 11));
+
+		dib0090_write_reg(state, 0x39, (1 << 10));
+	}
+}
+EXPORT_SYMBOL(dib0090_pwm_gain_reset);
+
+int dib0090_gain_control(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+	int ret = 10;
+
+	u16 wbd_val = 0;
+	u8 apply_gain_immediatly = 1;
+	s16 wbd_error = 0, adc_error = 0;
+
+	if (*tune_state == CT_AGC_START) {
+		state->agc_freeze = 0;
+		dib0090_write_reg(state, 0x04, 0x0);
+
+#ifdef CONFIG_BAND_SBAND
+		if (state->current_band == BAND_SBAND) {
+			dib0090_set_rframp(state, rf_ramp_sband);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_VHF
+		if (state->current_band == BAND_VHF) {
+			dib0090_set_rframp(state, rf_ramp_vhf);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_CBAND
+		if (state->current_band == BAND_CBAND) {
+			dib0090_set_rframp(state, rf_ramp_cband);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+		{
+			dib0090_set_rframp(state, rf_ramp_uhf);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		}
+
+		dib0090_write_reg(state, 0x32, 0);
+		dib0090_write_reg(state, 0x39, 0);
+
+		dib0090_wbd_target(state, state->current_rf);
+
+		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
+		state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
+
+		*tune_state = CT_AGC_STEP_0;
+	} else if (!state->agc_freeze) {
+		s16 wbd;
+
+		int adc;
+		wbd_val = dib0090_read_reg(state, 0x1d);
+
+		/* read and calc the wbd power */
+		wbd = dib0090_wbd_to_db(state, wbd_val);
+		wbd_error = state->wbd_target - wbd;
+
+		if (*tune_state == CT_AGC_STEP_0) {
+			if (wbd_error < 0 && state->rf_gain_limit > 0) {
+#ifdef CONFIG_BAND_CBAND
+				/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
+				u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
+				if (state->current_band == BAND_CBAND && ltg2) {
+					ltg2 >>= 1;
+					state->rf_lt_def &= ltg2 << 10;	/* reduce in 3 steps from 7 to 0 */
+				}
+#endif
+			} else {
+				state->agc_step = 0;
+				*tune_state = CT_AGC_STEP_1;
+			}
+		} else {
+			/* calc the adc power */
+			adc = state->config->get_adc_power(fe);
+			adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21;	/* included in [0:-700] */
+
+			adc_error = (s16) (((s32) ADC_TARGET) - adc);
+#ifdef CONFIG_STANDARD_DAB
+			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
+				adc_error += 130;
+#endif
+#ifdef CONFIG_STANDARD_DVBT
+			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
+			    (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
+				adc_error += 60;
+#endif
+#ifdef CONFIG_SYS_ISDBT
+			if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
+											       0)
+											      &&
+											      ((state->fe->dtv_property_cache.layer[0].modulation ==
+												QAM_64)
+											       || (state->fe->dtv_property_cache.layer[0].
+												   modulation == QAM_16)))
+											     ||
+											     ((state->fe->dtv_property_cache.layer[1].segment_count >
+											       0)
+											      &&
+											      ((state->fe->dtv_property_cache.layer[1].modulation ==
+												QAM_64)
+											       || (state->fe->dtv_property_cache.layer[1].
+												   modulation == QAM_16)))
+											     ||
+											     ((state->fe->dtv_property_cache.layer[2].segment_count >
+											       0)
+											      &&
+											      ((state->fe->dtv_property_cache.layer[2].modulation ==
+												QAM_64)
+											       || (state->fe->dtv_property_cache.layer[2].
+												   modulation == QAM_16)))
+			    )
+			    )
+				adc_error += 60;
+#endif
+
+			if (*tune_state == CT_AGC_STEP_1) {	/* quickly go to the correct range of the ADC power */
+				if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
+
+#ifdef CONFIG_STANDARD_DAB
+					if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
+						dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));	/* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
+						dib0090_write_reg(state, 0x04, 0x0);
+					} else
+#endif
+					{
+						dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
+						dib0090_write_reg(state, 0x04, 0x01);	/*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
+					}
+
+					*tune_state = CT_AGC_STOP;
+				}
+			} else {
+				/* everything higher than or equal to CT_AGC_STOP means tracking */
+				ret = 100;	/* 10ms interval */
+				apply_gain_immediatly = 0;
+			}
+		}
+#ifdef DEBUG_AGC
+		dprintk
+		    ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
+		     (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
+		     (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
+#endif
+	}
+
+	/* apply gain */
+	if (!state->agc_freeze)
+		dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
+	return ret;
+}
+EXPORT_SYMBOL(dib0090_gain_control);
+
+void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (rf)
+		*rf = state->gain[0];
+	if (bb)
+		*bb = state->gain[1];
+	if (rf_gain_limit)
+		*rf_gain_limit = state->rf_gain_limit;
+	if (rflt)
+		*rflt = (state->rf_lt_def >> 10) & 0x7;
+}
+EXPORT_SYMBOL(dib0090_get_current_gain);
+
+u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
+{
+	struct dib0090_state *st = tuner->tuner_priv;
+	return st->wbd_offset;
+}
+EXPORT_SYMBOL(dib0090_get_wbd_offset);
+
+static const u16 dib0090_defaults[] = {
+
+	25, 0x01,
+	0x0000,
+	0x99a0,
+	0x6008,
+	0x0000,
+	0x8acb,
+	0x0000,
+	0x0405,
+	0x0000,
+	0x0000,
+	0x0000,
+	0xb802,
+	0x0300,
+	0x2d12,
+	0xbac0,
+	0x7c00,
+	0xdbb9,
+	0x0954,
+	0x0743,
+	0x8000,
+	0x0001,
+	0x0040,
+	0x0100,
+	0x0000,
+	0xe910,
+	0x149e,
+
+	1, 0x1c,
+	0xff2d,
+
+	1, 0x39,
+	0x0000,
+
+	1, 0x1b,
+	EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
+	2, 0x1e,
+	0x07FF,
+	0x0007,
+
+	1, 0x24,
+	EN_UHF | EN_CRYSTAL,
+
+	2, 0x3c,
+	0x3ff,
+	0x111,
+	0
+};
+
+static int dib0090_reset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u16 l, r, *n;
+
+	dib0090_reset_digital(fe, state->config);
+	state->revision = dib0090_identify(fe);
+
+	/* Revision definition */
+	if (state->revision == 0xff)
+		return -EINVAL;
+#ifdef EFUSE
+	else if ((state->revision & 0x1f) >= 3)	/* Update the efuse : Only available for KROSUS > P1C */
+		dib0090_set_EFUSE(state);
+#endif
+
+#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
+	if (!(state->revision & 0x1))	/* it is P1B - reset is already done */
+		return 0;
+#endif
+
+	/* Upload the default values */
+	n = (u16 *) dib0090_defaults;
+	l = pgm_read_word(n++);
+	while (l) {
+		r = pgm_read_word(n++);
+		do {
+			/* DEBUG_TUNER */
+			/* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */
+			dib0090_write_reg(state, r, pgm_read_word(n++));
+			r++;
+		} while (--l);
+		l = pgm_read_word(n++);
+	}
+
+	/* Congigure in function of the crystal */
+	if (state->config->io.clock_khz >= 24000)
+		l = 1;
+	else
+		l = 2;
+	dib0090_write_reg(state, 0x14, l);
+	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
+
+	state->reset = 3;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
+
+	return 0;
+}
+
+#define steps(u) (((u) > 15) ? ((u)-16) : (u))
+#define INTERN_WAIT 10
+static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = INTERN_WAIT * 10;
+
+	switch (*tune_state) {
+	case CT_TUNER_STEP_2:
+		/* Turns to positive */
+		dib0090_write_reg(state, 0x1f, 0x7);
+		*tune_state = CT_TUNER_STEP_3;
+		break;
+
+	case CT_TUNER_STEP_3:
+		state->adc_diff = dib0090_read_reg(state, 0x1d);
+
+		/* Turns to negative */
+		dib0090_write_reg(state, 0x1f, 0x4);
+		*tune_state = CT_TUNER_STEP_4;
+		break;
+
+	case CT_TUNER_STEP_4:
+		state->adc_diff -= dib0090_read_reg(state, 0x1d);
+		*tune_state = CT_TUNER_STEP_5;
+		ret = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+struct dc_calibration {
+	uint8_t addr;
+	uint8_t offset;
+	uint8_t pga:1;
+	uint16_t bb1;
+	uint8_t i:1;
+};
+
+static const struct dc_calibration dc_table[] = {
+	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
+	{0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
+	{0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
+	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
+	{0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
+	{0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
+	{0},
+};
+
+static void dib0090_set_trim(struct dib0090_state *state)
+{
+	u16 *val;
+
+	if (state->dc->addr == 0x07)
+		val = &state->bb7;
+	else
+		val = &state->bb6;
+
+	*val &= ~(0x1f << state->dc->offset);
+	*val |= state->step << state->dc->offset;
+
+	dib0090_write_reg(state, state->dc->addr, *val);
+}
+
+static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 0;
+
+	switch (*tune_state) {
+
+	case CT_TUNER_START:
+		/* init */
+		dprintk("Internal DC calibration");
+
+		/* the LNA is off */
+		dib0090_write_reg(state, 0x24, 0x02ed);
+
+		/* force vcm2 = 0.8V */
+		state->bb6 = 0;
+		state->bb7 = 0x040d;
+
+		state->dc = dc_table;
+
+		*tune_state = CT_TUNER_STEP_0;
+
+		/* fall through */
+
+	case CT_TUNER_STEP_0:
+		dib0090_write_reg(state, 0x01, state->dc->bb1);
+		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
+
+		state->step = 0;
+
+		state->min_adc_diff = 1023;
+
+		*tune_state = CT_TUNER_STEP_1;
+		ret = 50;
+		break;
+
+	case CT_TUNER_STEP_1:
+		dib0090_set_trim(state);
+
+		*tune_state = CT_TUNER_STEP_2;
+		break;
+
+	case CT_TUNER_STEP_2:
+	case CT_TUNER_STEP_3:
+	case CT_TUNER_STEP_4:
+		ret = dib0090_get_offset(state, tune_state);
+		break;
+
+	case CT_TUNER_STEP_5:	/* found an offset */
+		dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step);
+
+		/* first turn for this frequency */
+		if (state->step == 0) {
+			if (state->dc->pga && state->adc_diff < 0)
+				state->step = 0x10;
+			if (state->dc->pga == 0 && state->adc_diff > 0)
+				state->step = 0x10;
+		}
+
+		state->adc_diff = ABS(state->adc_diff);
+
+		if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) {	/* stop search when the delta to 0 is increasing */
+			state->step++;
+			state->min_adc_diff = state->adc_diff;
+			*tune_state = CT_TUNER_STEP_1;
+		} else {
+
+			/* the minimum was what we have seen in the step before */
+			state->step--;
+			dib0090_set_trim(state);
+
+			dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff,
+				state->step);
+
+			state->dc++;
+			if (state->dc->addr == 0)	/* done */
+				*tune_state = CT_TUNER_STEP_6;
+			else
+				*tune_state = CT_TUNER_STEP_0;
+
+		}
+		break;
+
+	case CT_TUNER_STEP_6:
+		dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
+		dib0090_write_reg(state, 0x1f, 0x7);
+		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
+		state->reset &= ~0x1;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	switch (*tune_state) {
+	case CT_TUNER_START:
+		/* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */
+		dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10));
+		dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff);
+
+		*tune_state = CT_TUNER_STEP_0;
+		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
+	case CT_TUNER_STEP_0:
+		state->wbd_offset = dib0090_read_reg(state, 0x1d);
+		dprintk("WBD calibration offset = %d", state->wbd_offset);
+
+		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
+		state->reset &= ~0x2;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static void dib0090_set_bandwidth(struct dib0090_state *state)
+{
+	u16 tmp;
+
+	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
+		tmp = (3 << 14);
+	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
+		tmp = (2 << 14);
+	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
+		tmp = (1 << 14);
+	else
+		tmp = (0 << 14);
+
+	state->bb_1_def &= 0x3fff;
+	state->bb_1_def |= tmp;
+
+	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
+}
+
+static const struct dib0090_pll dib0090_pll_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{56000, 0, 9, 48, 6},
+	{70000, 1, 9, 48, 6},
+	{87000, 0, 8, 32, 4},
+	{105000, 1, 8, 32, 4},
+	{115000, 0, 7, 24, 6},
+	{140000, 1, 7, 24, 6},
+	{170000, 0, 6, 16, 4},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{200000, 1, 6, 16, 4},
+	{230000, 0, 5, 12, 6},
+	{280000, 1, 5, 12, 6},
+	{340000, 0, 4, 8, 4},
+	{380000, 1, 4, 8, 4},
+	{450000, 0, 3, 6, 6},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{580000, 1, 3, 6, 6},
+	{700000, 0, 2, 4, 4},
+	{860000, 1, 2, 4, 4},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1800000, 1, 0, 2, 4},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2900000, 0, 14, 1, 4},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
+
+#ifdef CONFIG_BAND_CBAND
+	{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+	{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+	{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table[] = {
+
+#ifdef CONFIG_BAND_CBAND
+	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
+static int dib0090_tune(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	const struct dib0090_tuning *tune = state->current_tune_table_index;
+	const struct dib0090_pll *pll = state->current_pll_table_index;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+
+	u32 rf;
+	u16 lo4 = 0xe900, lo5, lo6, Den;
+	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
+	u16 tmp, adc;
+	int8_t step_sign;
+	int ret = 10;		/* 1ms is the default delay most of the time */
+	u8 c, i;
+
+	state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
+	rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
+							BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf);
+	/* in any case we first need to do a reset if needed */
+	if (state->reset & 0x1)
+		return dib0090_dc_offset_calibration(state, tune_state);
+	else if (state->reset & 0x2)
+		return dib0090_wbd_calibration(state, tune_state);
+
+    /************************* VCO ***************************/
+	/* Default values for FG                                 */
+	/* from these are needed :                               */
+	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
+
+#ifdef CONFIG_SYS_ISDBT
+	if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
+		rf += 850;
+#endif
+
+	if (state->current_rf != rf) {
+		state->tuner_is_tuned = 0;
+
+		tune = dib0090_tuning_table;
+
+		tmp = (state->revision >> 5) & 0x7;
+		if (tmp == 0x4 || tmp == 0x7) {
+			/* CBAND tuner version for VHF */
+			if (state->current_band == BAND_FM || state->current_band == BAND_VHF) {
+				/* Force CBAND */
+				state->current_band = BAND_CBAND;
+				tune = dib0090_tuning_table_fm_vhf_on_cband;
+			}
+		}
+
+		pll = dib0090_pll_table;
+		/* Look for the interval */
+		while (rf > tune->max_freq)
+			tune++;
+		while (rf > pll->max_freq)
+			pll++;
+		state->current_tune_table_index = tune;
+		state->current_pll_table_index = pll;
+	}
+
+	if (*tune_state == CT_TUNER_START) {
+
+		if (state->tuner_is_tuned == 0)
+			state->current_rf = 0;
+
+		if (state->current_rf != rf) {
+
+			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
+
+			/* external loop filter, otherwise:
+			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
+			 * lo6 = 0x0e34 */
+			if (pll->vco_band)
+				lo5 = 0x049e;
+			else if (state->config->analog_output)
+				lo5 = 0x041d;
+			else
+				lo5 = 0x041c;
+
+			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
+
+			if (!state->config->io.pll_int_loop_filt)
+				lo6 = 0xff28;
+			else
+				lo6 = (state->config->io.pll_int_loop_filt << 3);
+
+			VCOF_kHz = (pll->hfdiv * rf) * 2;
+
+			FREF = state->config->io.clock_khz;
+
+			FBDiv = (VCOF_kHz / pll->topresc / FREF);
+			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
+
+			if (Rest < LPF)
+				Rest = 0;
+			else if (Rest < 2 * LPF)
+				Rest = 2 * LPF;
+			else if (Rest > (FREF - LPF)) {
+				Rest = 0;
+				FBDiv += 1;
+			} else if (Rest > (FREF - 2 * LPF))
+				Rest = FREF - 2 * LPF;
+			Rest = (Rest * 6528) / (FREF / 10);
+
+			Den = 1;
+
+			dprintk(" *****  ******* Rest value = %d", Rest);
+
+			if (Rest > 0) {
+				if (state->config->analog_output)
+					lo6 |= (1 << 2) | 2;
+				else
+					lo6 |= (1 << 2) | 1;
+				Den = 255;
+			}
+#ifdef CONFIG_BAND_SBAND
+			if (state->current_band == BAND_SBAND)
+				lo6 &= 0xfffb;
+#endif
+
+			dib0090_write_reg(state, 0x15, (u16) FBDiv);
+
+			dib0090_write_reg(state, 0x16, (Den << 8) | 1);
+
+			dib0090_write_reg(state, 0x17, (u16) Rest);
+
+			dib0090_write_reg(state, 0x19, lo5);
+
+			dib0090_write_reg(state, 0x1c, lo6);
+
+			lo6 = tune->tuner_enable;
+			if (state->config->analog_output)
+				lo6 = (lo6 & 0xff9f) | 0x2;
+
+			dib0090_write_reg(state, 0x24, lo6 | EN_LO
+#ifdef CONFIG_DIB0090_USE_PWM_AGC
+					  | state->config->use_pwm_agc * EN_CRYSTAL
+#endif
+			    );
+
+			state->current_rf = rf;
+
+			/* prepare a complete captrim */
+			state->step = state->captrim = state->fcaptrim = 64;
+
+		} else {	/* we are already tuned to this frequency - the configuration is correct  */
+
+			/* do a minimal captrim even if the frequency has not changed */
+			state->step = 4;
+			state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
+		}
+		state->adc_diff = 3000;
+
+		dib0090_write_reg(state, 0x10, 0x2B1);
+
+		dib0090_write_reg(state, 0x1e, 0x0032);
+
+		ret = 20;
+		*tune_state = CT_TUNER_STEP_1;
+	} else if (*tune_state == CT_TUNER_STEP_0) {
+		/* nothing */
+	} else if (*tune_state == CT_TUNER_STEP_1) {
+		state->step /= 2;
+		dib0090_write_reg(state, 0x18, lo4 | state->captrim);
+		*tune_state = CT_TUNER_STEP_2;
+	} else if (*tune_state == CT_TUNER_STEP_2) {
+
+		adc = dib0090_read_reg(state, 0x1d);
+		dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc,
+			(u32) (adc) * (u32) 1800 / (u32) 1024);
+
+		if (adc >= 400) {
+			adc -= 400;
+			step_sign = -1;
+		} else {
+			adc = 400 - adc;
+			step_sign = 1;
+		}
+
+		if (adc < state->adc_diff) {
+			dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
+			state->adc_diff = adc;
+			state->fcaptrim = state->captrim;
+
+		}
+
+		state->captrim += step_sign * state->step;
+		if (state->step >= 1)
+			*tune_state = CT_TUNER_STEP_1;
+		else
+			*tune_state = CT_TUNER_STEP_3;
+
+		ret = 15;
+	} else if (*tune_state == CT_TUNER_STEP_3) {
+		/*write the final cptrim config */
+		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
+
+#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
+		state->memory[state->memory_index].cap = state->fcaptrim;
+#endif
+
+		*tune_state = CT_TUNER_STEP_4;
+	} else if (*tune_state == CT_TUNER_STEP_4) {
+		dib0090_write_reg(state, 0x1e, 0x07ff);
+
+		dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim);
+		dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code);
+		dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band);
+		dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf);
+		dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz);
+		dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
+		dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17),
+			(u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3);
+
+		c = 4;
+		i = 3;
+#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
+		if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) {
+			c = 2;
+			i = 2;
+		}
+#endif
+		dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD
+#ifdef CONFIG_DIB0090_USE_PWM_AGC
+									| (state->config->use_pwm_agc << 1)
+#endif
+				  ));
+		dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0));
+		dib0090_write_reg(state, 0x0c, tune->v2i);
+		dib0090_write_reg(state, 0x0d, tune->mix);
+		dib0090_write_reg(state, 0x0e, tune->load);
+
+		*tune_state = CT_TUNER_STEP_5;
+	} else if (*tune_state == CT_TUNER_STEP_5) {
+
+		/* initialize the lt gain register */
+		state->rf_lt_def = 0x7c00;
+		dib0090_write_reg(state, 0x0f, state->rf_lt_def);
+
+		dib0090_set_bandwidth(state);
+		state->tuner_is_tuned = 1;
+		*tune_state = CT_TUNER_STOP;
+	} else
+		ret = FE_CALLBACK_TIME_NEVER;
+	return ret;
+}
+
+static int dib0090_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	return state->tune_state;
+}
+EXPORT_SYMBOL(dib0090_get_tune_state);
+
+int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	state->tune_state = tune_state;
+	return 0;
+}
+EXPORT_SYMBOL(dib0090_set_tune_state);
+
+static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	*frequency = 1000 * state->current_rf;
+	return 0;
+}
+
+static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	uint32_t ret;
+
+	state->tune_state = CT_TUNER_START;
+
+	do {
+		ret = dib0090_tune(fe);
+		if (ret != FE_CALLBACK_TIME_NEVER)
+			msleep(ret / 10);
+		else
+			break;
+	} while (state->tune_state != CT_TUNER_STOP);
+
+	return 0;
+}
+
+static const struct dvb_tuner_ops dib0090_ops = {
+	.info = {
+		 .name = "DiBcom DiB0090",
+		 .frequency_min = 45000000,
+		 .frequency_max = 860000000,
+		 .frequency_step = 1000,
+		 },
+	.release = dib0090_release,
+
+	.init = dib0090_wakeup,
+	.sleep = dib0090_sleep,
+	.set_params = dib0090_set_params,
+	.get_frequency = dib0090_get_frequency,
+};
+
+struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
+{
+	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->config = config;
+	st->i2c = i2c;
+	st->fe = fe;
+	fe->tuner_priv = st;
+
+	if (dib0090_reset(fe) != 0)
+		goto free_mem;
+
+	printk(KERN_INFO "DiB0090: successfully identified\n");
+	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
+
+	return fe;
+ free_mem:
+	kfree(st);
+	fe->tuner_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(dib0090_register);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h
new file mode 100644
index 0000000..aa7711e
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0090.h
@@ -0,0 +1,108 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
+ */
+#ifndef DIB0090_H
+#define DIB0090_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
+
+struct dib0090_io_config {
+	u32 clock_khz;
+
+	u8 pll_bypass:1;
+	u8 pll_range:1;
+	u8 pll_prediv:6;
+	u8 pll_loopdiv:6;
+
+	u8 adc_clock_ratio;	/* valid is 8, 7 ,6 */
+	u16 pll_int_loop_filt;
+};
+
+struct dib0090_config {
+	struct dib0090_io_config io;
+	int (*reset) (struct dvb_frontend *, int);
+	int (*sleep) (struct dvb_frontend *, int);
+
+	/*  offset in kHz */
+	int freq_offset_khz_uhf;
+	int freq_offset_khz_vhf;
+
+	int (*get_adc_power) (struct dvb_frontend *);
+
+	u8 clkouttobamse:1;	/* activate or deactivate clock output */
+	u8 analog_output;
+
+	u8 i2c_address;
+	/* add drives and other things if necessary */
+	u16 wbd_vhf_offset;
+	u16 wbd_cband_offset;
+	u8 use_pwm_agc;
+	u8 clkoutdrive;
+};
+
+#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
+extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
+extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
+extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
+extern int dib0090_gain_control(struct dvb_frontend *fe);
+extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
+extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
+#else
+static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int dib0090_gain_control(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return CT_DONE;
+}
+
+static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index 898400d..6f6fa29 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -28,18 +28,6 @@
 
 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
 
-enum frontend_tune_state {
-	CT_AGC_START = 20,
-	CT_AGC_STEP_0,
-	CT_AGC_STEP_1,
-	CT_AGC_STEP_2,
-	CT_AGC_STEP_3,
-	CT_AGC_STEP_4,
-	CT_AGC_STOP,
-
-	CT_DEMOD_START = 30,
-};
-
 #define FE_STATUS_TUNE_FAILED 0
 
 struct i2c_device {
@@ -133,104 +121,104 @@
 	return dib8000_i2c_write16(&state->i2c, reg, val);
 }
 
-const int16_t coeff_2k_sb_1seg_dqpsk[8] = {
+static const int16_t coeff_2k_sb_1seg_dqpsk[8] = {
 	(769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
 	    (920 << 5) | 0x09
 };
 
-const int16_t coeff_2k_sb_1seg[8] = {
+static const int16_t coeff_2k_sb_1seg[8] = {
 	(692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
 };
 
-const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
 	    (-931 << 5) | 0x0f
 };
 
-const int16_t coeff_2k_sb_3seg_0dqpsk[8] = {
+static const int16_t coeff_2k_sb_3seg_0dqpsk[8] = {
 	(622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
 	    (982 << 5) | 0x0c
 };
 
-const int16_t coeff_2k_sb_3seg_1dqpsk[8] = {
+static const int16_t coeff_2k_sb_3seg_1dqpsk[8] = {
 	(699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
 	    (-720 << 5) | 0x0d
 };
 
-const int16_t coeff_2k_sb_3seg[8] = {
+static const int16_t coeff_2k_sb_3seg[8] = {
 	(664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
 	    (-610 << 5) | 0x0a
 };
 
-const int16_t coeff_4k_sb_1seg_dqpsk[8] = {
+static const int16_t coeff_4k_sb_1seg_dqpsk[8] = {
 	(-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
 	    (-922 << 5) | 0x0d
 };
 
-const int16_t coeff_4k_sb_1seg[8] = {
+static const int16_t coeff_4k_sb_1seg[8] = {
 	(638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
 	    (-655 << 5) | 0x0a
 };
 
-const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
 	    (-958 << 5) | 0x13
 };
 
-const int16_t coeff_4k_sb_3seg_0dqpsk[8] = {
+static const int16_t coeff_4k_sb_3seg_0dqpsk[8] = {
 	(-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
 	    (-568 << 5) | 0x0f
 };
 
-const int16_t coeff_4k_sb_3seg_1dqpsk[8] = {
+static const int16_t coeff_4k_sb_3seg_1dqpsk[8] = {
 	(-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
 	    (-848 << 5) | 0x13
 };
 
-const int16_t coeff_4k_sb_3seg[8] = {
+static const int16_t coeff_4k_sb_3seg[8] = {
 	(612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
 	    (-869 << 5) | 0x13
 };
 
-const int16_t coeff_8k_sb_1seg_dqpsk[8] = {
+static const int16_t coeff_8k_sb_1seg_dqpsk[8] = {
 	(-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
 	    (-598 << 5) | 0x10
 };
 
-const int16_t coeff_8k_sb_1seg[8] = {
+static const int16_t coeff_8k_sb_1seg[8] = {
 	(673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
 	    (585 << 5) | 0x0f
 };
 
-const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
 	    (0 << 5) | 0x14
 };
 
-const int16_t coeff_8k_sb_3seg_0dqpsk[8] = {
+static const int16_t coeff_8k_sb_3seg_0dqpsk[8] = {
 	(-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
 	    (-877 << 5) | 0x15
 };
 
-const int16_t coeff_8k_sb_3seg_1dqpsk[8] = {
+static const int16_t coeff_8k_sb_3seg_1dqpsk[8] = {
 	(-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
 	    (-921 << 5) | 0x14
 };
 
-const int16_t coeff_8k_sb_3seg[8] = {
+static const int16_t coeff_8k_sb_3seg[8] = {
 	(514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
 	    (690 << 5) | 0x14
 };
 
-const int16_t ana_fe_coeff_3seg[24] = {
+static const int16_t ana_fe_coeff_3seg[24] = {
 	81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
 };
 
-const int16_t ana_fe_coeff_1seg[24] = {
+static const int16_t ana_fe_coeff_1seg[24] = {
 	249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
 };
 
-const int16_t ana_fe_coeff_13seg[24] = {
+static const int16_t ana_fe_coeff_13seg[24] = {
 	396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
 };
 
@@ -852,6 +840,14 @@
 	return 0;
 }
 
+void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	dib8000_set_adc_state(state, DIBX000_ADC_ON);
+	dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
+}
+EXPORT_SYMBOL(dib8000_pwm_agc_reset);
+
 static int dib8000_agc_soft_split(struct dib8000_state *state)
 {
 	u16 agc, split_offset;
@@ -939,6 +935,32 @@
 
 }
 
+static const int32_t lut_1000ln_mant[] =
+{
+	908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
+};
+
+int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode)
+{
+    struct dib8000_state *state = fe->demodulator_priv;
+    uint32_t ix = 0, tmp_val = 0, exp = 0, mant = 0;
+    int32_t val;
+
+    val = dib8000_read32(state, 384);
+    /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */
+    if (mode) {
+	tmp_val = val;
+	while (tmp_val >>= 1)
+		exp++;
+	mant = (val * 1000 / (1<<exp));
+	ix = (uint8_t)((mant-1000)/100); /* index of the LUT */
+	val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */
+	val = (val*256)/1000;
+    }
+    return val;
+}
+EXPORT_SYMBOL(dib8000_get_adc_power);
+
 static void dib8000_update_timf(struct dib8000_state *state)
 {
 	u32 timf = state->timf = dib8000_read32(state, 435);
@@ -1401,10 +1423,9 @@
 			}
 			break;
 		}
-	}
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1)
 		for (i = 0; i < 8; i++)
 			dib8000_write_word(state, 343 + i, ncoeff[i]);
+	}
 
 	// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
 	dib8000_write_word(state, 351,
@@ -1854,6 +1875,24 @@
 	}
 }
 
+enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	return state->tune_state;
+}
+EXPORT_SYMBOL(dib8000_get_tune_state);
+
+int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	state->tune_state = tune_state;
+	return 0;
+}
+EXPORT_SYMBOL(dib8000_set_tune_state);
+
+
+
+
 static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
@@ -2043,29 +2082,31 @@
 
 	*stat = 0;
 
-	if ((lock >> 14) & 1)	// AGC
+	if ((lock >> 13) & 1)
 		*stat |= FE_HAS_SIGNAL;
 
-	if ((lock >> 8) & 1)	// Equal
+	if ((lock >> 8) & 1) /* Equal */
 		*stat |= FE_HAS_CARRIER;
 
-	if ((lock >> 3) & 1)	// TMCC_SYNC
+	if (((lock >> 1) & 0xf) == 0xf) /* TMCC_SYNC */
 		*stat |= FE_HAS_SYNC;
 
-	if ((lock >> 5) & 7)	// FEC MPEG
+	if (((lock >> 12) & 1) && ((lock >> 5) & 7)) /* FEC MPEG */
 		*stat |= FE_HAS_LOCK;
 
-	lock = dib8000_read_word(state, 554);	// Viterbi Layer A
-	if (lock & 0x01)
-		*stat |= FE_HAS_VITERBI;
+	if ((lock >> 12) & 1) {
+		lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
 
-	lock = dib8000_read_word(state, 555);	// Viterbi Layer B
-	if (lock & 0x01)
-		*stat |= FE_HAS_VITERBI;
+		lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
 
-	lock = dib8000_read_word(state, 556);	// Viterbi Layer C
-	if (lock & 0x01)
-		*stat |= FE_HAS_VITERBI;
+		lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
+	}
 
 	return 0;
 }
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h
index 8c89482..d99619a 100644
--- a/drivers/media/dvb/frontends/dib8000.h
+++ b/drivers/media/dvb/frontends/dib8000.h
@@ -46,6 +46,10 @@
 extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
 extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
 extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
+extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
+extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
+extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
 #else
 static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
 {
@@ -59,35 +63,53 @@
 	return NULL;
 }
 
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
+static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+    return CT_SHUTDOWN,
+}
+static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
 #endif
 
 #endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index 4efca30..e6f3d73 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -6,7 +6,7 @@
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
 
 static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
 {
@@ -25,7 +25,7 @@
 					enum dibx000_i2c_interface intf)
 {
 	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
-		dprintk("selecting interface: %d\n", intf);
+		dprintk("selecting interface: %d", intf);
 		mst->selected_interface = intf;
 		return dibx000_write_word(mst, mst->base_reg + 4, intf);
 	}
@@ -171,9 +171,18 @@
 {
 	i2c_del_adapter(&mst->gated_tuner_i2c_adap);
 }
-
 EXPORT_SYMBOL(dibx000_exit_i2c_master);
 
+
+u32 systime()
+{
+    struct timespec t;
+
+    t = current_kernel_time();
+    return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
+}
+EXPORT_SYMBOL(systime);
+
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
 MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index 5be10ec..4f5d141 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -36,13 +36,17 @@
 extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
 extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
 
+extern u32 systime(void);
+
 #define BAND_LBAND 0x01
 #define BAND_UHF   0x02
 #define BAND_VHF   0x04
 #define BAND_SBAND 0x08
-#define BAND_FM	   0x10
+#define BAND_FM    0x10
+#define BAND_CBAND 0x20
 
-#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
+#define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \
+									(freq_kHz) <= 115000 ? BAND_FM : \
 									(freq_kHz) <= 250000 ? BAND_VHF : \
 									(freq_kHz) <= 863000 ? BAND_UHF : \
 									(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
@@ -149,4 +153,67 @@
 #define OUTMODE_MPEG2_FIFO          5
 #define OUTMODE_ANALOG_ADC          6
 
+enum frontend_tune_state {
+    CT_TUNER_START = 10,
+    CT_TUNER_STEP_0,
+    CT_TUNER_STEP_1,
+    CT_TUNER_STEP_2,
+    CT_TUNER_STEP_3,
+    CT_TUNER_STEP_4,
+    CT_TUNER_STEP_5,
+    CT_TUNER_STEP_6,
+    CT_TUNER_STEP_7,
+    CT_TUNER_STOP,
+
+    CT_AGC_START = 20,
+    CT_AGC_STEP_0,
+    CT_AGC_STEP_1,
+    CT_AGC_STEP_2,
+    CT_AGC_STEP_3,
+    CT_AGC_STEP_4,
+    CT_AGC_STOP,
+
+	CT_DEMOD_START = 30,
+    CT_DEMOD_STEP_1,
+    CT_DEMOD_STEP_2,
+    CT_DEMOD_STEP_3,
+    CT_DEMOD_STEP_4,
+    CT_DEMOD_STEP_5,
+    CT_DEMOD_STEP_6,
+    CT_DEMOD_STEP_7,
+    CT_DEMOD_STEP_8,
+    CT_DEMOD_STEP_9,
+    CT_DEMOD_STEP_10,
+    CT_DEMOD_SEARCH_NEXT = 41,
+    CT_DEMOD_STEP_LOCKED,
+    CT_DEMOD_STOP,
+
+    CT_DONE = 100,
+    CT_SHUTDOWN,
+
+};
+
+struct dvb_frontend_parametersContext {
+#define CHANNEL_STATUS_PARAMETERS_UNKNOWN   0x01
+#define CHANNEL_STATUS_PARAMETERS_SET       0x02
+    u8 status;
+    u32 tune_time_estimation[2];
+    s32 tps_available;
+    u16 tps[9];
+};
+
+#define FE_STATUS_TUNE_FAILED          0
+#define FE_STATUS_TUNE_TIMED_OUT      -1
+#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
+#define FE_STATUS_TUNE_PENDING        -3
+#define FE_STATUS_STD_SUCCESS         -4
+#define FE_STATUS_FFT_SUCCESS         -5
+#define FE_STATUS_DEMOD_SUCCESS       -6
+#define FE_STATUS_LOCKED              -7
+#define FE_STATUS_DATA_LOCKED         -8
+
+#define FE_CALLBACK_TIME_NEVER 0xffffffff
+
+#define ABS(x) ((x < 0) ? (-x) : (x))
+
 #endif
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
index eabcadc..dee5396 100644
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ b/drivers/media/dvb/frontends/lgs8gxx.c
@@ -199,7 +199,7 @@
 
 	val = freq;
 	if (freq != 0) {
-		val *= (u64)1 << 32;
+		val <<= 32;
 		if (if_clk != 0)
 			do_div(val, if_clk);
 		v32 = val & 0xFFFFFFFF;
@@ -246,7 +246,7 @@
 
 	val = v32;
 	val *= priv->config->if_clk_freq;
-	val /= (u64)1 << 32;
+	val >>= 32;
 	dprintk("AFC = %u kHz\n", (u32)val);
 	return 0;
 }
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
index 71f607f..b181bf0 100644
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -1,7 +1,7 @@
 /*
  * lnbp21.c - driver for lnb supply and control ic lnbp21
  *
- * Copyright (C) 2006 Oliver Endriss
+ * Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de>
  * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
  *
  * This program is free software; you can redistribute it and/or
@@ -91,6 +91,31 @@
 	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
 }
 
+static int lnbp21_set_tone(struct dvb_frontend *fe,
+				fe_sec_tone_mode_t tone)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		lnbp21->config &= ~LNBP21_TEN;
+		break;
+	case SEC_TONE_ON:
+		lnbp21->config |= LNBP21_TEN;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
 static void lnbp21_release(struct dvb_frontend *fe)
 {
 	/* LNBP power off */
@@ -133,6 +158,7 @@
 	/* override frontend ops */
 	fe->ops.set_voltage = lnbp21_set_voltage;
 	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+	fe->ops.set_tone = lnbp21_set_tone;
 	printk(KERN_INFO "LNBx2x attached on addr=%x\n", lnbp21->i2c_addr);
 
 	return fe;
diff --git a/drivers/media/dvb/frontends/stv0900_core.c b/drivers/media/dvb/frontends/stv0900_core.c
index df49ea0..8762c86 100644
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ b/drivers/media/dvb/frontends/stv0900_core.c
@@ -1451,6 +1451,8 @@
 {
 	enum fe_stv0900_search_state demod_state;
 	int locked = FALSE;
+	u8 tsbitrate0_val, tsbitrate1_val;
+	s32 bitrate;
 
 	demod_state = stv0900_get_bits(intp, HEADER_MODE);
 	switch (demod_state) {
@@ -1473,6 +1475,17 @@
 
 	dprintk("%s: locked = %d\n", __func__, locked);
 
+	if (stvdebug) {
+		/* Print TS bitrate */
+		tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0);
+		tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1);
+		/* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */
+		bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
+			* (tsbitrate1_val << 8 | tsbitrate0_val);
+		bitrate /= 16384;
+		dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
+	};
+
 	return locked;
 }
 
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
index 48edd54..1573466 100644
--- a/drivers/media/dvb/frontends/stv090x.c
+++ b/drivers/media/dvb/frontends/stv090x.c
@@ -3597,7 +3597,8 @@
 
 	reg = STV090x_READ_DEMOD(state, DISTXCTL);
 
-	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 2);
+	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD,
+		(state->config->diseqc_envelope_mode) ? 4 : 2);
 	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
 	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
 		goto err;
@@ -3649,10 +3650,10 @@
 	reg = STV090x_READ_DEMOD(state, DISTXCTL);
 
 	if (burst == SEC_MINI_A) {
-		mode = 3;
+		mode = (state->config->diseqc_envelope_mode) ? 5 : 3;
 		value = 0x00;
 	} else {
-		mode = 2;
+		mode = (state->config->diseqc_envelope_mode) ? 4 : 2;
 		value = 0xFF;
 	}
 
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h
index e968c98..b133807 100644
--- a/drivers/media/dvb/frontends/stv090x.h
+++ b/drivers/media/dvb/frontends/stv090x.h
@@ -75,6 +75,8 @@
 
 	enum stv090x_i2crpt	repeater_level;
 
+	bool diseqc_envelope_mode;
+
 	int (*tuner_init) (struct dvb_frontend *fe);
 	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
 	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
index 266033a..68bf9fb 100644
--- a/drivers/media/dvb/siano/smsdvb.c
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -662,7 +662,7 @@
 	return rc;
 }
 
-int smsdvb_module_init(void)
+static int __init smsdvb_module_init(void)
 {
 	int rc;
 
@@ -676,7 +676,7 @@
 	return rc;
 }
 
-void smsdvb_module_exit(void)
+static void __exit smsdvb_module_exit(void)
 {
 	smscore_unregister_hotplug(smsdvb_hotplug);
 
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
index 24206cb..195244a 100644
--- a/drivers/media/dvb/siano/smssdio.c
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -48,7 +48,7 @@
 #define SMSSDIO_INT		0x04
 #define SMSSDIO_BLOCK_SIZE	128
 
-static const struct sdio_device_id smssdio_ids[] = {
+static const struct sdio_device_id smssdio_ids[] __devinitconst = {
 	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
 	 .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
 	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
@@ -222,7 +222,7 @@
 	smscore_onresponse(smsdev->coredev, cb);
 }
 
-static int smssdio_probe(struct sdio_func *func,
+static int __devinit smssdio_probe(struct sdio_func *func,
 			 const struct sdio_device_id *id)
 {
 	int ret;
@@ -338,7 +338,7 @@
 /* Module functions                                                */
 /*******************************************************************/
 
-int smssdio_module_init(void)
+static int __init smssdio_module_init(void)
 {
 	int ret = 0;
 
@@ -350,7 +350,7 @@
 	return ret;
 }
 
-void smssdio_module_exit(void)
+static void __exit smssdio_module_exit(void)
 {
 	sdio_unregister_driver(&smssdio_driver);
 }
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 8f88a58..5eac272 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -390,7 +390,7 @@
 	return rc;
 }
 
-static int smsusb_probe(struct usb_interface *intf,
+static int __devinit smsusb_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
@@ -484,7 +484,7 @@
 	return 0;
 }
 
-struct usb_device_id smsusb_id_table[] = {
+static const struct usb_device_id smsusb_id_table[] __devinitconst = {
 	{ USB_DEVICE(0x187f, 0x0010),
 		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
 	{ USB_DEVICE(0x187f, 0x0100),
@@ -533,8 +533,18 @@
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0xb910),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xb980),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xb990),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0xc000),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc010),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc080),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+	{ USB_DEVICE(0x2040, 0xc090),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ } /* Terminating entry */
 	};
 
@@ -550,7 +560,7 @@
 	.resume			= smsusb_resume,
 };
 
-int smsusb_module_init(void)
+static int __init smsusb_module_init(void)
 {
 	int rc = usb_register(&smsusb_driver);
 	if (rc)
@@ -561,7 +571,7 @@
 	return rc;
 }
 
-void smsusb_module_exit(void)
+static void __exit smsusb_module_exit(void)
 {
 	/* Regular USB Cleanup */
 	usb_deregister(&smsusb_driver);
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 7d193eb..9782e05 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -190,12 +190,13 @@
 	struct saa7146_dev *saa = budget_ci->budget.dev;
 	struct input_dev *input_dev = budget_ci->ir.dev;
 	int error;
+	struct ir_scancode_table *ir_codes;
+
 
 	budget_ci->ir.dev = input_dev = input_allocate_device();
 	if (!input_dev) {
 		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
-		error = -ENOMEM;
-		goto out1;
+		return -ENOMEM;
 	}
 
 	snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
@@ -217,6 +218,11 @@
 	}
 	input_dev->dev.parent = &saa->pci->dev;
 
+	if (rc5_device < 0)
+		budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+	else
+		budget_ci->ir.rc5_device = rc5_device;
+
 	/* Select keymap and address */
 	switch (budget_ci->budget.dev->pci->subsystem_device) {
 	case 0x100c:
@@ -224,53 +230,34 @@
 	case 0x1011:
 	case 0x1012:
 		/* The hauppauge keymap is a superset of these remotes */
-		error = ir_input_init(input_dev, &budget_ci->ir.state,
-			      IR_TYPE_RC5, &ir_codes_hauppauge_new_table);
-		if (error < 0)
-			goto out2;
+		ir_codes = &ir_codes_hauppauge_new_table;
 
 		if (rc5_device < 0)
 			budget_ci->ir.rc5_device = 0x1f;
-		else
-			budget_ci->ir.rc5_device = rc5_device;
 		break;
 	case 0x1010:
 	case 0x1017:
 	case 0x101a:
 		/* for the Technotrend 1500 bundled remote */
-		error = ir_input_init(input_dev, &budget_ci->ir.state,
-			      IR_TYPE_RC5, &ir_codes_tt_1500_table);
-		if (error < 0)
-			goto out2;
-
-		if (rc5_device < 0)
-			budget_ci->ir.rc5_device = IR_DEVICE_ANY;
-		else
-			budget_ci->ir.rc5_device = rc5_device;
+		ir_codes = &ir_codes_tt_1500_table;
 		break;
 	default:
 		/* unknown remote */
-		error = ir_input_init(input_dev, &budget_ci->ir.state,
-			      IR_TYPE_RC5, &ir_codes_budget_ci_old_table);
-		if (error < 0)
-			goto out2;
-
-		if (rc5_device < 0)
-			budget_ci->ir.rc5_device = IR_DEVICE_ANY;
-		else
-			budget_ci->ir.rc5_device = rc5_device;
+		ir_codes = &ir_codes_budget_ci_old_table;
 		break;
 	}
 
+	ir_input_init(input_dev, &budget_ci->ir.state, IR_TYPE_RC5);
+
 	/* initialise the key-up timeout handler */
 	init_timer(&budget_ci->ir.timer_keyup);
 	budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
 	budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
 	budget_ci->ir.last_raw = 0xffff; /* An impossible value */
-	error = input_register_device(input_dev);
+	error = ir_input_register(input_dev, ir_codes);
 	if (error) {
 		printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
-		goto out2;
+		return error;
 	}
 
 	/* note: these must be after input_register_device */
@@ -284,12 +271,6 @@
 	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
 	return 0;
-
-out2:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
-out1:
-	return error;
 }
 
 static void msp430_ir_deinit(struct budget_ci *budget_ci)
@@ -304,8 +285,7 @@
 	del_timer_sync(&dev->timer);
 	ir_input_nokey(dev, &budget_ci->ir.state);
 
-	ir_input_free(dev);
-	input_unregister_device(dev);
+	ir_input_unregister(dev);
 }
 
 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 4c2b8a2..3f40f37 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -215,13 +215,10 @@
 	  module will be called radio-miropcm20.
 
 config RADIO_SF16FMI
-	tristate "SF16FMI Radio"
+	tristate "SF16-FMI/SF16-FMP Radio"
 	depends on ISA && VIDEO_V4L2
 	---help---
-	  Choose Y here if you have one of these FM radio cards.  If you
-	  compile the driver into the kernel and your card is not PnP one, you
-	  have to add "sf16fm=<io>" to the kernel command line (I/O address is
-	  0x284 or 0x384).
+	  Choose Y here if you have one of these FM radio cards.
 
 	  In order to control your radio card, you will need to use programs
 	  that are compatible with the Video For Linux API.  Information on
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 35edee0..5bf4985 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -268,6 +268,8 @@
 {
 	struct rtrack *rt = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	rt_setfreq(rt, f->frequency);
 	return 0;
 }
@@ -277,6 +279,8 @@
 {
 	struct rtrack *rt = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = rt->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 8daf809e..c223113 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -254,6 +254,8 @@
 {
 	struct aztech *az = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	az_setfreq(az, f->frequency);
 	return 0;
 }
@@ -263,6 +265,8 @@
 {
 	struct aztech *az = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = az->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index c6cf116..000f4d3 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -240,6 +240,8 @@
 {
 	struct gemtek_pci *card = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (f->frequency < GEMTEK_PCI_RANGE_LOW ||
 	    f->frequency > GEMTEK_PCI_RANGE_HIGH)
 		return -EINVAL;
@@ -253,6 +255,8 @@
 {
 	struct gemtek_pci *card = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = card->current_frequency;
 	return 0;
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 64d737c..f8213b7 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -200,6 +200,8 @@
 {
 	struct maestro *dev = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI)
 		return -EINVAL;
 	mutex_lock(&dev->lock);
@@ -213,6 +215,8 @@
 {
 	struct maestro *dev = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	mutex_lock(&dev->lock);
 	f->frequency = BITS2FREQ(radio_bits_get(dev));
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 3da51fe..44b4dbe 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -262,6 +262,8 @@
 {
 	struct maxiradio *dev = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) {
 		dprintk(dev, 1, "radio freq (%d.%02d MHz) out of range (%d-%d)\n",
 					f->frequency / 16000,
@@ -285,6 +287,8 @@
 {
 	struct maxiradio *dev = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = dev->freq;
 
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index 949f605..02a9cef 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -374,6 +374,8 @@
 {
 	struct amradio_device *radio = file->private_data;
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	return amradio_setfreq(radio, f->frequency);
 }
 
@@ -383,6 +385,8 @@
 {
 	struct amradio_device *radio = file->private_data;
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = radio->curfreq;
 
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 9cb193f..a79296a 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -167,6 +167,8 @@
 {
 	struct rtrack2 *rt = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	rt_setfreq(rt, f->frequency);
 	return 0;
 }
@@ -176,6 +178,8 @@
 {
 	struct rtrack2 *rt = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = rt->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 49c4aab..985359d1 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -1,4 +1,4 @@
-/* SF16FMI radio driver for Linux radio support
+/* SF16-FMI and SF16-FMP radio driver for Linux radio support
  * heavily based on rtrack driver...
  * (c) 1997 M. Kirkwood
  * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
@@ -11,7 +11,7 @@
  *
  *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
  *  No volume control - only mute/unmute - you have to use line volume
- *  control on SB-part of SF16FMI
+ *  control on SB-part of SF16-FMI/SF16-FMP
  *
  * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
  */
@@ -30,14 +30,14 @@
 #include <media/v4l2-ioctl.h>
 
 MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
-MODULE_DESCRIPTION("A driver for the SF16MI radio.");
+MODULE_DESCRIPTION("A driver for the SF16-FMI and SF16-FMP radio.");
 MODULE_LICENSE("GPL");
 
 static int io = -1;
 static int radio_nr = -1;
 
 module_param(io, int, 0);
-MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
+MODULE_PARM_DESC(io, "I/O address of the SF16-FMI or SF16-FMP card (0x284 or 0x384)");
 module_param(radio_nr, int, 0);
 
 #define RADIO_VERSION KERNEL_VERSION(0, 0, 2)
@@ -47,13 +47,14 @@
 	struct v4l2_device v4l2_dev;
 	struct video_device vdev;
 	int io;
-	int curvol; /* 1 or 0 */
+	bool mute;
 	unsigned long curfreq; /* freq in kHz */
 	struct mutex lock;
 };
 
 static struct fmi fmi_card;
 static struct pnp_dev *dev;
+bool pnp_attached;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
 /* It is only useful to give freq in interval of 800 (=0.05Mhz),
@@ -105,7 +106,7 @@
 	outbits(8, 0xC0, fmi->io);
 	msleep(143);		/* was schedule_timeout(HZ/7) */
 	mutex_unlock(&fmi->lock);
-	if (fmi->curvol)
+	if (!fmi->mute)
 		fmi_unmute(fmi);
 	return 0;
 }
@@ -116,7 +117,7 @@
 	int res;
 
 	mutex_lock(&fmi->lock);
-	val = fmi->curvol ? 0x08 : 0x00;	/* unmute/mute */
+	val = fmi->mute ? 0x00 : 0x08;	/* mute/unmute */
 	outb(val, fmi->io);
 	outb(val | 0x10, fmi->io);
 	msleep(143); 		/* was schedule_timeout(HZ/7) */
@@ -168,6 +169,8 @@
 {
 	struct fmi *fmi = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (f->frequency < RSF16_MINFREQ ||
 			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
@@ -182,6 +185,8 @@
 {
 	struct fmi *fmi = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmi->curfreq;
 	return 0;
@@ -204,7 +209,7 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = fmi->curvol;
+		ctrl->value = fmi->mute;
 		return 0;
 	}
 	return -EINVAL;
@@ -221,7 +226,7 @@
 			fmi_mute(fmi);
 		else
 			fmi_unmute(fmi);
-		fmi->curvol = ctrl->value;
+		fmi->mute = ctrl->value;
 		return 0;
 	}
 	return -EINVAL;
@@ -316,26 +321,54 @@
 {
 	struct fmi *fmi = &fmi_card;
 	struct v4l2_device *v4l2_dev = &fmi->v4l2_dev;
-	int res;
+	int res, i;
+	int probe_ports[] = { 0, 0x284, 0x384 };
 
-	if (io < 0)
-		io = isapnp_fmi_probe();
+	if (io < 0) {
+		for (i = 0; i < ARRAY_SIZE(probe_ports); i++) {
+			io = probe_ports[i];
+			if (io == 0) {
+				io = isapnp_fmi_probe();
+				if (io < 0)
+					continue;
+				pnp_attached = 1;
+			}
+			if (!request_region(io, 2, "radio-sf16fmi")) {
+				if (pnp_attached)
+					pnp_device_detach(dev);
+				io = -1;
+				continue;
+			}
+			if (pnp_attached ||
+			    ((inb(io) & 0xf9) == 0xf9 && (inb(io) & 0x4) == 0))
+				break;
+			release_region(io, 2);
+			io = -1;
+		}
+	} else {
+		if (!request_region(io, 2, "radio-sf16fmi")) {
+			printk(KERN_ERR "radio-sf16fmi: port %#x already in use\n", io);
+			return -EBUSY;
+		}
+		if (inb(io) == 0xff) {
+			printk(KERN_ERR "radio-sf16fmi: card not present at %#x\n", io);
+			release_region(io, 2);
+			return -ENODEV;
+		}
+	}
+	if (io < 0) {
+		printk(KERN_ERR "radio-sf16fmi: no cards found\n");
+		return -ENODEV;
+	}
+
 	strlcpy(v4l2_dev->name, "sf16fmi", sizeof(v4l2_dev->name));
 	fmi->io = io;
-	if (fmi->io < 0) {
-		v4l2_err(v4l2_dev, "No PnP card found.\n");
-		return fmi->io;
-	}
-	if (!request_region(io, 2, "radio-sf16fmi")) {
-		v4l2_err(v4l2_dev, "port 0x%x already in use\n", fmi->io);
-		pnp_device_detach(dev);
-		return -EBUSY;
-	}
 
 	res = v4l2_device_register(NULL, v4l2_dev);
 	if (res < 0) {
 		release_region(fmi->io, 2);
-		pnp_device_detach(dev);
+		if (pnp_attached)
+			pnp_device_detach(dev);
 		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
 		return res;
 	}
@@ -352,7 +385,8 @@
 	if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
 		v4l2_device_unregister(v4l2_dev);
 		release_region(fmi->io, 2);
-		pnp_device_detach(dev);
+		if (pnp_attached)
+			pnp_device_detach(dev);
 		return -EINVAL;
 	}
 
@@ -369,7 +403,7 @@
 	video_unregister_device(&fmi->vdev);
 	v4l2_device_unregister(&fmi->v4l2_dev);
 	release_region(fmi->io, 2);
-	if (dev)
+	if (dev && pnp_attached)
 		pnp_device_detach(dev);
 }
 
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index a11414f..52c7bbb 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -251,6 +251,8 @@
 {
 	struct fmr2 *fmr2 = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (f->frequency < RSF16_MINFREQ ||
 			f->frequency > RSF16_MAXFREQ)
 		return -EINVAL;
@@ -272,6 +274,8 @@
 {
 	struct fmr2 *fmr2 = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = fmr2->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 3cd76dd..8e718bf 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -314,7 +314,7 @@
 	if (v->index > 0)
 		return -EINVAL;
 
-	memset(v, 0, sizeof(v));
+	memset(v, 0, sizeof(*v));
 	strcpy(v->name, "FM");
 	v->type = V4L2_TUNER_RADIO;
 	tea5764_i2c_read(radio);
@@ -349,7 +349,7 @@
 {
 	struct tea5764_device *radio = video_drvdata(file);
 
-	if (f->tuner != 0)
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
 		return -EINVAL;
 	if (f->frequency == 0) {
 		/* We special case this as a power down control. */
@@ -370,8 +370,10 @@
 	struct tea5764_device *radio = video_drvdata(file);
 	struct tea5764_regs *r = &radio->regs;
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	tea5764_i2c_read(radio);
-	memset(f, 0, sizeof(f));
+	memset(f, 0, sizeof(*f));
 	f->type = V4L2_TUNER_RADIO;
 	if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
 		f->frequency = (tea5764_get_freq(radio) * 2) / 125;
@@ -458,12 +460,8 @@
 static int tea5764_open(struct file *file)
 {
 	/* Currently we support only one device */
-	int minor = video_devdata(file)->minor;
 	struct tea5764_device *radio = video_drvdata(file);
 
-	if (radio->videodev->minor != minor)
-		return -ENODEV;
-
 	mutex_lock(&radio->mutex);
 	/* Only exclusive access */
 	if (radio->users) {
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 699db9a..fc1c860 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -240,6 +240,8 @@
 {
 	struct terratec *tt = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	tt_setfreq(tt, f->frequency);
 	return 0;
 }
@@ -249,6 +251,8 @@
 {
 	struct terratec *tt = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = tt->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index 6f9ecc3..9d6dcf8 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -239,6 +239,8 @@
 {
 	struct trust *tr = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	tr_setfreq(tr, f->frequency);
 	return 0;
 }
@@ -248,6 +250,8 @@
 {
 	struct trust *tr = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = tr->curfreq;
 	return 0;
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 3a98f13..0343928 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -207,6 +207,8 @@
 {
 	struct typhoon *dev = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = dev->curfreq;
 	return 0;
@@ -217,6 +219,8 @@
 {
 	struct typhoon *dev = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	dev->curfreq = f->frequency;
 	typhoon_setfreq(dev, dev->curfreq);
 	return 0;
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 80e98b6..f31eab9 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -266,6 +266,8 @@
 {
 	struct zoltrix *zol = video_drvdata(file);
 
+	if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
 	if (zol_setfreq(zol, f->frequency) != 0)
 		return -EINVAL;
 	return 0;
@@ -276,6 +278,8 @@
 {
 	struct zoltrix *zol = video_drvdata(file);
 
+	if (f->tuner != 0)
+		return -EINVAL;
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = zol->curfreq;
 	return 0;
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index f33315f..4da0f15 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -426,6 +426,104 @@
 
 
 /**************************************************************************
+ * File Operations Interface
+ **************************************************************************/
+
+/*
+ * si470x_fops_read - read RDS data
+ */
+static ssize_t si470x_fops_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct si470x_device *radio = video_drvdata(file);
+	int retval = 0;
+	unsigned int block_count = 0;
+
+	/* switch on rds reception */
+	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+		si470x_rds_on(radio);
+
+	/* block if no new data available */
+	while (radio->wr_index == radio->rd_index) {
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EWOULDBLOCK;
+			goto done;
+		}
+		if (wait_event_interruptible(radio->read_queue,
+			radio->wr_index != radio->rd_index) < 0) {
+			retval = -EINTR;
+			goto done;
+		}
+	}
+
+	/* calculate block count from byte count */
+	count /= 3;
+
+	/* copy RDS block out of internal buffer and to user buffer */
+	mutex_lock(&radio->lock);
+	while (block_count < count) {
+		if (radio->rd_index == radio->wr_index)
+			break;
+
+		/* always transfer rds complete blocks */
+		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
+			/* retval = -EFAULT; */
+			break;
+
+		/* increment and wrap read pointer */
+		radio->rd_index += 3;
+		if (radio->rd_index >= radio->buf_size)
+			radio->rd_index = 0;
+
+		/* increment counters */
+		block_count++;
+		buf += 3;
+		retval += 3;
+	}
+	mutex_unlock(&radio->lock);
+
+done:
+	return retval;
+}
+
+
+/*
+ * si470x_fops_poll - poll RDS data
+ */
+static unsigned int si470x_fops_poll(struct file *file,
+		struct poll_table_struct *pts)
+{
+	struct si470x_device *radio = video_drvdata(file);
+	int retval = 0;
+
+	/* switch on rds reception */
+	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+		si470x_rds_on(radio);
+
+	poll_wait(file, &radio->read_queue, pts);
+
+	if (radio->rd_index != radio->wr_index)
+		retval = POLLIN | POLLRDNORM;
+
+	return retval;
+}
+
+
+/*
+ * si470x_fops - file operations interface
+ */
+static const struct v4l2_file_operations si470x_fops = {
+	.owner			= THIS_MODULE,
+	.read			= si470x_fops_read,
+	.poll			= si470x_fops_poll,
+	.ioctl			= video_ioctl2,
+	.open			= si470x_fops_open,
+	.release		= si470x_fops_release,
+};
+
+
+
+/**************************************************************************
  * Video4Linux Interface
  **************************************************************************/
 
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index 2d53b6a..5466015 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -22,22 +22,17 @@
  */
 
 
-/*
- * ToDo:
- * - RDS support
- */
-
-
 /* driver definitions */
 #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
-#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 0)
+#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 1)
 #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
 #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
-#define DRIVER_VERSION "1.0.0"
+#define DRIVER_VERSION "1.0.1"
 
 /* kernel includes */
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 
 #include "radio-si470x.h"
 
@@ -62,6 +57,20 @@
 module_param(radio_nr, int, 0444);
 MODULE_PARM_DESC(radio_nr, "Radio Nr");
 
+/* RDS buffer blocks */
+static unsigned int rds_buf = 100;
+module_param(rds_buf, uint, 0444);
+MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
+
+/* RDS maximum block errors */
+static unsigned short max_rds_errors = 1;
+/* 0 means   0  errors requiring correction */
+/* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) */
+/* 2 means 3-5  errors requiring correction */
+/* 3 means   6+ errors or errors in checkword, correction not possible */
+module_param(max_rds_errors, ushort, 0644);
+MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
+
 
 
 /**************************************************************************
@@ -173,7 +182,7 @@
 /*
  * si470x_fops_open - file open
  */
-static int si470x_fops_open(struct file *file)
+int si470x_fops_open(struct file *file)
 {
 	struct si470x_device *radio = video_drvdata(file);
 	int retval = 0;
@@ -181,12 +190,21 @@
 	mutex_lock(&radio->lock);
 	radio->users++;
 
-	if (radio->users == 1)
+	if (radio->users == 1) {
 		/* start radio */
 		retval = si470x_start(radio);
+		if (retval < 0)
+			goto done;
 
+		/* enable RDS interrupt */
+		radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
+		radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
+		radio->registers[SYSCONFIG1] |= 0x1 << 2;
+		retval = si470x_set_register(radio, SYSCONFIG1);
+	}
+
+done:
 	mutex_unlock(&radio->lock);
-
 	return retval;
 }
 
@@ -194,7 +212,7 @@
 /*
  * si470x_fops_release - file release
  */
-static int si470x_fops_release(struct file *file)
+int si470x_fops_release(struct file *file)
 {
 	struct si470x_device *radio = video_drvdata(file);
 	int retval = 0;
@@ -215,17 +233,6 @@
 }
 
 
-/*
- * si470x_fops - file operations interface
- */
-const struct v4l2_file_operations si470x_fops = {
-	.owner		= THIS_MODULE,
-	.ioctl		= video_ioctl2,
-	.open		= si470x_fops_open,
-	.release	= si470x_fops_release,
-};
-
-
 
 /**************************************************************************
  * Video4Linux Interface
@@ -253,6 +260,105 @@
  **************************************************************************/
 
 /*
+ * si470x_i2c_interrupt_work - rds processing function
+ */
+static void si470x_i2c_interrupt_work(struct work_struct *work)
+{
+	struct si470x_device *radio = container_of(work,
+			struct si470x_device, radio_work);
+	unsigned char regnr;
+	unsigned char blocknum;
+	unsigned short bler; /* rds block errors */
+	unsigned short rds;
+	unsigned char tmpbuf[3];
+	int retval = 0;
+
+	/* safety checks */
+	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
+		return;
+
+	/* Update RDS registers */
+	for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) {
+		retval = si470x_get_register(radio, STATUSRSSI + regnr);
+		if (retval < 0)
+			return;
+	}
+
+	/* get rds blocks */
+	if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0)
+		/* No RDS group ready, better luck next time */
+		return;
+
+	for (blocknum = 0; blocknum < 4; blocknum++) {
+		switch (blocknum) {
+		default:
+			bler = (radio->registers[STATUSRSSI] &
+					STATUSRSSI_BLERA) >> 9;
+			rds = radio->registers[RDSA];
+			break;
+		case 1:
+			bler = (radio->registers[READCHAN] &
+					READCHAN_BLERB) >> 14;
+			rds = radio->registers[RDSB];
+			break;
+		case 2:
+			bler = (radio->registers[READCHAN] &
+					READCHAN_BLERC) >> 12;
+			rds = radio->registers[RDSC];
+			break;
+		case 3:
+			bler = (radio->registers[READCHAN] &
+					READCHAN_BLERD) >> 10;
+			rds = radio->registers[RDSD];
+			break;
+		};
+
+		/* Fill the V4L2 RDS buffer */
+		put_unaligned_le16(rds, &tmpbuf);
+		tmpbuf[2] = blocknum;		/* offset name */
+		tmpbuf[2] |= blocknum << 3;	/* received offset */
+		if (bler > max_rds_errors)
+			tmpbuf[2] |= 0x80;	/* uncorrectable errors */
+		else if (bler > 0)
+			tmpbuf[2] |= 0x40;	/* corrected error(s) */
+
+		/* copy RDS block to internal buffer */
+		memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
+		radio->wr_index += 3;
+
+		/* wrap write pointer */
+		if (radio->wr_index >= radio->buf_size)
+			radio->wr_index = 0;
+
+		/* check for overflow */
+		if (radio->wr_index == radio->rd_index) {
+			/* increment and wrap read pointer */
+			radio->rd_index += 3;
+			if (radio->rd_index >= radio->buf_size)
+				radio->rd_index = 0;
+		}
+	}
+
+	if (radio->wr_index != radio->rd_index)
+		wake_up_interruptible(&radio->read_queue);
+}
+
+
+/*
+ * si470x_i2c_interrupt - interrupt handler
+ */
+static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id)
+{
+	struct si470x_device *radio = dev_id;
+
+	if (!work_pending(&radio->radio_work))
+		schedule_work(&radio->radio_work);
+
+	return IRQ_HANDLED;
+}
+
+
+/*
  * si470x_i2c_probe - probe for the device
  */
 static int __devinit si470x_i2c_probe(struct i2c_client *client,
@@ -268,6 +374,8 @@
 		retval = -ENOMEM;
 		goto err_initial;
 	}
+
+	INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work);
 	radio->users = 0;
 	radio->client = client;
 	mutex_init(&radio->lock);
@@ -319,6 +427,26 @@
 	/* set initial frequency */
 	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
 
+	/* rds buffer allocation */
+	radio->buf_size = rds_buf * 3;
+	radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
+	if (!radio->buffer) {
+		retval = -EIO;
+		goto err_video;
+	}
+
+	/* rds buffer configuration */
+	radio->wr_index = 0;
+	radio->rd_index = 0;
+	init_waitqueue_head(&radio->read_queue);
+
+	retval = request_irq(client->irq, si470x_i2c_interrupt,
+			IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
+	if (retval) {
+		dev_err(&client->dev, "Failed to register interrupt\n");
+		goto err_rds;
+	}
+
 	/* register video device */
 	retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
 			radio_nr);
@@ -330,6 +458,9 @@
 
 	return 0;
 err_all:
+	free_irq(client->irq, radio);
+err_rds:
+	kfree(radio->buffer);
 err_video:
 	video_device_release(radio->videodev);
 err_radio:
@@ -346,6 +477,8 @@
 {
 	struct si470x_device *radio = i2c_get_clientdata(client);
 
+	free_irq(client->irq, radio);
+	cancel_work_sync(&radio->radio_work);
 	video_unregister_device(radio->videodev);
 	kfree(radio);
 	i2c_set_clientdata(client, NULL);
@@ -354,6 +487,44 @@
 }
 
 
+#ifdef CONFIG_PM
+/*
+ * si470x_i2c_suspend - suspend the device
+ */
+static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct si470x_device *radio = i2c_get_clientdata(client);
+
+	/* power down */
+	radio->registers[POWERCFG] |= POWERCFG_DISABLE;
+	if (si470x_set_register(radio, POWERCFG) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+
+/*
+ * si470x_i2c_resume - resume the device
+ */
+static int si470x_i2c_resume(struct i2c_client *client)
+{
+	struct si470x_device *radio = i2c_get_clientdata(client);
+
+	/* power up : need 110ms */
+	radio->registers[POWERCFG] |= POWERCFG_ENABLE;
+	if (si470x_set_register(radio, POWERCFG) < 0)
+		return -EIO;
+	msleep(110);
+
+	return 0;
+}
+#else
+#define si470x_i2c_suspend	NULL
+#define si470x_i2c_resume	NULL
+#endif
+
+
 /*
  * si470x_i2c_driver - i2c driver interface
  */
@@ -364,6 +535,8 @@
 	},
 	.probe			= si470x_i2c_probe,
 	.remove			= __devexit_p(si470x_i2c_remove),
+	.suspend		= si470x_i2c_suspend,
+	.resume			= si470x_i2c_resume,
 	.id_table		= si470x_i2c_id,
 };
 
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index f2d0e1d..a96e1b9 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -509,89 +509,9 @@
  **************************************************************************/
 
 /*
- * si470x_fops_read - read RDS data
- */
-static ssize_t si470x_fops_read(struct file *file, char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	struct si470x_device *radio = video_drvdata(file);
-	int retval = 0;
-	unsigned int block_count = 0;
-
-	/* switch on rds reception */
-	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
-		si470x_rds_on(radio);
-
-	/* block if no new data available */
-	while (radio->wr_index == radio->rd_index) {
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EWOULDBLOCK;
-			goto done;
-		}
-		if (wait_event_interruptible(radio->read_queue,
-			radio->wr_index != radio->rd_index) < 0) {
-			retval = -EINTR;
-			goto done;
-		}
-	}
-
-	/* calculate block count from byte count */
-	count /= 3;
-
-	/* copy RDS block out of internal buffer and to user buffer */
-	mutex_lock(&radio->lock);
-	while (block_count < count) {
-		if (radio->rd_index == radio->wr_index)
-			break;
-
-		/* always transfer rds complete blocks */
-		if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
-			/* retval = -EFAULT; */
-			break;
-
-		/* increment and wrap read pointer */
-		radio->rd_index += 3;
-		if (radio->rd_index >= radio->buf_size)
-			radio->rd_index = 0;
-
-		/* increment counters */
-		block_count++;
-		buf += 3;
-		retval += 3;
-	}
-	mutex_unlock(&radio->lock);
-
-done:
-	return retval;
-}
-
-
-/*
- * si470x_fops_poll - poll RDS data
- */
-static unsigned int si470x_fops_poll(struct file *file,
-		struct poll_table_struct *pts)
-{
-	struct si470x_device *radio = video_drvdata(file);
-	int retval = 0;
-
-	/* switch on rds reception */
-	if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
-		si470x_rds_on(radio);
-
-	poll_wait(file, &radio->read_queue, pts);
-
-	if (radio->rd_index != radio->wr_index)
-		retval = POLLIN | POLLRDNORM;
-
-	return retval;
-}
-
-
-/*
  * si470x_fops_open - file open
  */
-static int si470x_fops_open(struct file *file)
+int si470x_fops_open(struct file *file)
 {
 	struct si470x_device *radio = video_drvdata(file);
 	int retval;
@@ -645,7 +565,7 @@
 /*
  * si470x_fops_release - file release
  */
-static int si470x_fops_release(struct file *file)
+int si470x_fops_release(struct file *file)
 {
 	struct si470x_device *radio = video_drvdata(file);
 	int retval = 0;
@@ -688,19 +608,6 @@
 }
 
 
-/*
- * si470x_fops - file operations interface
- */
-const struct v4l2_file_operations si470x_fops = {
-	.owner		= THIS_MODULE,
-	.read		= si470x_fops_read,
-	.poll		= si470x_fops_poll,
-	.ioctl		= video_ioctl2,
-	.open		= si470x_fops_open,
-	.release	= si470x_fops_release,
-};
-
-
 
 /**************************************************************************
  * Video4Linux Interface
diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h
index d0af194..3cd0a29 100644
--- a/drivers/media/radio/si470x/radio-si470x.h
+++ b/drivers/media/radio/si470x/radio-si470x.h
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/input.h>
@@ -181,6 +182,7 @@
 
 #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
 	struct i2c_client *client;
+	struct work_struct radio_work;
 #endif
 };
 
@@ -212,7 +214,6 @@
 /**************************************************************************
  * Common Functions
  **************************************************************************/
-extern const struct v4l2_file_operations si470x_fops;
 extern struct video_device si470x_viddev_template;
 int si470x_get_register(struct si470x_device *radio, int regnr);
 int si470x_set_register(struct si470x_device *radio, int regnr);
@@ -221,5 +222,7 @@
 int si470x_start(struct si470x_device *radio);
 int si470x_stop(struct si470x_device *radio);
 int si470x_rds_on(struct si470x_device *radio);
+int si470x_fops_open(struct file *file);
+int si470x_fops_release(struct file *file);
 int si470x_vidioc_querycap(struct file *file, void *priv,
 		struct v4l2_capability *capability);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 9dc74c9..2f83be7 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -37,10 +37,6 @@
 	depends on PCI
 	tristate
 
-config VIDEO_IR
-	tristate
-	depends on INPUT
-
 config VIDEO_TVEEPROM
 	tristate
 	depends on I2C
@@ -840,6 +836,12 @@
 	help
 	  This driver supports MT9T031 cameras from Micron.
 
+config SOC_CAMERA_MT9T112
+	tristate "mt9t112 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports MT9T112 cameras from Aptina.
+
 config SOC_CAMERA_MT9V022
 	tristate "mt9v022 support"
 	depends on SOC_CAMERA && I2C
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 7a2dcc3..2af68ee 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -75,6 +75,7 @@
 obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
 obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9T112)	+= mt9t112.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
 obj-$(CONFIG_SOC_CAMERA_OV9640)		+= ov9640.o
@@ -149,7 +150,7 @@
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
 obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
-obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o
+obj-$(CONFIG_SOC_CAMERA)		+= soc_camera.o soc_mediabus.o
 obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o
 # soc-camera host drivers have to be linked after camera drivers
 obj-$(CONFIG_VIDEO_MX1)			+= mx1_camera.o
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index d137bac..a356d6b 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -767,7 +767,6 @@
 	.name		= "Colour AR VGA",
 	.fops		= &ar_fops,
 	.release	= ar_release,
-	.minor		= -1,
 };
 
 #define ALIGN4(x)	((((int)(x)) & 0x3) == 0)
@@ -860,8 +859,8 @@
 		goto out_dev;
 	}
 
-	printk("video%d: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
-		ar->vdev->num, M32R_IRQ_INT3, freq);
+	printk("%s: Found M64278 VGA (IRQ %d, Freq %dMHz).\n",
+		video_device_node_name(ar->vdev), M32R_IRQ_INT3, freq);
 
 	return 0;
 
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
index 1485aee..dc67bc4 100644
--- a/drivers/media/video/au0828/au0828-video.c
+++ b/drivers/media/video/au0828/au0828-video.c
@@ -40,7 +40,6 @@
 #include "au0828.h"
 #include "au0828-reg.h"
 
-static LIST_HEAD(au0828_devlist);
 static DEFINE_MUTEX(au0828_sysfs_lock);
 
 #define AU0828_VERSION_CODE KERNEL_VERSION(0, 0, 1)
@@ -693,10 +692,8 @@
 	dprintk(1, "au0828_release_resources called\n");
 	mutex_lock(&au0828_sysfs_lock);
 
-	if (dev->vdev) {
-		list_del(&dev->au0828list);
+	if (dev->vdev)
 		video_unregister_device(dev->vdev);
-	}
 	if (dev->vbi_dev)
 		video_unregister_device(dev->vbi_dev);
 
@@ -737,29 +734,15 @@
 
 static int au0828_v4l2_open(struct file *filp)
 {
-	int minor = video_devdata(filp)->minor;
 	int ret = 0;
-	struct au0828_dev *h, *dev = NULL;
+	struct au0828_dev *dev = video_drvdata(filp);
 	struct au0828_fh *fh;
-	int type = 0;
-	struct list_head *list;
+	int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	list_for_each(list, &au0828_devlist) {
-		h = list_entry(list, struct au0828_dev, au0828list);
-		if (h->vdev->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
 #ifdef VBI_IS_WORKING
-		if (h->vbi_dev->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		}
+	if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER)
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
 #endif
-	}
-
-	if (NULL == dev)
-		return -ENODEV;
 
 	fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
 	if (NULL == fh) {
@@ -1587,7 +1570,6 @@
 	.fops                       = &au0828_v4l_fops,
 	.release                    = video_device_release,
 	.ioctl_ops 		    = &video_ioctl_ops,
-	.minor                      = -1,
 	.tvnorms                    = V4L2_STD_NTSC_M,
 	.current_norm               = V4L2_STD_NTSC_M,
 };
@@ -1676,25 +1658,23 @@
 	strcpy(dev->vbi_dev->name, "au0828a vbi");
 #endif
 
-	list_add_tail(&dev->au0828list, &au0828_devlist);
-
 	/* Register the v4l2 device */
+	video_set_drvdata(dev->vdev, dev);
 	retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
 	if (retval != 0) {
 		dprintk(1, "unable to register video device (error = %d).\n",
 			retval);
-		list_del(&dev->au0828list);
 		video_device_release(dev->vdev);
 		return -ENODEV;
 	}
 
 #ifdef VBI_IS_WORKING
 	/* Register the vbi device */
+	video_set_drvdata(dev->vbi_dev, dev);
 	retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
 	if (retval != 0) {
 		dprintk(1, "unable to register vbi device (error = %d).\n",
 			retval);
-		list_del(&dev->au0828list);
 		video_device_release(dev->vbi_dev);
 		video_device_release(dev->vdev);
 		return -ENODEV;
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
index b977915..207f32d 100644
--- a/drivers/media/video/au0828/au0828.h
+++ b/drivers/media/video/au0828/au0828.h
@@ -192,7 +192,6 @@
 	struct au0828_dvb		dvb;
 
 	/* Analog */
-	struct list_head au0828list;
 	struct v4l2_device v4l2_dev;
 	int users;
 	unsigned int stream_on:1;	/* Locks streams */
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index a6724019..3182a40 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3206,24 +3206,24 @@
 
 static int bttv_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
+	struct video_device *vdev = video_devdata(file);
 	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
 	enum v4l2_buf_type type = 0;
 
-	dprintk(KERN_DEBUG "bttv: open minor=%d\n",minor);
+	dprintk(KERN_DEBUG "bttv: open dev=%s\n", video_device_node_name(vdev));
 
-	lock_kernel();
-	if (btv->video_dev->minor == minor) {
+	if (vdev->vfl_type == VFL_TYPE_GRABBER) {
 		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	} else if (btv->vbi_dev->minor == minor) {
+	} else if (vdev->vfl_type == VFL_TYPE_VBI) {
 		type = V4L2_BUF_TYPE_VBI_CAPTURE;
 	} else {
 		WARN_ON(1);
-		unlock_kernel();
 		return -ENODEV;
 	}
 
+	lock_kernel();
+
 	dprintk(KERN_DEBUG "bttv%d: open called (type=%s)\n",
 		btv->c.nr,v4l2_type_names[type]);
 
@@ -3397,7 +3397,6 @@
 
 static struct video_device bttv_video_template = {
 	.fops         = &bttv_fops,
-	.minor        = -1,
 	.ioctl_ops    = &bttv_ioctl_ops,
 	.tvnorms      = BTTV_NORMS,
 	.current_norm = V4L2_STD_PAL,
@@ -3408,18 +3407,13 @@
 
 static int radio_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
+	struct video_device *vdev = video_devdata(file);
 	struct bttv *btv = video_drvdata(file);
 	struct bttv_fh *fh;
 
-	dprintk("bttv: open minor=%d\n",minor);
+	dprintk("bttv: open dev=%s\n", video_device_node_name(vdev));
 
 	lock_kernel();
-	WARN_ON(btv->radio_dev && btv->radio_dev->minor != minor);
-	if (!btv->radio_dev || btv->radio_dev->minor != minor) {
-		unlock_kernel();
-		return -ENODEV;
-	}
 
 	dprintk("bttv%d: open called (radio)\n",btv->c.nr);
 
@@ -3640,7 +3634,6 @@
 
 static struct video_device radio_template = {
 	.fops      = &radio_fops,
-	.minor     = -1,
 	.ioctl_ops = &radio_ioctl_ops,
 };
 
@@ -4208,21 +4201,21 @@
 static void bttv_unregister_video(struct bttv *btv)
 {
 	if (btv->video_dev) {
-		if (-1 != btv->video_dev->minor)
+		if (video_is_registered(btv->video_dev))
 			video_unregister_device(btv->video_dev);
 		else
 			video_device_release(btv->video_dev);
 		btv->video_dev = NULL;
 	}
 	if (btv->vbi_dev) {
-		if (-1 != btv->vbi_dev->minor)
+		if (video_is_registered(btv->vbi_dev))
 			video_unregister_device(btv->vbi_dev);
 		else
 			video_device_release(btv->vbi_dev);
 		btv->vbi_dev = NULL;
 	}
 	if (btv->radio_dev) {
-		if (-1 != btv->radio_dev->minor)
+		if (video_is_registered(btv->radio_dev))
 			video_unregister_device(btv->radio_dev);
 		else
 			video_device_release(btv->radio_dev);
@@ -4244,8 +4237,8 @@
 	if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
 				  video_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device video%d\n",
-	       btv->c.nr, btv->video_dev->num);
+	printk(KERN_INFO "bttv%d: registered device %s\n",
+	       btv->c.nr, video_device_node_name(btv->video_dev));
 	if (device_create_file(&btv->video_dev->dev,
 				     &dev_attr_card)<0) {
 		printk(KERN_ERR "bttv%d: device_create_file 'card' "
@@ -4261,8 +4254,8 @@
 	if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
 				  vbi_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device vbi%d\n",
-	       btv->c.nr, btv->vbi_dev->num);
+	printk(KERN_INFO "bttv%d: registered device %s\n",
+	       btv->c.nr, video_device_node_name(btv->vbi_dev));
 
 	if (!btv->has_radio)
 		return 0;
@@ -4273,8 +4266,8 @@
 	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
 				  radio_nr[btv->c.nr]) < 0)
 		goto err;
-	printk(KERN_INFO "bttv%d: registered device radio%d\n",
-	       btv->c.nr, btv->radio_dev->num);
+	printk(KERN_INFO "bttv%d: registered device %s\n",
+	       btv->c.nr, video_device_node_name(btv->radio_dev));
 
 	/* all done */
 	return 0;
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index beda363..63aa31a 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -40,7 +40,7 @@
 static int i2c_hw;
 static int i2c_scan;
 module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_hw,"configure i2c debug level");
+MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
 module_param(i2c_hw,    int, 0444);
 MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
 			"instead of software bitbang");
@@ -400,7 +400,7 @@
 		   That's why we probe 0x1a (~0x34) first. CB
 		*/
 		const unsigned short addr_list[] = {
-			0x1a, 0x18, 0x4b, 0x64, 0x30,
+			0x1a, 0x18, 0x4b, 0x64, 0x30, 0x71,
 			I2C_CLIENT_END
 		};
 
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 84a957e..277a092 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -368,7 +368,7 @@
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(btv->c.pci));
 
-	err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, ir_type);
 	if (err < 0)
 		goto err_out_free;
 
@@ -389,7 +389,7 @@
 	bttv_ir_start(btv, ir);
 
 	/* all done */
-	err = input_register_device(btv->remote->dev);
+	err = ir_input_register(btv->remote->dev, ir_codes);
 	if (err)
 		goto err_out_stop;
 
@@ -403,8 +403,6 @@
 	bttv_ir_stop(btv);
 	btv->remote = NULL;
  err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -415,8 +413,7 @@
 		return;
 
 	bttv_ir_stop(btv);
-	ir_input_free(btv->remote->dev);
-	input_unregister_device(btv->remote->dev);
+	ir_input_unregister(btv->remote->dev);
 	kfree(btv->remote);
 	btv->remote = NULL;
 }
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 85cf177..e2cbeba 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -809,8 +809,8 @@
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO "video%d: Colour QuickCam found on %s\n",
-	       qcam->vdev.num, qcam->pport->name);
+	printk(KERN_INFO "%s: Colour QuickCam found on %s\n",
+	       video_device_node_name(&qcam->vdev), qcam->pport->name);
 
 	qcams[num_cams++] = qcam;
 
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 10230cb..7bb9c1e 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -1723,7 +1723,6 @@
 
 static struct video_device cafe_v4l_template = {
 	.name = "cafe",
-	.minor = -1, /* Get one dynamically */
 	.tvnorms = V4L2_STD_NTSC_M,
 	.current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
 
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 2377313..551ddf2 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -32,6 +32,7 @@
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
@@ -244,72 +245,67 @@
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *cpia_proc_root=NULL;
 
-static int cpia_read_proc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data)
+static int cpia_proc_show(struct seq_file *m, void *v)
 {
-	char *out = page;
-	int len, tmp;
-	struct cam_data *cam = data;
+	struct cam_data *cam = m->private;
+	int tmp;
 	char tmpstr[29];
 
-	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
-	 *            or we need to get more sophisticated. */
-
-	out += sprintf(out, "read-only\n-----------------------\n");
-	out += sprintf(out, "V4L Driver version:       %d.%d.%d\n",
+	seq_printf(m, "read-only\n-----------------------\n");
+	seq_printf(m, "V4L Driver version:       %d.%d.%d\n",
 		       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
-	out += sprintf(out, "CPIA Version:             %d.%02d (%d.%d)\n",
+	seq_printf(m, "CPIA Version:             %d.%02d (%d.%d)\n",
 		       cam->params.version.firmwareVersion,
 		       cam->params.version.firmwareRevision,
 		       cam->params.version.vcVersion,
 		       cam->params.version.vcRevision);
-	out += sprintf(out, "CPIA PnP-ID:              %04x:%04x:%04x\n",
+	seq_printf(m, "CPIA PnP-ID:              %04x:%04x:%04x\n",
 		       cam->params.pnpID.vendor, cam->params.pnpID.product,
 		       cam->params.pnpID.deviceRevision);
-	out += sprintf(out, "VP-Version:               %d.%d %04x\n",
+	seq_printf(m, "VP-Version:               %d.%d %04x\n",
 		       cam->params.vpVersion.vpVersion,
 		       cam->params.vpVersion.vpRevision,
 		       cam->params.vpVersion.cameraHeadID);
 
-	out += sprintf(out, "system_state:             %#04x\n",
+	seq_printf(m, "system_state:             %#04x\n",
 		       cam->params.status.systemState);
-	out += sprintf(out, "grab_state:               %#04x\n",
+	seq_printf(m, "grab_state:               %#04x\n",
 		       cam->params.status.grabState);
-	out += sprintf(out, "stream_state:             %#04x\n",
+	seq_printf(m, "stream_state:             %#04x\n",
 		       cam->params.status.streamState);
-	out += sprintf(out, "fatal_error:              %#04x\n",
+	seq_printf(m, "fatal_error:              %#04x\n",
 		       cam->params.status.fatalError);
-	out += sprintf(out, "cmd_error:                %#04x\n",
+	seq_printf(m, "cmd_error:                %#04x\n",
 		       cam->params.status.cmdError);
-	out += sprintf(out, "debug_flags:              %#04x\n",
+	seq_printf(m, "debug_flags:              %#04x\n",
 		       cam->params.status.debugFlags);
-	out += sprintf(out, "vp_status:                %#04x\n",
+	seq_printf(m, "vp_status:                %#04x\n",
 		       cam->params.status.vpStatus);
-	out += sprintf(out, "error_code:               %#04x\n",
+	seq_printf(m, "error_code:               %#04x\n",
 		       cam->params.status.errorCode);
 	/* QX3 specific entries */
 	if (cam->params.qx3.qx3_detected) {
-		out += sprintf(out, "button:                   %4d\n",
+		seq_printf(m, "button:                   %4d\n",
 			       cam->params.qx3.button);
-		out += sprintf(out, "cradled:                  %4d\n",
+		seq_printf(m, "cradled:                  %4d\n",
 			       cam->params.qx3.cradled);
 	}
-	out += sprintf(out, "video_size:               %s\n",
+	seq_printf(m, "video_size:               %s\n",
 		       cam->params.format.videoSize == VIDEOSIZE_CIF ?
 		       "CIF " : "QCIF");
-	out += sprintf(out, "roi:                      (%3d, %3d) to (%3d, %3d)\n",
+	seq_printf(m, "roi:                      (%3d, %3d) to (%3d, %3d)\n",
 		       cam->params.roi.colStart*8,
 		       cam->params.roi.rowStart*4,
 		       cam->params.roi.colEnd*8,
 		       cam->params.roi.rowEnd*4);
-	out += sprintf(out, "actual_fps:               %3d\n", cam->fps);
-	out += sprintf(out, "transfer_rate:            %4dkB/s\n",
+	seq_printf(m, "actual_fps:               %3d\n", cam->fps);
+	seq_printf(m, "transfer_rate:            %4dkB/s\n",
 		       cam->transfer_rate);
 
-	out += sprintf(out, "\nread-write\n");
-	out += sprintf(out, "-----------------------  current       min"
+	seq_printf(m, "\nread-write\n");
+	seq_printf(m, "-----------------------  current       min"
 		       "       max   default  comment\n");
-	out += sprintf(out, "brightness:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "brightness:             %8d  %8d  %8d  %8d\n",
 		       cam->params.colourParams.brightness, 0, 100, 50);
 	if (cam->params.version.firmwareVersion == 1 &&
 	   cam->params.version.firmwareRevision == 2)
@@ -318,26 +314,26 @@
 	else
 		tmp = 96;
 
-	out += sprintf(out, "contrast:               %8d  %8d  %8d  %8d"
+	seq_printf(m, "contrast:               %8d  %8d  %8d  %8d"
 		       "  steps of 8\n",
 		       cam->params.colourParams.contrast, 0, tmp, 48);
-	out += sprintf(out, "saturation:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "saturation:             %8d  %8d  %8d  %8d\n",
 		       cam->params.colourParams.saturation, 0, 100, 50);
 	tmp = (25000+5000*cam->params.sensorFps.baserate)/
 	      (1<<cam->params.sensorFps.divisor);
-	out += sprintf(out, "sensor_fps:             %4d.%03d  %8d  %8d  %8d\n",
+	seq_printf(m, "sensor_fps:             %4d.%03d  %8d  %8d  %8d\n",
 		       tmp/1000, tmp%1000, 3, 30, 15);
-	out += sprintf(out, "stream_start_line:      %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "stream_start_line:      %8d  %8d  %8d  %8d\n",
 		       2*cam->params.streamStartLine, 0,
 		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 288:144,
 		       cam->params.format.videoSize == VIDEOSIZE_CIF ? 240:120);
-	out += sprintf(out, "sub_sample:             %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "sub_sample:             %8s  %8s  %8s  %8s\n",
 		       cam->params.format.subSample == SUBSAMPLE_420 ?
 		       "420" : "422", "420", "422", "422");
-	out += sprintf(out, "yuv_order:              %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "yuv_order:              %8s  %8s  %8s  %8s\n",
 		       cam->params.format.yuvOrder == YUVORDER_YUYV ?
 		       "YUYV" : "UYVY", "YUYV" , "UYVY", "YUYV");
-	out += sprintf(out, "ecp_timing:             %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "ecp_timing:             %8s  %8s  %8s  %8s\n",
 		       cam->params.ecpTiming ? "slow" : "normal", "slow",
 		       "normal", "normal");
 
@@ -346,13 +342,13 @@
 	} else {
 		sprintf(tmpstr, "manual");
 	}
-	out += sprintf(out, "color_balance_mode:     %8s  %8s  %8s"
+	seq_printf(m, "color_balance_mode:     %8s  %8s  %8s"
 		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
-	out += sprintf(out, "red_gain:               %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "red_gain:               %8d  %8d  %8d  %8d\n",
 		       cam->params.colourBalance.redGain, 0, 212, 32);
-	out += sprintf(out, "green_gain:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "green_gain:             %8d  %8d  %8d  %8d\n",
 		       cam->params.colourBalance.greenGain, 0, 212, 6);
-	out += sprintf(out, "blue_gain:              %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "blue_gain:              %8d  %8d  %8d  %8d\n",
 		       cam->params.colourBalance.blueGain, 0, 212, 92);
 
 	if (cam->params.version.firmwareVersion == 1 &&
@@ -363,10 +359,10 @@
 		sprintf(tmpstr, "%8d  %8d  %8d", 1, 8, 2);
 
 	if (cam->params.exposure.gainMode == 0)
-		out += sprintf(out, "max_gain:                unknown  %28s"
+		seq_printf(m, "max_gain:                unknown  %28s"
 			       "  powers of 2\n", tmpstr);
 	else
-		out += sprintf(out, "max_gain:               %8d  %28s"
+		seq_printf(m, "max_gain:               %8d  %28s"
 			       "  1,2,4 or 8 \n",
 			       1<<(cam->params.exposure.gainMode-1), tmpstr);
 
@@ -382,12 +378,12 @@
 		sprintf(tmpstr, "unknown");
 		break;
 	}
-	out += sprintf(out, "exposure_mode:          %8s  %8s  %8s"
+	seq_printf(m, "exposure_mode:          %8s  %8s  %8s"
 		       "  %8s\n",  tmpstr, "manual", "auto", "auto");
-	out += sprintf(out, "centre_weight:          %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "centre_weight:          %8s  %8s  %8s  %8s\n",
 		       (2-cam->params.exposure.centreWeight) ? "on" : "off",
 		       "off", "on", "on");
-	out += sprintf(out, "gain:                   %8d  %8d  max_gain  %8d  1,2,4,8 possible\n",
+	seq_printf(m, "gain:                   %8d  %8d  max_gain  %8d  1,2,4,8 possible\n",
 		       1<<cam->params.exposure.gain, 1, 1);
 	if (cam->params.version.firmwareVersion == 1 &&
 	   cam->params.version.firmwareRevision == 2)
@@ -396,7 +392,7 @@
 	else
 		tmp = 510;
 
-	out += sprintf(out, "fine_exp:               %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "fine_exp:               %8d  %8d  %8d  %8d\n",
 		       cam->params.exposure.fineExp*2, 0, tmp, 0);
 	if (cam->params.version.firmwareVersion == 1 &&
 	   cam->params.version.firmwareRevision == 2)
@@ -405,127 +401,122 @@
 	else
 		tmp = MAX_EXP;
 
-	out += sprintf(out, "coarse_exp:             %8d  %8d  %8d"
+	seq_printf(m, "coarse_exp:             %8d  %8d  %8d"
 		       "  %8d\n", cam->params.exposure.coarseExpLo+
 		       256*cam->params.exposure.coarseExpHi, 0, tmp, 185);
-	out += sprintf(out, "red_comp:               %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "red_comp:               %8d  %8d  %8d  %8d\n",
 		       cam->params.exposure.redComp, COMP_RED, 255, COMP_RED);
-	out += sprintf(out, "green1_comp:            %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "green1_comp:            %8d  %8d  %8d  %8d\n",
 		       cam->params.exposure.green1Comp, COMP_GREEN1, 255,
 		       COMP_GREEN1);
-	out += sprintf(out, "green2_comp:            %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "green2_comp:            %8d  %8d  %8d  %8d\n",
 		       cam->params.exposure.green2Comp, COMP_GREEN2, 255,
 		       COMP_GREEN2);
-	out += sprintf(out, "blue_comp:              %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "blue_comp:              %8d  %8d  %8d  %8d\n",
 		       cam->params.exposure.blueComp, COMP_BLUE, 255, COMP_BLUE);
 
-	out += sprintf(out, "apcor_gain1:            %#8x  %#8x  %#8x  %#8x\n",
+	seq_printf(m, "apcor_gain1:            %#8x  %#8x  %#8x  %#8x\n",
 		       cam->params.apcor.gain1, 0, 0xff, 0x1c);
-	out += sprintf(out, "apcor_gain2:            %#8x  %#8x  %#8x  %#8x\n",
+	seq_printf(m, "apcor_gain2:            %#8x  %#8x  %#8x  %#8x\n",
 		       cam->params.apcor.gain2, 0, 0xff, 0x1a);
-	out += sprintf(out, "apcor_gain4:            %#8x  %#8x  %#8x  %#8x\n",
+	seq_printf(m, "apcor_gain4:            %#8x  %#8x  %#8x  %#8x\n",
 		       cam->params.apcor.gain4, 0, 0xff, 0x2d);
-	out += sprintf(out, "apcor_gain8:            %#8x  %#8x  %#8x  %#8x\n",
+	seq_printf(m, "apcor_gain8:            %#8x  %#8x  %#8x  %#8x\n",
 		       cam->params.apcor.gain8, 0, 0xff, 0x2a);
-	out += sprintf(out, "vl_offset_gain1:        %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "vl_offset_gain1:        %8d  %8d  %8d  %8d\n",
 		       cam->params.vlOffset.gain1, 0, 255, 24);
-	out += sprintf(out, "vl_offset_gain2:        %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "vl_offset_gain2:        %8d  %8d  %8d  %8d\n",
 		       cam->params.vlOffset.gain2, 0, 255, 28);
-	out += sprintf(out, "vl_offset_gain4:        %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "vl_offset_gain4:        %8d  %8d  %8d  %8d\n",
 		       cam->params.vlOffset.gain4, 0, 255, 30);
-	out += sprintf(out, "vl_offset_gain8:        %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "vl_offset_gain8:        %8d  %8d  %8d  %8d\n",
 		       cam->params.vlOffset.gain8, 0, 255, 30);
-	out += sprintf(out, "flicker_control:        %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "flicker_control:        %8s  %8s  %8s  %8s\n",
 		       cam->params.flickerControl.flickerMode ? "on" : "off",
 		       "off", "on", "off");
-	out += sprintf(out, "mains_frequency:        %8d  %8d  %8d  %8d"
+	seq_printf(m, "mains_frequency:        %8d  %8d  %8d  %8d"
 		       " only 50/60\n",
 		       cam->mainsFreq ? 60 : 50, 50, 60, 50);
 	if(cam->params.flickerControl.allowableOverExposure < 0)
-		out += sprintf(out, "allowable_overexposure: %4dauto      auto  %8d      auto\n",
+		seq_printf(m, "allowable_overexposure: %4dauto      auto  %8d      auto\n",
 			       -cam->params.flickerControl.allowableOverExposure,
 			       255);
 	else
-		out += sprintf(out, "allowable_overexposure: %8d      auto  %8d      auto\n",
+		seq_printf(m, "allowable_overexposure: %8d      auto  %8d      auto\n",
 			       cam->params.flickerControl.allowableOverExposure,
 			       255);
-	out += sprintf(out, "compression_mode:       ");
+	seq_printf(m, "compression_mode:       ");
 	switch(cam->params.compression.mode) {
 	case CPIA_COMPRESSION_NONE:
-		out += sprintf(out, "%8s", "none");
+		seq_printf(m, "%8s", "none");
 		break;
 	case CPIA_COMPRESSION_AUTO:
-		out += sprintf(out, "%8s", "auto");
+		seq_printf(m, "%8s", "auto");
 		break;
 	case CPIA_COMPRESSION_MANUAL:
-		out += sprintf(out, "%8s", "manual");
+		seq_printf(m, "%8s", "manual");
 		break;
 	default:
-		out += sprintf(out, "%8s", "unknown");
+		seq_printf(m, "%8s", "unknown");
 		break;
 	}
-	out += sprintf(out, "    none,auto,manual      auto\n");
-	out += sprintf(out, "decimation_enable:      %8s  %8s  %8s  %8s\n",
+	seq_printf(m, "    none,auto,manual      auto\n");
+	seq_printf(m, "decimation_enable:      %8s  %8s  %8s  %8s\n",
 		       cam->params.compression.decimation ==
 		       DECIMATION_ENAB ? "on":"off", "off", "on",
 		       "off");
-	out += sprintf(out, "compression_target:    %9s %9s %9s %9s\n",
+	seq_printf(m, "compression_target:    %9s %9s %9s %9s\n",
 		       cam->params.compressionTarget.frTargeting  ==
 		       CPIA_COMPRESSION_TARGET_FRAMERATE ?
 		       "framerate":"quality",
 		       "framerate", "quality", "quality");
-	out += sprintf(out, "target_framerate:       %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "target_framerate:       %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionTarget.targetFR, 1, 30, 15);
-	out += sprintf(out, "target_quality:         %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "target_quality:         %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionTarget.targetQ, 1, 64, 5);
-	out += sprintf(out, "y_threshold:            %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "y_threshold:            %8d  %8d  %8d  %8d\n",
 		       cam->params.yuvThreshold.yThreshold, 0, 31, 6);
-	out += sprintf(out, "uv_threshold:           %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "uv_threshold:           %8d  %8d  %8d  %8d\n",
 		       cam->params.yuvThreshold.uvThreshold, 0, 31, 6);
-	out += sprintf(out, "hysteresis:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "hysteresis:             %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.hysteresis, 0, 255, 3);
-	out += sprintf(out, "threshold_max:          %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "threshold_max:          %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.threshMax, 0, 255, 11);
-	out += sprintf(out, "small_step:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "small_step:             %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.smallStep, 0, 255, 1);
-	out += sprintf(out, "large_step:             %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "large_step:             %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.largeStep, 0, 255, 3);
-	out += sprintf(out, "decimation_hysteresis:  %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "decimation_hysteresis:  %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.decimationHysteresis,
 		       0, 255, 2);
-	out += sprintf(out, "fr_diff_step_thresh:    %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "fr_diff_step_thresh:    %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.frDiffStepThresh,
 		       0, 255, 5);
-	out += sprintf(out, "q_diff_step_thresh:     %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "q_diff_step_thresh:     %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.qDiffStepThresh,
 		       0, 255, 3);
-	out += sprintf(out, "decimation_thresh_mod:  %8d  %8d  %8d  %8d\n",
+	seq_printf(m, "decimation_thresh_mod:  %8d  %8d  %8d  %8d\n",
 		       cam->params.compressionParams.decimationThreshMod,
 		       0, 255, 2);
 	/* QX3 specific entries */
 	if (cam->params.qx3.qx3_detected) {
-		out += sprintf(out, "toplight:               %8s  %8s  %8s  %8s\n",
+		seq_printf(m, "toplight:               %8s  %8s  %8s  %8s\n",
 			       cam->params.qx3.toplight ? "on" : "off",
 			       "off", "on", "off");
-		out += sprintf(out, "bottomlight:            %8s  %8s  %8s  %8s\n",
+		seq_printf(m, "bottomlight:            %8s  %8s  %8s  %8s\n",
 			       cam->params.qx3.bottomlight ? "on" : "off",
 			       "off", "on", "off");
 	}
 
-	len = out - page;
-	len -= off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0) return 0;
-	} else
-		len = count;
-
-	*start = page + off;
-	return len;
+	return 0;
 }
 
+static int cpia_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, cpia_proc_show, PDE(inode)->data);
+}
 
-static int match(char *checkstr, char **buffer, unsigned long *count,
+static int match(char *checkstr, char **buffer, size_t *count,
 		 int *find_colon, int *err)
 {
 	int ret, colon_found = 1;
@@ -551,7 +542,7 @@
 	return ret;
 }
 
-static unsigned long int value(char **buffer, unsigned long *count, int *err)
+static unsigned long int value(char **buffer, size_t *count, int *err)
 {
 	char *p;
 	unsigned long int ret;
@@ -565,10 +556,10 @@
 	return ret;
 }
 
-static int cpia_write_proc(struct file *file, const char __user *buf,
-			   unsigned long count, void *data)
+static ssize_t cpia_proc_write(struct file *file, const char __user *buf,
+			       size_t count, loff_t *pos)
 {
-	struct cam_data *cam = data;
+	struct cam_data *cam = PDE(file->f_path.dentry->d_inode)->data;
 	struct cam_params new_params;
 	char *page, *buffer;
 	int retval, find_colon;
@@ -582,7 +573,7 @@
 	 * from the comx driver
 	 */
 	if (count > PAGE_SIZE) {
-		printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);
+		printk(KERN_ERR "count is %zu > %d!!!\n", count, (int)PAGE_SIZE);
 		return -ENOSPC;
 	}
 
@@ -1340,23 +1331,28 @@
 	return retval;
 }
 
+static const struct file_operations cpia_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cpia_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= cpia_proc_write,
+};
+
 static void create_proc_cpia_cam(struct cam_data *cam)
 {
-	char name[5 + 1 + 10 + 1];
 	struct proc_dir_entry *ent;
 
 	if (!cpia_proc_root || !cam)
 		return;
 
-	snprintf(name, sizeof(name), "video%d", cam->vdev.num);
-
-	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, cpia_proc_root);
+	ent = proc_create_data(video_device_node_name(&cam->vdev),
+			       S_IRUGO|S_IWUSR, cpia_proc_root,
+			       &cpia_proc_fops, cam);
 	if (!ent)
 		return;
 
-	ent->data = cam;
-	ent->read_proc = cpia_read_proc;
-	ent->write_proc = cpia_write_proc;
 	/*
 	   size of the proc entry is 3736 bytes for the standard webcam;
 	   the extra features of the QX3 microscope add 189 bytes.
@@ -1368,13 +1364,10 @@
 
 static void destroy_proc_cpia_cam(struct cam_data *cam)
 {
-	char name[5 + 1 + 10 + 1];
-
 	if (!cam || !cam->proc_entry)
 		return;
 
-	snprintf(name, sizeof(name), "video%d", cam->vdev.num);
-	remove_proc_entry(name, cpia_proc_root);
+	remove_proc_entry(video_device_node_name(&cam->vdev), cpia_proc_root);
 	cam->proc_entry = NULL;
 }
 
@@ -3999,7 +3992,7 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-	DBG("destroying /proc/cpia/video%d\n", cam->vdev.num);
+	DBG("destroying /proc/cpia/%s\n", video_device_node_name(&cam->vdev));
 	destroy_proc_cpia_cam(cam);
 #endif
 	if (!cam->open_count) {
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 0b4a8f3..6f91415 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -38,17 +38,12 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
+#include <linux/stringify.h>
 #include <media/v4l2-ioctl.h>
 
 #include "cpia2.h"
 #include "cpia2dev.h"
 
-
-//#define _CPIA2_DEBUG_
-
-#define MAKE_STRING_1(x)	#x
-#define MAKE_STRING(x)	MAKE_STRING_1(x)
-
 static int video_nr = -1;
 module_param(video_nr, int, 0);
 MODULE_PARM_DESC(video_nr,"video device to register (0=/dev/video0, etc)");
@@ -60,26 +55,26 @@
 static int num_buffers = 3;
 module_param(num_buffers, int, 0);
 MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-"
-		 MAKE_STRING(VIDEO_MAX_FRAME) ", default 3)");
+		 __stringify(VIDEO_MAX_FRAME) ", default 3)");
 
 static int alternate = DEFAULT_ALT;
 module_param(alternate, int, 0);
-MODULE_PARM_DESC(alternate, "USB Alternate (" MAKE_STRING(USBIF_ISO_1) "-"
-		 MAKE_STRING(USBIF_ISO_6) ", default "
-		 MAKE_STRING(DEFAULT_ALT) ")");
+MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"
+		 __stringify(USBIF_ISO_6) ", default "
+		 __stringify(DEFAULT_ALT) ")");
 
 static int flicker_freq = 60;
 module_param(flicker_freq, int, 0);
-MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" MAKE_STRING(50) "or"
-		 MAKE_STRING(60) ", default "
-		 MAKE_STRING(60) ")");
+MODULE_PARM_DESC(flicker_freq, "Flicker frequency (" __stringify(50) "or"
+		 __stringify(60) ", default "
+		 __stringify(60) ")");
 
 static int flicker_mode = NEVER_FLICKER;
 module_param(flicker_mode, int, 0);
 MODULE_PARM_DESC(flicker_mode,
-		 "Flicker supression (" MAKE_STRING(NEVER_FLICKER) "or"
-		 MAKE_STRING(ANTI_FLICKER_ON) ", default "
-		 MAKE_STRING(NEVER_FLICKER) ")");
+		 "Flicker supression (" __stringify(NEVER_FLICKER) "or"
+		 __stringify(ANTI_FLICKER_ON) ", default "
+		 __stringify(NEVER_FLICKER) ")");
 
 MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
 MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
@@ -1926,7 +1921,6 @@
 static struct video_device cpia2_template = {
 	/* I could not find any place for the old .initialize initializer?? */
 	.name=		"CPiA2 Camera",
-	.minor=		-1,
 	.fops=		&fops_template,
 	.release=	video_device_release,
 };
@@ -1967,9 +1961,9 @@
 	if (!cam->open_count) {
 		video_unregister_device(cam->vdev);
 	} else {
-		LOG("/dev/video%d removed while open, "
-		    "deferring video_unregister_device\n",
-		    cam->vdev->num);
+		LOG("%s removed while open, deferring "
+		    "video_unregister_device\n",
+		    video_device_node_name(cam->vdev));
 	}
 }
 
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 4e278db..c0885c6 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -758,8 +758,8 @@
 
 	mutex_lock(&cx->serialize_lock);
 	if (cx18_init_on_first_open(cx)) {
-		CX18_ERR("Failed to initialize on minor %d\n",
-			 video_dev->minor);
+		CX18_ERR("Failed to initialize on %s\n",
+			 video_device_node_name(video_dev));
 		mutex_unlock(&cx->serialize_lock);
 		return -ENXIO;
 	}
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index c398651..987a930 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -219,6 +219,7 @@
 {
 	struct cx18_stream *s = &cx->streams[type];
 	int vfl_type = cx18_stream_info[type].vfl_type;
+	const char *name;
 	int num, ret;
 
 	/* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
@@ -258,31 +259,30 @@
 		s->video_dev = NULL;
 		return ret;
 	}
-	num = s->video_dev->num;
+
+	name = video_device_node_name(s->video_dev);
 
 	switch (vfl_type) {
 	case VFL_TYPE_GRABBER:
-		CX18_INFO("Registered device video%d for %s "
-			  "(%d x %d.%02d kB)\n",
-			  num, s->name, cx->stream_buffers[type],
+		CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
+			  name, s->name, cx->stream_buffers[type],
 			  cx->stream_buf_size[type] / 1024,
 			  (cx->stream_buf_size[type] * 100 / 1024) % 100);
 		break;
 
 	case VFL_TYPE_RADIO:
-		CX18_INFO("Registered device radio%d for %s\n",
-			num, s->name);
+		CX18_INFO("Registered device %s for %s\n", name, s->name);
 		break;
 
 	case VFL_TYPE_VBI:
 		if (cx->stream_buffers[type])
-			CX18_INFO("Registered device vbi%d for %s "
+			CX18_INFO("Registered device %s for %s "
 				  "(%d x %d bytes)\n",
-				  num, s->name, cx->stream_buffers[type],
+				  name, s->name, cx->stream_buffers[type],
 				  cx->stream_buf_size[type]);
 		else
-			CX18_INFO("Registered device vbi%d for %s\n",
-				num, s->name);
+			CX18_INFO("Registered device %s for %s\n",
+				name, s->name);
 		break;
 	}
 
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
index 319c459..a549082 100644
--- a/drivers/media/video/cx231xx/cx231xx-cards.c
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -68,19 +68,19 @@
 				.type = CX231XX_VMUX_TELEVISION,
 				.vmux = CX231XX_VIN_3_1,
 				.amux = CX231XX_AMUX_VIDEO,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_COMPOSITE1,
 				.vmux = CX231XX_VIN_2_1,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_SVIDEO,
 				.vmux = CX231XX_VIN_1_1 |
 					(CX231XX_VIN_1_2 << 8) |
 					CX25840_SVIDEO_ON,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}
 		},
 	},
@@ -107,19 +107,19 @@
 				.type = CX231XX_VMUX_TELEVISION,
 				.vmux = CX231XX_VIN_3_1,
 				.amux = CX231XX_AMUX_VIDEO,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_COMPOSITE1,
 				.vmux = CX231XX_VIN_2_1,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_SVIDEO,
 				.vmux = CX231XX_VIN_1_1 |
 					(CX231XX_VIN_1_2 << 8) |
 					CX25840_SVIDEO_ON,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}
 		},
 	},
@@ -147,19 +147,19 @@
 				.type = CX231XX_VMUX_TELEVISION,
 				.vmux = CX231XX_VIN_3_1,
 				.amux = CX231XX_AMUX_VIDEO,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_COMPOSITE1,
 				.vmux = CX231XX_VIN_2_1,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}, {
 				.type = CX231XX_VMUX_SVIDEO,
 				.vmux = CX231XX_VIN_1_1 |
 					(CX231XX_VIN_1_2 << 8) |
 					CX25840_SVIDEO_ON,
 				.amux = CX231XX_AMUX_LINE_IN,
-				.gpio = 0,
+				.gpio = NULL,
 			}
 		},
 	},
@@ -856,8 +856,9 @@
 
 	if (dev->users) {
 		cx231xx_warn
-		    ("device /dev/video%d is open! Deregistration and memory "
-		     "deallocation are deferred on close.\n", dev->vdev->num);
+		    ("device %s is open! Deregistration and memory "
+		     "deallocation are deferred on close.\n",
+		     video_device_node_name(dev->vdev));
 
 		dev->state |= DEV_MISCONFIGURED;
 		cx231xx_uninit_isoc(dev);
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
index 0d333e6..4a60dfb 100644
--- a/drivers/media/video/cx231xx/cx231xx-core.c
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -66,32 +66,6 @@
 static LIST_HEAD(cx231xx_devlist);
 static DEFINE_MUTEX(cx231xx_devlist_mutex);
 
-struct cx231xx *cx231xx_get_device(int minor,
-				   enum v4l2_buf_type *fh_type, int *has_radio)
-{
-	struct cx231xx *h, *dev = NULL;
-
-	*fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	*has_radio = 0;
-
-	mutex_lock(&cx231xx_devlist_mutex);
-	list_for_each_entry(h, &cx231xx_devlist, devlist) {
-		if (h->vdev->minor == minor)
-			dev = h;
-		if (h->vbi_dev->minor == minor) {
-			dev = h;
-			*fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		}
-		if (h->radio_dev && h->radio_dev->minor == minor) {
-			dev = h;
-			*has_radio = 1;
-		}
-	}
-	mutex_unlock(&cx231xx_devlist_mutex);
-
-	return dev;
-}
-
 /*
  * cx231xx_realease_resources()
  * unregisters the v4l2,i2c and usb devices
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
index cd135f0..15826f9 100644
--- a/drivers/media/video/cx231xx/cx231xx-input.c
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -197,8 +197,7 @@
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER,
-			    dev->board.ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER);
 	if (err < 0)
 		goto err_out_free;
 
@@ -217,7 +216,7 @@
 	cx231xx_ir_start(ir);
 
 	/* all done */
-	err = input_register_device(ir->input);
+	err = ir_input_register(ir->input, dev->board.ir_codes);
 	if (err)
 		goto err_out_stop;
 
@@ -226,8 +225,6 @@
 	cx231xx_ir_stop(ir);
 	dev->ir = NULL;
 err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -241,8 +238,7 @@
 		return 0;
 
 	cx231xx_ir_stop(ir);
-	ir_input_free(ir->input);
-	input_unregister_device(ir->input);
+	ir_input_unregister(ir->input);
 	kfree(ir);
 
 	/* done */
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index d095aa0..d4f546f 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -1916,20 +1916,29 @@
  */
 static int cx231xx_v4l2_open(struct file *filp)
 {
-	int minor = video_devdata(filp)->minor;
 	int errCode = 0, radio = 0;
-	struct cx231xx *dev = NULL;
+	struct video_device *vdev = video_devdata(filp);
+	struct cx231xx *dev = video_drvdata(filp);
 	struct cx231xx_fh *fh;
 	enum v4l2_buf_type fh_type = 0;
 
-	dev = cx231xx_get_device(minor, &fh_type, &radio);
-	if (NULL == dev)
-		return -ENODEV;
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
 
 	mutex_lock(&dev->lock);
 
-	cx231xx_videodbg("open minor=%d type=%s users=%d\n",
-			 minor, v4l2_type_names[fh_type], dev->users);
+	cx231xx_videodbg("open dev=%s type=%s users=%d\n",
+			 video_device_node_name(vdev), v4l2_type_names[fh_type],
+			 dev->users);
 
 #if 0
 	errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
@@ -2020,25 +2029,25 @@
 	/*FIXME: I2C IR should be disconnected */
 
 	if (dev->radio_dev) {
-		if (-1 != dev->radio_dev->minor)
+		if (video_is_registered(dev->radio_dev))
 			video_unregister_device(dev->radio_dev);
 		else
 			video_device_release(dev->radio_dev);
 		dev->radio_dev = NULL;
 	}
 	if (dev->vbi_dev) {
-		cx231xx_info("V4L2 device /dev/vbi%d deregistered\n",
-			     dev->vbi_dev->num);
-		if (-1 != dev->vbi_dev->minor)
+		cx231xx_info("V4L2 device %s deregistered\n",
+			     video_device_node_name(dev->vbi_dev));
+		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
 		else
 			video_device_release(dev->vbi_dev);
 		dev->vbi_dev = NULL;
 	}
 	if (dev->vdev) {
-		cx231xx_info("V4L2 device /dev/video%d deregistered\n",
-			     dev->vdev->num);
-		if (-1 != dev->vdev->minor)
+		cx231xx_info("V4L2 device %s deregistered\n",
+			     video_device_node_name(dev->vdev));
+		if (video_is_registered(dev->vdev))
 			video_unregister_device(dev->vdev);
 		else
 			video_device_release(dev->vdev);
@@ -2268,7 +2277,6 @@
 	.fops         = &cx231xx_v4l_fops,
 	.release      = video_device_release,
 	.ioctl_ops    = &video_ioctl_ops,
-	.minor        = -1,
 	.tvnorms      = V4L2_STD_ALL,
 	.current_norm = V4L2_STD_PAL,
 };
@@ -2303,7 +2311,6 @@
 	.name      = "cx231xx-radio",
 	.fops      = &radio_fops,
 	.ioctl_ops = &radio_ioctl_ops,
-	.minor     = -1,
 };
 
 /******************************** usb interface ******************************/
@@ -2319,13 +2326,13 @@
 		return NULL;
 
 	*vfd = *template;
-	vfd->minor = -1;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	vfd->debug = video_debug;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
+	video_set_drvdata(vfd, dev);
 	return vfd;
 }
 
@@ -2374,8 +2381,8 @@
 		return ret;
 	}
 
-	cx231xx_info("%s/0: registered device video%d [v4l2]\n",
-		     dev->name, dev->vdev->num);
+	cx231xx_info("%s/0: registered device %s [v4l2]\n",
+		     dev->name, video_device_node_name(dev->vdev));
 
 	/* Initialize VBI template */
 	memcpy(&cx231xx_vbi_template, &cx231xx_video_template,
@@ -2393,8 +2400,8 @@
 		return ret;
 	}
 
-	cx231xx_info("%s/0: registered device vbi%d\n",
-		     dev->name, dev->vbi_dev->num);
+	cx231xx_info("%s/0: registered device %s\n",
+		     dev->name, video_device_node_name(dev->vbi_dev));
 
 	if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
 		dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
@@ -2409,12 +2416,13 @@
 			cx231xx_errdev("can't register radio device\n");
 			return ret;
 		}
-		cx231xx_info("Registered radio device as /dev/radio%d\n",
-			     dev->radio_dev->num);
+		cx231xx_info("Registered radio device as %s\n",
+			     video_device_node_name(dev->radio_dev));
 	}
 
-	cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
-		     dev->vdev->num, dev->vbi_dev->num);
+	cx231xx_info("V4L2 device registered as %s and %s\n",
+		     video_device_node_name(dev->vdev),
+		     video_device_node_name(dev->vbi_dev));
 
 	return 0;
 }
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
index 64e2ddd..17d4d1a 100644
--- a/drivers/media/video/cx231xx/cx231xx.h
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -689,8 +689,6 @@
 int cx231xx_register_analog_devices(struct cx231xx *dev);
 void cx231xx_remove_from_devlist(struct cx231xx *dev);
 void cx231xx_add_into_devlist(struct cx231xx *dev);
-struct cx231xx *cx231xx_get_device(int minor,
-				   enum v4l2_buf_type *fh_type, int *has_radio);
 void cx231xx_init_extension(struct cx231xx *dev);
 void cx231xx_close_extension(struct cx231xx *dev);
 
diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c
index c04222f..d4a9d2c 100644
--- a/drivers/media/video/cx23885/cimax2.c
+++ b/drivers/media/video/cx23885/cimax2.c
@@ -53,6 +53,8 @@
 #define NETUP_CI_CTL		0x04
 #define NETUP_CI_RD		1
 
+#define NETUP_IRQ_DETAM 	0x1
+#define NETUP_IRQ_IRQAM		0x4
 
 static unsigned int ci_dbg;
 module_param(ci_dbg, int, 0644);
@@ -73,6 +75,9 @@
 	int status;
 	struct work_struct work;
 	void *priv;
+	u8 current_irq_mode;
+	int current_ci_flag;
+	unsigned long next_status_checked_time;
 };
 
 
@@ -169,24 +174,26 @@
 	if (0 != slot)
 		return -EINVAL;
 
-	ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
-							0, &store, 1);
-	if (ret != 0)
-		return ret;
+	if (state->current_ci_flag != flag) {
+		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+				0, &store, 1);
+		if (ret != 0)
+			return ret;
 
-	store &= ~0x0c;
-	store |= flag;
+		store &= ~0x0c;
+		store |= flag;
 
-	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-							0, &store, 1);
-	if (ret != 0)
-		return ret;
+		ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+				0, &store, 1);
+		if (ret != 0)
+			return ret;
+	};
+	state->current_ci_flag = flag;
 
 	mutex_lock(&dev->gpio_lock);
 
 	/* write addr */
 	cx_write(MC417_OEN, NETUP_EN_ALL);
-	msleep(2);
 	cx_write(MC417_RWD, NETUP_CTRL_OFF |
 				NETUP_ADLO | (0xff & addr));
 	cx_clear(MC417_RWD, NETUP_ADLO);
@@ -196,7 +203,6 @@
 
 	if (read) { /* data in */
 		cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
-		msleep(2);
 	} else /* data out */
 		cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
 
@@ -213,8 +219,8 @@
 		if (mem < 0)
 			return -EREMOTEIO;
 
-	ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
-			(read) ? "read" : "write", addr,
+	ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
+			(read) ? "read" : "write", state->ci_i2c_addr, addr,
 			(flag == NETUP_CI_CTL) ? "ctl" : "mem",
 			(read) ? mem : data);
 
@@ -283,14 +289,39 @@
 	return 0;
 }
 
+int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
+{
+	struct netup_ci_state *state = en50221->data;
+	int ret;
+
+	if (irq_mode == state->current_irq_mode)
+		return 0;
+
+	ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
+			__func__, state->ci_i2c_addr, irq_mode);
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0x1b, &irq_mode, 1);
+
+	if (ret != 0)
+		return ret;
+
+	state->current_irq_mode = irq_mode;
+
+	return 0;
+}
+
 int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
 {
 	struct netup_ci_state *state = en50221->data;
-	u8 buf = 0x60;
+	u8 buf;
 
 	if (0 != slot)
 		return -EINVAL;
 
+	netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+			0, &buf, 1);
+	buf |= 0x60;
+
 	return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
 							0, &buf, 1);
 }
@@ -303,21 +334,35 @@
 	u8 buf[33];
 	int ret;
 
-	ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
-							0, &buf[0], 33);
+	/* CAM module IRQ processing. fast operation */
+	dvb_ca_en50221_frda_irq(&state->ca, 0);
 
-	if (ret != 0)
-		return;
+	/* CAM module INSERT/REMOVE processing. slow operation because of i2c
+	 * transfers */
+	if (time_after(jiffies, state->next_status_checked_time)
+			|| !state->status) {
+		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+				0, &buf[0], 33);
 
-	ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, "
-		"TS config = %02x\n", __func__, state->ci_i2c_addr, 0, buf[0],
-		buf[32]);
+		state->next_status_checked_time = jiffies
+			+ msecs_to_jiffies(1000);
 
-	if (buf[0] & 1)
-		state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
-			DVB_CA_EN50221_POLL_CAM_READY;
-	else
-		state->status = 0;
+		if (ret != 0)
+			return;
+
+		ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
+				"Reg=[0x%02x], data=%02x, "
+				"TS config = %02x\n", __func__,
+				state->ci_i2c_addr, 0, buf[0],
+				buf[0]);
+
+
+		if (buf[0] & 1)
+			state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
+				DVB_CA_EN50221_POLL_CAM_READY;
+		else
+			state->status = 0;
+	};
 }
 
 /* CI irq handler */
@@ -347,6 +392,9 @@
 	if (0 != slot)
 		return -EINVAL;
 
+	netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | NETUP_IRQ_IRQAM)
+			: NETUP_IRQ_DETAM);
+
 	return state->status;
 }
 
@@ -381,8 +429,8 @@
 		0x01, /* power on (use it like store place) */
 		0x00, /* RFU */
 		0x00, /* int status read only */
-		0x01, /* all int unmasked */
-		0x04, /* int config */
+		NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
+		0x05, /* EXTINT=active-high, INT=push-pull */
 		0x00, /* USCG1 */
 		0x04, /* ack active low */
 		0x00, /* LOCK = 0 */
@@ -422,6 +470,7 @@
 	state->ca.poll_slot_status = netup_poll_ci_slot_status;
 	state->ca.data = state;
 	state->priv = port;
+	state->current_irq_mode = NETUP_IRQ_IRQAM | NETUP_IRQ_DETAM;
 
 	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
 						0, &cimax_init[0], 34);
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 0eed852..88c0d24 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -1568,28 +1568,11 @@
 
 static int mpeg_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx23885_dev *h, *dev = NULL;
-	struct list_head *list;
+	struct cx23885_dev *dev = video_drvdata(file);
 	struct cx23885_fh *fh;
 
 	dprintk(2, "%s()\n", __func__);
 
-	lock_kernel();
-	list_for_each(list, &cx23885_devlist) {
-		h = list_entry(list, struct cx23885_dev, devlist);
-		if (h->v4l_device &&
-		    h->v4l_device->minor == minor) {
-			dev = h;
-			break;
-		}
-	}
-
-	if (dev == NULL) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 	if (NULL == fh) {
@@ -1597,6 +1580,8 @@
 		return -ENOMEM;
 	}
 
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev      = dev;
 
@@ -1736,7 +1721,6 @@
 	.name          = "cx23885",
 	.fops          = &mpeg_fops,
 	.ioctl_ops     = &mpeg_ioctl_ops,
-	.minor         = -1,
 	.tvnorms       = CX23885_NORMS,
 	.current_norm  = V4L2_STD_NTSC_M,
 };
@@ -1746,7 +1730,7 @@
 	dprintk(1, "%s()\n", __func__);
 
 	if (dev->v4l_device) {
-		if (-1 != dev->v4l_device->minor)
+		if (video_is_registered(dev->v4l_device))
 			video_unregister_device(dev->v4l_device);
 		else
 			video_device_release(dev->v4l_device);
@@ -1803,6 +1787,7 @@
 	/* Allocate and initialize V4L video device */
 	dev->v4l_device = cx23885_video_dev_alloc(tsport,
 		dev->pci, &cx23885_mpeg_template, "mpeg");
+	video_set_drvdata(dev->v4l_device, dev);
 	err = video_register_device(dev->v4l_device,
 		VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
@@ -1810,8 +1795,8 @@
 		return err;
 	}
 
-	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
-	       dev->name, dev->v4l_device->num);
+	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+	       dev->name, video_device_node_name(dev->v4l_device));
 
 	return 0;
 }
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index 04b12d2..0dde57e 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -55,9 +55,6 @@
 
 static unsigned int cx23885_devcount;
 
-static DEFINE_MUTEX(devlist);
-LIST_HEAD(cx23885_devlist);
-
 #define NO_SYNC_LINE (-1U)
 
 /* FIXME, these allocations will change when
@@ -785,10 +782,6 @@
 	dev->nr = cx23885_devcount++;
 	sprintf(dev->name, "cx23885[%d]", dev->nr);
 
-	mutex_lock(&devlist);
-	list_add_tail(&dev->devlist, &cx23885_devlist);
-	mutex_unlock(&devlist);
-
 	/* Configure the internal memory */
 	if (dev->pci->device == 0x8880) {
 		/* Could be 887 or 888, assume a default */
@@ -2008,10 +2001,6 @@
 	/* unregister stuff */
 	free_irq(pci_dev->irq, dev);
 
-	mutex_lock(&devlist);
-	list_del(&dev->devlist);
-	mutex_unlock(&devlist);
-
 	cx23885_dev_unregister(dev);
 	v4l2_device_unregister(v4l2_dev);
 	kfree(dev);
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 469e083..768eec9 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -377,7 +377,7 @@
 		 cx23885_boards[dev->board].name);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci));
 
-	ret = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	ret = ir_input_init(input_dev, &ir->ir, ir_type);
 	if (ret < 0)
 		goto err_out_free;
 
@@ -397,7 +397,7 @@
 	dev->ir_input = ir;
 	cx23885_input_ir_start(dev);
 
-	ret = input_register_device(ir->dev);
+	ret = ir_input_register(ir->dev, ir_codes);
 	if (ret)
 		goto err_out_stop;
 
@@ -407,8 +407,6 @@
 	cx23885_input_ir_stop(dev);
 	dev->ir_input = NULL;
 err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return ret;
 }
@@ -420,8 +418,7 @@
 
 	if (dev->ir_input == NULL)
 		return;
-	ir_input_free(dev->ir_input->dev);
-	input_unregister_device(dev->ir_input->dev);
+	ir_input_unregister(dev->ir_input->dev);
 	kfree(dev->ir_input);
 	dev->ir_input = NULL;
 }
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 8b372b4..8934d61 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -318,11 +318,11 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor = -1;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 dev->name, type, cx23885_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
 	return vfd;
 }
 
@@ -716,46 +716,34 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx23885_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx23885_dev *dev = video_drvdata(file);
 	struct cx23885_fh *fh;
-	struct list_head *list;
 	enum v4l2_buf_type type = 0;
 	int radio = 0;
 
-	lock_kernel();
-	list_for_each(list, &cx23885_devlist) {
-		h = list_entry(list, struct cx23885_dev, devlist);
-		if (h->video_dev &&
-		    h->video_dev->minor == minor) {
-			dev  = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-		if (h->vbi_dev &&
-		    h->vbi_dev->minor == minor) {
-			dev  = h;
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		}
-		if (h->radio_dev &&
-		    h->radio_dev->minor == minor) {
-			radio = 1;
-			dev   = h;
-		}
-	}
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
 	}
 
-	dprintk(1, "open minor=%d radio=%d type=%s\n",
-		minor, radio, v4l2_type_names[type]);
+	dprintk(1, "open dev=%s radio=%d type=%s\n",
+		video_device_node_name(vdev), radio, v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev      = dev;
 	fh->radio    = radio;
@@ -1441,7 +1429,6 @@
 static struct video_device cx23885_video_template = {
 	.name                 = "cx23885-video",
 	.fops                 = &video_fops,
-	.minor                = -1,
 	.ioctl_ops 	      = &video_ioctl_ops,
 	.tvnorms              = CX23885_NORMS,
 	.current_norm         = V4L2_STD_NTSC_M,
@@ -1461,7 +1448,7 @@
 	cx_clear(PCI_INT_MSK, 1);
 
 	if (dev->video_dev) {
-		if (-1 != dev->video_dev->minor)
+		if (video_is_registered(dev->video_dev))
 			video_unregister_device(dev->video_dev);
 		else
 			video_device_release(dev->video_dev);
@@ -1532,8 +1519,8 @@
 			dev->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
-	       dev->name, dev->video_dev->num);
+	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+	       dev->name, video_device_node_name(dev->video_dev));
 	/* initial device configuration */
 	mutex_lock(&dev->lock);
 	cx23885_set_tvnorm(dev, dev->tvnorm);
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index fa74476..08b3f6b 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -303,7 +303,6 @@
 };
 
 struct cx23885_dev {
-	struct list_head           devlist;
 	atomic_t                   refcount;
 	struct v4l2_device 	   v4l2_dev;
 
@@ -399,8 +398,6 @@
 
 extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
 
-extern struct list_head cx23885_devlist;
-
 #define SRAM_CH01  0 /* Video A */
 #define SRAM_CH02  1 /* VBI A */
 #define SRAM_CH03  2 /* Video B */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index fbdc1cd..6fe30e6 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1048,21 +1048,15 @@
 
 static int mpeg_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx8802_dev *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx8802_fh *fh;
 	struct cx8802_driver *drv = NULL;
 	int err;
 
-	lock_kernel();
-	dev = cx8802_get_device(minor);
-
 	dprintk( 1, "%s\n", __func__);
 
-	if (dev == NULL) {
-		unlock_kernel();
-		return -ENODEV;
-	}
+	lock_kernel();
 
 	/* Make sure we can acquire the hardware */
 	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
@@ -1081,7 +1075,7 @@
 		unlock_kernel();
 		return -EINVAL;
 	}
-	dprintk(1,"open minor=%d\n",minor);
+	dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
@@ -1129,10 +1123,6 @@
 	kfree(fh);
 
 	/* Make sure we release the hardware */
-	dev = cx8802_get_device(video_devdata(file)->minor);
-	if (dev == NULL)
-		return -ENODEV;
-
 	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
 	if (drv)
 		drv->request_release(drv);
@@ -1220,7 +1210,6 @@
 	.name                 = "cx8802",
 	.fops                 = &mpeg_fops,
 	.ioctl_ops 	      = &mpeg_ioctl_ops,
-	.minor                = -1,
 	.tvnorms              = CX88_NORMS,
 	.current_norm         = V4L2_STD_NTSC_M,
 };
@@ -1276,7 +1265,7 @@
 static void blackbird_unregister_video(struct cx8802_dev *dev)
 {
 	if (dev->mpeg_dev) {
-		if (-1 != dev->mpeg_dev->minor)
+		if (video_is_registered(dev->mpeg_dev))
 			video_unregister_device(dev->mpeg_dev);
 		else
 			video_device_release(dev->mpeg_dev);
@@ -1290,14 +1279,15 @@
 
 	dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
 				       &cx8802_mpeg_template,"mpeg");
+	video_set_drvdata(dev->mpeg_dev, dev);
 	err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
 		printk(KERN_INFO "%s/2: can't register mpeg device\n",
 		       dev->core->name);
 		return err;
 	}
-	printk(KERN_INFO "%s/2: registered device video%d [mpeg]\n",
-	       dev->core->name, dev->mpeg_dev->num);
+	printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
+	       dev->core->name, video_device_node_name(dev->mpeg_dev));
 	return 0;
 }
 
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 92b8cdf..f9fda18 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -360,7 +360,7 @@
 	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
 
-	err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, ir_type);
 	if (err < 0)
 		goto err_out_free;
 
@@ -383,7 +383,7 @@
 	cx88_ir_start(core, ir);
 
 	/* all done */
-	err = input_register_device(ir->input);
+	err = ir_input_register(ir->input, ir_codes);
 	if (err)
 		goto err_out_stop;
 
@@ -393,8 +393,6 @@
 	cx88_ir_stop(core, ir);
 	core->ir = NULL;
  err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -408,8 +406,7 @@
 		return 0;
 
 	cx88_ir_stop(core, ir);
-	ir_input_free(ir->input);
-	input_unregister_device(ir->input);
+	ir_input_unregister(ir->input);
 	kfree(ir);
 
 	/* done */
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index de9ff0f..bb51048 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -580,21 +580,6 @@
 	return 0;
 }
 
-#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
-    defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
-struct cx8802_dev *cx8802_get_device(int minor)
-{
-	struct cx8802_dev *dev;
-
-	list_for_each_entry(dev, &cx8802_devlist, devlist)
-		if (dev->mpeg_dev && dev->mpeg_dev->minor == minor)
-			return dev;
-
-	return NULL;
-}
-EXPORT_SYMBOL(cx8802_get_device);
-#endif
-
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
 {
 	struct cx8802_driver *d;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index d7e8fce..48c450f 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -75,10 +75,6 @@
 #define dprintk(level,fmt, arg...)	if (video_debug >= level) \
 	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
 
-/* ------------------------------------------------------------------ */
-
-static LIST_HEAD(cx8800_devlist);
-
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
 
@@ -753,38 +749,31 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx8800_dev *h,*dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core;
 	struct cx8800_fh *fh;
 	enum v4l2_buf_type type = 0;
 	int radio = 0;
 
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
+
 	lock_kernel();
-	list_for_each_entry(h, &cx8800_devlist, devlist) {
-		if (h->video_dev->minor == minor) {
-			dev  = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-		if (h->vbi_dev->minor == minor) {
-			dev  = h;
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		}
-		if (h->radio_dev &&
-		    h->radio_dev->minor == minor) {
-			radio = 1;
-			dev   = h;
-		}
-	}
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
 
 	core = dev->core;
 
-	dprintk(1,"open minor=%d radio=%d type=%s\n",
-		minor,radio,v4l2_type_names[type]);
+	dprintk(1, "open dev=%s radio=%d type=%s\n",
+		video_device_node_name(vdev), radio, v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
@@ -1733,7 +1722,6 @@
 static struct video_device cx8800_video_template = {
 	.name                 = "cx8800-video",
 	.fops                 = &video_fops,
-	.minor                = -1,
 	.ioctl_ops 	      = &video_ioctl_ops,
 	.tvnorms              = CX88_NORMS,
 	.current_norm         = V4L2_STD_NTSC_M,
@@ -1769,7 +1757,6 @@
 static struct video_device cx8800_radio_template = {
 	.name                 = "cx8800-radio",
 	.fops                 = &radio_fops,
-	.minor                = -1,
 	.ioctl_ops 	      = &radio_ioctl_ops,
 };
 
@@ -1778,21 +1765,21 @@
 static void cx8800_unregister_video(struct cx8800_dev *dev)
 {
 	if (dev->radio_dev) {
-		if (-1 != dev->radio_dev->minor)
+		if (video_is_registered(dev->radio_dev))
 			video_unregister_device(dev->radio_dev);
 		else
 			video_device_release(dev->radio_dev);
 		dev->radio_dev = NULL;
 	}
 	if (dev->vbi_dev) {
-		if (-1 != dev->vbi_dev->minor)
+		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
 		else
 			video_device_release(dev->vbi_dev);
 		dev->vbi_dev = NULL;
 	}
 	if (dev->video_dev) {
-		if (-1 != dev->video_dev->minor)
+		if (video_is_registered(dev->video_dev))
 			video_unregister_device(dev->video_dev);
 		else
 			video_device_release(dev->video_dev);
@@ -1909,6 +1896,7 @@
 	/* register v4l devices */
 	dev->video_dev = cx88_vdev_init(core,dev->pci,
 					&cx8800_video_template,"video");
+	video_set_drvdata(dev->video_dev, dev);
 	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
 				    video_nr[core->nr]);
 	if (err < 0) {
@@ -1916,10 +1904,11 @@
 		       core->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device video%d [v4l2]\n",
-	       core->name, dev->video_dev->num);
+	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+	       core->name, video_device_node_name(dev->video_dev));
 
 	dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
+	video_set_drvdata(dev->vbi_dev, dev);
 	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
 				    vbi_nr[core->nr]);
 	if (err < 0) {
@@ -1927,12 +1916,13 @@
 		       core->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device vbi%d\n",
-	       core->name, dev->vbi_dev->num);
+	printk(KERN_INFO "%s/0: registered device %s\n",
+	       core->name, video_device_node_name(dev->vbi_dev));
 
 	if (core->board.radio.type == CX88_RADIO) {
 		dev->radio_dev = cx88_vdev_init(core,dev->pci,
 						&cx8800_radio_template,"radio");
+		video_set_drvdata(dev->radio_dev, dev);
 		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
 					    radio_nr[core->nr]);
 		if (err < 0) {
@@ -1940,12 +1930,11 @@
 			       core->name);
 			goto fail_unreg;
 		}
-		printk(KERN_INFO "%s/0: registered device radio%d\n",
-		       core->name, dev->radio_dev->num);
+		printk(KERN_INFO "%s/0: registered device %s\n",
+		       core->name, video_device_node_name(dev->radio_dev));
 	}
 
 	/* everything worked */
-	list_add_tail(&dev->devlist,&cx8800_devlist);
 	pci_set_drvdata(pci_dev,dev);
 
 	/* initial device configuration */
@@ -2001,7 +1990,6 @@
 
 	/* free memory */
 	btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
-	list_del(&dev->devlist);
 	cx88_core_put(core,dev->pci);
 	kfree(dev);
 }
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index e1c5217..b1499bf 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -423,7 +423,6 @@
 
 struct cx8800_dev {
 	struct cx88_core           *core;
-	struct list_head           devlist;
 	spinlock_t                 slock;
 
 	/* various device info */
@@ -670,7 +669,6 @@
 
 int cx8802_register_driver(struct cx8802_driver *drv);
 int cx8802_unregister_driver(struct cx8802_driver *drv);
-struct cx8802_dev *cx8802_get_device(int minor);
 struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
index c3916a4..de22bc9 100644
--- a/drivers/media/video/davinci/vpfe_capture.c
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -70,7 +70,6 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/version.h>
 #include <media/v4l2-common.h>
 #include <linux/io.h>
 #include <media/davinci/vpfe_capture.h>
@@ -1967,7 +1966,6 @@
 	vfd->release		= video_device_release;
 	vfd->fops		= &vpfe_fops;
 	vfd->ioctl_ops		= &vpfe_ioctl_ops;
-	vfd->minor		= -1;
 	vfd->tvnorms		= 0;
 	vfd->current_norm	= V4L2_STD_PAL;
 	vfd->v4l2_dev 		= &vpfe_dev->v4l2_dev;
@@ -2071,7 +2069,7 @@
 probe_out_v4l2_unregister:
 	v4l2_device_unregister(&vpfe_dev->v4l2_dev);
 probe_out_video_release:
-	if (vpfe_dev->video_dev->minor == -1)
+	if (!video_is_registered(vpfe_dev->video_dev))
 		video_device_release(vpfe_dev->video_dev);
 probe_out_release_irq:
 	free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
@@ -2091,7 +2089,7 @@
 /*
  * vpfe_remove : It un-register device from V4L2 driver
  */
-static int vpfe_remove(struct platform_device *pdev)
+static int __devexit vpfe_remove(struct platform_device *pdev)
 {
 	struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
 	struct resource *res;
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
index 3b8eac3..1f532e3 100644
--- a/drivers/media/video/davinci/vpif.c
+++ b/drivers/media/video/davinci/vpif.c
@@ -266,7 +266,7 @@
 	return status;
 }
 
-static int vpif_remove(struct platform_device *pdev)
+static int __devexit vpif_remove(struct platform_device *pdev)
 {
 	iounmap(vpif_base);
 	release_mem_region(res->start, res_len);
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
index d14cfb2..dfddef7 100644
--- a/drivers/media/video/davinci/vpif_display.c
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -1347,7 +1347,6 @@
 static struct video_device vpif_video_template = {
 	.name		= "vpif",
 	.fops		= &vpif_fops,
-	.minor		= -1,
 	.ioctl_ops	= &vpif_ioctl_ops,
 	.tvnorms	= DM646X_V4L2_STD,
 	.current_norm	= V4L2_STD_625_50,
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
index 453236b..7ee72ec 100644
--- a/drivers/media/video/davinci/vpss.c
+++ b/drivers/media/video/davinci/vpss.c
@@ -268,7 +268,7 @@
 	return status;
 }
 
-static int vpss_remove(struct platform_device *pdev)
+static int __devexit vpss_remove(struct platform_device *pdev)
 {
 	iounmap(oper_cfg.vpss_bl_regs_base);
 	release_mem_region(oper_cfg.r1->start, oper_cfg.len1);
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 82da205..2510000 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -2285,7 +2285,7 @@
 		dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
 		break;
 	case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-		dev->init_data.ir_codes = &ir_codes_hauppauge_new_table;
+		dev->init_data.ir_codes = &ir_codes_rc5_hauppauge_new_table;
 		dev->init_data.get_key = em28xx_get_key_em_haup;
 		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
 		break;
@@ -2653,7 +2653,6 @@
 	INIT_LIST_HEAD(&dev->vbiq.active);
 	INIT_LIST_HEAD(&dev->vbiq.queued);
 
-
 	if (dev->board.has_msp34xx) {
 		/* Send a reset to other chips via gpio */
 		errCode = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
@@ -2923,9 +2922,9 @@
 
 	if (dev->users) {
 		em28xx_warn
-		    ("device /dev/video%d is open! Deregistration and memory "
+		    ("device %s is open! Deregistration and memory "
 		     "deallocation are deferred on close.\n",
-				dev->vdev->num);
+		     video_device_node_name(dev->vdev));
 
 		dev->state |= DEV_MISCONFIGURED;
 		em28xx_uninit_isoc(dev);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 3f86d36..b311d45 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -216,7 +216,7 @@
  * sets only some bits (specified by bitmask) of a register, by first reading
  * the actual value
  */
-static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
 				 u8 bitmask)
 {
 	int oldval;
@@ -1136,34 +1136,6 @@
 static LIST_HEAD(em28xx_devlist);
 static DEFINE_MUTEX(em28xx_devlist_mutex);
 
-struct em28xx *em28xx_get_device(int minor,
-				 enum v4l2_buf_type *fh_type,
-				 int *has_radio)
-{
-	struct em28xx *h, *dev = NULL;
-
-	*fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	*has_radio = 0;
-
-	mutex_lock(&em28xx_devlist_mutex);
-	list_for_each_entry(h, &em28xx_devlist, devlist) {
-		if (h->vdev->minor == minor)
-			dev = h;
-		if (h->vbi_dev && h->vbi_dev->minor == minor) {
-			dev = h;
-			*fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
-		}
-		if (h->radio_dev &&
-		    h->radio_dev->minor == minor) {
-			dev = h;
-			*has_radio = 1;
-		}
-	}
-	mutex_unlock(&em28xx_devlist_mutex);
-
-	return dev;
-}
-
 /*
  * em28xx_realease_resources()
  * unregisters the v4l2,i2c and usb devices
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index d96ec7c..af0d935 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -112,10 +112,13 @@
 int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
 	unsigned char buf[2];
-	unsigned char code;
+	u16 code;
+	int size;
 
 	/* poll IR chip */
-	if (2 != i2c_master_recv(ir->c, buf, 2))
+	size = i2c_master_recv(ir->c, buf, sizeof(buf));
+
+	if (size != 2)
 		return -EIO;
 
 	/* Does eliminate repeated parity code */
@@ -124,16 +127,30 @@
 
 	ir->old = buf[1];
 
-	/* Rearranges bits to the right order */
-	code =   ((buf[0]&0x01)<<5) | /* 0010 0000 */
-		 ((buf[0]&0x02)<<3) | /* 0001 0000 */
-		 ((buf[0]&0x04)<<1) | /* 0000 1000 */
-		 ((buf[0]&0x08)>>1) | /* 0000 0100 */
-		 ((buf[0]&0x10)>>3) | /* 0000 0010 */
-		 ((buf[0]&0x20)>>5);  /* 0000 0001 */
+	/*
+	 * Rearranges bits to the right order.
+	 * The bit order were determined experimentally by using
+	 * The original Hauppauge Grey IR and another RC5 that uses addr=0x08
+	 * The RC5 code has 14 bits, but we've experimentally determined
+	 * the meaning for only 11 bits.
+	 * So, the code translation is not complete. Yet, it is enough to
+	 * work with the provided RC5 IR.
+	 */
+	code =
+		 ((buf[0] & 0x01) ? 0x0020 : 0) | /* 		0010 0000 */
+		 ((buf[0] & 0x02) ? 0x0010 : 0) | /* 		0001 0000 */
+		 ((buf[0] & 0x04) ? 0x0008 : 0) | /* 		0000 1000 */
+		 ((buf[0] & 0x08) ? 0x0004 : 0) | /* 		0000 0100 */
+		 ((buf[0] & 0x10) ? 0x0002 : 0) | /* 		0000 0010 */
+		 ((buf[0] & 0x20) ? 0x0001 : 0) | /* 		0000 0001 */
+		 ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000		  */
+		 ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000		  */
+		 ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100		  */
+		 ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010		  */
+		 ((buf[1] & 0x80) ? 0x0100 : 0);  /* 0000 0001		  */
 
-	i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x)\n",
-			code, buf[0]);
+	i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n",
+			code, buf[1], buf[0]);
 
 	/* return key */
 	*ir_key = code;
@@ -337,19 +354,28 @@
 		goto err_out_free;
 
 	ir->input = input_dev;
+	ir_config = EM2874_IR_RC5;
+
+	/* Adjust xclk based o IR table for RC5/NEC tables */
+	if (dev->board.ir_codes->ir_type == IR_TYPE_RC5) {
+		dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
+		ir->full_code = 1;
+	} else  if (dev->board.ir_codes->ir_type == IR_TYPE_NEC) {
+		dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
+		ir_config = EM2874_IR_NEC;
+		ir->full_code = 1;
+	}
+	em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
+			      EM28XX_XCLK_IR_RC5_MODE);
 
 	/* Setup the proper handler based on the chip */
 	switch (dev->chip_id) {
 	case CHIP_ID_EM2860:
 	case CHIP_ID_EM2883:
-		if (dev->model == EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950)
-			ir->full_code = 1;
 		ir->get_key = default_polling_getkey;
 		break;
 	case CHIP_ID_EM2874:
 		ir->get_key = em2874_polling_getkey;
-		/* For now we only support RC5, so enable it */
-		ir_config = EM2874_IR_RC5;
 		em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
 		break;
 	default:
@@ -367,8 +393,7 @@
 	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
-	err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER,
-			     dev->board.ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER);
 	if (err < 0)
 		goto err_out_free;
 
@@ -387,7 +412,7 @@
 	em28xx_ir_start(ir);
 
 	/* all done */
-	err = input_register_device(ir->input);
+	err = ir_input_register(ir->input, dev->board.ir_codes);
 	if (err)
 		goto err_out_stop;
 
@@ -396,8 +421,6 @@
 	em28xx_ir_stop(ir);
 	dev->ir = NULL;
  err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -411,8 +434,7 @@
 		return 0;
 
 	em28xx_ir_stop(ir);
-	ir_input_free(ir->input);
-	input_unregister_device(ir->input);
+	ir_input_unregister(ir->input);
 	kfree(ir);
 
 	/* done */
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 7ad6537..849b18c 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -2081,22 +2081,30 @@
  */
 static int em28xx_v4l2_open(struct file *filp)
 {
-	int minor = video_devdata(filp)->minor;
-	int errCode = 0, radio;
-	struct em28xx *dev;
-	enum v4l2_buf_type fh_type;
+	int errCode = 0, radio = 0;
+	struct video_device *vdev = video_devdata(filp);
+	struct em28xx *dev = video_drvdata(filp);
+	enum v4l2_buf_type fh_type = 0;
 	struct em28xx_fh *fh;
 	enum v4l2_field field;
 
-	dev = em28xx_get_device(minor, &fh_type, &radio);
-
-	if (NULL == dev)
-		return -ENODEV;
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
 
 	mutex_lock(&dev->lock);
 
-	em28xx_videodbg("open minor=%d type=%s users=%d\n",
-				minor, v4l2_type_names[fh_type], dev->users);
+	em28xx_videodbg("open dev=%s type=%s users=%d\n",
+			video_device_node_name(vdev), v4l2_type_names[fh_type],
+			dev->users);
 
 
 	fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
@@ -2160,25 +2168,25 @@
 	/*FIXME: I2C IR should be disconnected */
 
 	if (dev->radio_dev) {
-		if (-1 != dev->radio_dev->minor)
+		if (video_is_registered(dev->radio_dev))
 			video_unregister_device(dev->radio_dev);
 		else
 			video_device_release(dev->radio_dev);
 		dev->radio_dev = NULL;
 	}
 	if (dev->vbi_dev) {
-		em28xx_info("V4L2 device /dev/vbi%d deregistered\n",
-			    dev->vbi_dev->num);
-		if (-1 != dev->vbi_dev->minor)
+		em28xx_info("V4L2 device %s deregistered\n",
+			    video_device_node_name(dev->vbi_dev));
+		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
 		else
 			video_device_release(dev->vbi_dev);
 		dev->vbi_dev = NULL;
 	}
 	if (dev->vdev) {
-		em28xx_info("V4L2 device /dev/video%d deregistered\n",
-			    dev->vdev->num);
-		if (-1 != dev->vdev->minor)
+		em28xx_info("V4L2 device %s deregistered\n",
+			    video_device_node_name(dev->vdev));
+		if (video_is_registered(dev->vdev))
 			video_unregister_device(dev->vdev);
 		else
 			video_device_release(dev->vdev);
@@ -2397,8 +2405,6 @@
 	.release                    = video_device_release,
 	.ioctl_ops 		    = &video_ioctl_ops,
 
-	.minor                      = -1,
-
 	.tvnorms                    = V4L2_STD_ALL,
 	.current_norm               = V4L2_STD_PAL,
 };
@@ -2433,7 +2439,6 @@
 	.name                 = "em28xx-radio",
 	.fops                 = &radio_fops,
 	.ioctl_ops 	      = &radio_ioctl_ops,
-	.minor                = -1,
 };
 
 /******************************** usb interface ******************************/
@@ -2451,7 +2456,6 @@
 		return NULL;
 
 	*vfd		= *template;
-	vfd->minor	= -1;
 	vfd->v4l2_dev	= &dev->v4l2_dev;
 	vfd->release	= video_device_release;
 	vfd->debug	= video_debug;
@@ -2459,6 +2463,7 @@
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s",
 		 dev->name, type_name);
 
+	video_set_drvdata(vfd, dev);
 	return vfd;
 }
 
@@ -2540,16 +2545,16 @@
 			em28xx_errdev("can't register radio device\n");
 			return ret;
 		}
-		em28xx_info("Registered radio device as /dev/radio%d\n",
-			    dev->radio_dev->num);
+		em28xx_info("Registered radio device as %s\n",
+			    video_device_node_name(dev->radio_dev));
 	}
 
-	em28xx_info("V4L2 video device registered as /dev/video%d\n",
-				dev->vdev->num);
+	em28xx_info("V4L2 video device registered as %s\n",
+		    video_device_node_name(dev->vdev));
 
 	if (dev->vbi_dev)
-		em28xx_info("V4L2 VBI device registered as /dev/vbi%d\n",
-			    dev->vbi_dev->num);
+		em28xx_info("V4L2 VBI device registered as %s\n",
+			    video_device_node_name(dev->vbi_dev));
 
 	return 0;
 }
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 441df64..80d9b4f 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -643,6 +643,8 @@
 			  int len);
 int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
 int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
+int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+				 u8 bitmask);
 
 int em28xx_read_ac97(struct em28xx *dev, u8 reg);
 int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val);
@@ -666,9 +668,6 @@
 void em28xx_wake_i2c(struct em28xx *dev);
 void em28xx_remove_from_devlist(struct em28xx *dev);
 void em28xx_add_into_devlist(struct em28xx *dev);
-struct em28xx *em28xx_get_device(int minor,
-				 enum v4l2_buf_type *fh_type,
-				 int *has_radio);
 int em28xx_register_extension(struct em28xx_ops *dev);
 void em28xx_unregister_extension(struct em28xx_ops *dev);
 void em28xx_init_extension(struct em28xx *dev);
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 88987a5..e6c23d50 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -587,8 +587,8 @@
 	else if (cam->stream != STREAM_OFF) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "URB timeout reached. The camera is misconfigured. To "
-		       "use it, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use it, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1195,7 +1195,8 @@
 
 	cam = container_of(kref, struct et61x251_device, kref);
 
-	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
+	DBG(2, "V4L2 device %s deregistered",
+	    video_device_node_name(cam->v4ldev));
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_unregister_device(cam->v4ldev);
 	usb_put_dev(cam->usbdev);
@@ -1236,8 +1237,8 @@
 	}
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is already in use",
-		       cam->v4ldev->num);
+		DBG(2, "Device %s is already in use",
+		       video_device_node_name(cam->v4ldev));
 		DBG(3, "Simultaneous opens are not supported");
 		if ((filp->f_flags & O_NONBLOCK) ||
 		    (filp->f_flags & O_NDELAY)) {
@@ -1280,7 +1281,8 @@
 	cam->frame_count = 0;
 	et61x251_empty_framequeues(cam);
 
-	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
+	DBG(3, "Video device %s is open",
+	    video_device_node_name(cam->v4ldev));
 
 out:
 	mutex_unlock(&cam->open_mutex);
@@ -1304,7 +1306,8 @@
 	cam->users--;
 	wake_up_interruptible_nr(&cam->wait_open, 1);
 
-	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
+	DBG(3, "Video device %s closed",
+	    video_device_node_name(cam->v4ldev));
 
 	kref_put(&cam->kref, et61x251_release_resources);
 
@@ -1846,8 +1849,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1859,8 +1862,8 @@
 	    nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -2069,8 +2072,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -2081,8 +2084,8 @@
 	    nbuffers != et61x251_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -2130,7 +2133,7 @@
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
 		       "problems. To use the camera, close and open "
-		       "/dev/video%d again.", cam->v4ldev->num);
+		       "%s again.", video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -2584,7 +2587,6 @@
 
 	strcpy(cam->v4ldev->name, "ET61X[12]51 PC Camera");
 	cam->v4ldev->fops = &et61x251_fops;
-	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
 	cam->v4ldev->parent = &udev->dev;
 	video_set_drvdata(cam->v4ldev, cam);
@@ -2603,7 +2605,8 @@
 		goto fail;
 	}
 
-	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
+	DBG(2, "V4L2 device registered as %s",
+	    video_device_node_name(cam->v4ldev));
 
 	cam->module_param.force_munmap = force_munmap[dev_nr];
 	cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2654,9 +2657,9 @@
 	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is open! Deregistration and "
-		       "memory deallocation are deferred.",
-		    cam->v4ldev->num);
+		DBG(2, "Device %s is open! Deregistration and memory "
+		       "deallocation are deferred.",
+		    video_device_node_name(cam->v4ldev));
 		cam->state |= DEV_MISCONFIGURED;
 		et61x251_stop_transfer(cam);
 		cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
index 2f0b8d6..c98b5d6 100644
--- a/drivers/media/video/gspca/conex.c
+++ b/drivers/media/video/gspca/conex.c
@@ -1046,14 +1046,14 @@
 };
 
 /* -- module initialisation -- */
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x0572, 0x0041)},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
index 9de8641..fdf4c0ec 100644
--- a/drivers/media/video/gspca/etoms.c
+++ b/drivers/media/video/gspca/etoms.c
@@ -864,7 +864,7 @@
 };
 
 /* -- module initialisation -- */
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
 #if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
 	{USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
@@ -875,7 +875,7 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 		    const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c
index 1355e52..c276a7d 100644
--- a/drivers/media/video/gspca/gl860/gl860-mi1320.c
+++ b/drivers/media/video/gspca/gl860/gl860-mi1320.c
@@ -345,7 +345,7 @@
 	return 0;
 }
 
-int mi1320_camera_settings(struct gspca_dev *gspca_dev)
+static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c
index 80cb3f1..7c31b4f 100644
--- a/drivers/media/video/gspca/gl860/gl860-mi2020.c
+++ b/drivers/media/video/gspca/gl860/gl860-mi2020.c
@@ -769,7 +769,7 @@
 	return 0;
 }
 
-int mi2020_camera_settings(struct gspca_dev *gspca_dev)
+static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
index a695e0a..4878c8f 100644
--- a/drivers/media/video/gspca/gl860/gl860.c
+++ b/drivers/media/video/gspca/gl860/gl860.c
@@ -40,7 +40,7 @@
 static void sd_callback(struct gspca_dev *gspca_dev);
 
 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
-				s32 vendor_id, s32 product_id);
+				u16 vendor_id, u16 product_id);
 
 /*============================ driver options ==============================*/
 
@@ -326,11 +326,11 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
-	s32 vendor_id, product_id;
+	u16 vendor_id, product_id;
 
 	/* Get USB VendorID and ProductID */
-	vendor_id  = le16_to_cpu(id->idVendor);
-	product_id = le16_to_cpu(id->idProduct);
+	vendor_id  = id->idVendor;
+	product_id = id->idProduct;
 
 	sd->nbRightUp = 1;
 	sd->nbIm = -1;
@@ -534,8 +534,8 @@
 		gspca_dev = usb_get_intfdata(intf);
 
 		PDEBUG(D_PROBE,
-			"Camera is now controlling video device /dev/video%d",
-			gspca_dev->vdev.minor);
+			"Camera is now controlling video device %s",
+			video_device_node_name(&gspca_dev->vdev));
 	}
 
 	return ret;
@@ -673,7 +673,7 @@
 }
 
 static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
-				s32 vendor_id, s32 product_id)
+				u16 vendor_id, u16 product_id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 probe, nb26, nb96, nOV, ntry;
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 4076f8e..e930a67 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -304,7 +304,6 @@
 		j = gspca_dev->fr_queue[i];
 		gspca_dev->cur_frame = &gspca_dev->frame[j];
 	}
-	return;
 }
 EXPORT_SYMBOL(gspca_frame_add);
 
@@ -321,7 +320,7 @@
 	return 0;
 }
 
-static void *rvmalloc(unsigned long size)
+static void *rvmalloc(long size)
 {
 	void *mem;
 	unsigned long adr;
@@ -329,7 +328,7 @@
 	mem = vmalloc_32(size);
 	if (mem != NULL) {
 		adr = (unsigned long) mem;
-		while ((long) size > 0) {
+		while (size > 0) {
 			SetPageReserved(vmalloc_to_page((void *) adr));
 			adr += PAGE_SIZE;
 			size -= PAGE_SIZE;
@@ -768,6 +767,7 @@
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
 	else
@@ -791,6 +791,7 @@
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
 	else
@@ -812,6 +813,7 @@
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
 	else
@@ -983,11 +985,40 @@
 	return -EINVAL;
 }
 
+static int vidioc_enum_frameintervals(struct file *filp, void *priv,
+				      struct v4l2_frmivalenum *fival)
+{
+	struct gspca_dev *gspca_dev = priv;
+	int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
+	__u32 i;
+
+	if (gspca_dev->cam.mode_framerates == NULL ||
+			gspca_dev->cam.mode_framerates[mode].nrates == 0)
+		return -EINVAL;
+
+	if (fival->pixel_format !=
+			gspca_dev->cam.cam_mode[mode].pixelformat)
+		return -EINVAL;
+
+	for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
+		if (fival->index == i) {
+			fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+			fival->discrete.numerator = 1;
+			fival->discrete.denominator =
+				gspca_dev->cam.mode_framerates[mode].rates[i];
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void gspca_release(struct video_device *vfd)
 {
 	struct gspca_dev *gspca_dev = container_of(vfd, struct gspca_dev, vdev);
 
-	PDEBUG(D_PROBE, "/dev/video%d released", gspca_dev->vdev.num);
+	PDEBUG(D_PROBE, "%s released",
+		video_device_node_name(&gspca_dev->vdev));
 
 	kfree(gspca_dev->usb_buf);
 	kfree(gspca_dev);
@@ -1053,6 +1084,7 @@
 	if (gspca_dev->capt_file == file) {
 		if (gspca_dev->streaming) {
 			mutex_lock(&gspca_dev->usb_lock);
+			gspca_dev->usb_err = 0;
 			gspca_stream_off(gspca_dev);
 			mutex_unlock(&gspca_dev->usb_lock);
 		}
@@ -1143,12 +1175,14 @@
 				continue;
 			ctrls = &gspca_dev->sd_desc->ctrls[i];
 		}
+		if (ctrls == NULL)
+			return -EINVAL;
 	} else {
 		ctrls = get_ctrl(gspca_dev, id);
+		if (ctrls == NULL)
+			return -EINVAL;
 		i = ctrls - gspca_dev->sd_desc->ctrls;
 	}
-	if (ctrls == NULL)
-		return -EINVAL;
 	memcpy(q_ctrl, ctrls, sizeof *q_ctrl);
 	if (gspca_dev->ctrl_inac & (1 << i))
 		q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
@@ -1172,6 +1206,7 @@
 	PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = ctrls->set(gspca_dev, ctrl->value);
 	else
@@ -1193,6 +1228,7 @@
 
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = ctrls->get(gspca_dev, &ctrl->value);
 	else
@@ -1307,6 +1343,7 @@
 	/* stop streaming */
 	if (gspca_dev->streaming) {
 		mutex_lock(&gspca_dev->usb_lock);
+		gspca_dev->usb_err = 0;
 		gspca_stream_off(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
 	}
@@ -1398,6 +1435,7 @@
 		ret = -ERESTARTSYS;
 		goto out;
 	}
+	gspca_dev->usb_err = 0;
 	gspca_stream_off(gspca_dev);
 	mutex_unlock(&gspca_dev->usb_lock);
 
@@ -1423,6 +1461,7 @@
 		return -EINVAL;
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
 	else
@@ -1441,6 +1480,7 @@
 		return -EINVAL;
 	if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 		return -ERESTARTSYS;
+	gspca_dev->usb_err = 0;
 	if (gspca_dev->present)
 		ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
 	else
@@ -1461,6 +1501,7 @@
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
+		gspca_dev->usb_err = 0;
 		if (gspca_dev->present)
 			ret = gspca_dev->sd_desc->get_streamparm(gspca_dev,
 								 parm);
@@ -1490,6 +1531,7 @@
 
 		if (mutex_lock_interruptible(&gspca_dev->usb_lock))
 			return -ERESTARTSYS;
+		gspca_dev->usb_err = 0;
 		if (gspca_dev->present)
 			ret = gspca_dev->sd_desc->set_streamparm(gspca_dev,
 								 parm);
@@ -1613,7 +1655,7 @@
 		size -= PAGE_SIZE;
 	}
 
-	vma->vm_ops = (struct vm_operations_struct *) &gspca_vm_ops;
+	vma->vm_ops = &gspca_vm_ops;
 	vma->vm_private_data = frame;
 	gspca_vm_open(vma);
 	ret = 0;
@@ -1661,6 +1703,7 @@
 
 	if (gspca_dev->sd_desc->dq_callback) {
 		mutex_lock(&gspca_dev->usb_lock);
+		gspca_dev->usb_err = 0;
 		if (gspca_dev->present)
 			gspca_dev->sd_desc->dq_callback(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
@@ -1973,6 +2016,7 @@
 	.vidioc_g_parm		= vidioc_g_parm,
 	.vidioc_s_parm		= vidioc_s_parm,
 	.vidioc_enum_framesizes = vidioc_enum_framesizes,
+	.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.vidioc_g_register	= vidioc_g_register,
 	.vidioc_s_register	= vidioc_s_register,
@@ -1988,7 +2032,6 @@
 	.fops = &dev_fops,
 	.ioctl_ops = &dev_ioctl_ops,
 	.release = gspca_release,
-	.minor = -1,
 };
 
 /*
@@ -2049,9 +2092,6 @@
 	ret = sd_desc->init(gspca_dev);
 	if (ret < 0)
 		goto out;
-	ret = gspca_set_alt0(gspca_dev);
-	if (ret < 0)
-		goto out;
 	gspca_set_default_mode(gspca_dev);
 
 	mutex_init(&gspca_dev->usb_lock);
@@ -2073,7 +2113,7 @@
 	}
 
 	usb_set_intfdata(intf, gspca_dev);
-	PDEBUG(D_PROBE, "/dev/video%d created", gspca_dev->vdev.num);
+	PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
 	return 0;
 out:
 	kfree(gspca_dev->usb_buf);
@@ -2092,7 +2132,8 @@
 {
 	struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
 
-	PDEBUG(D_PROBE, "/dev/video%d disconnect", gspca_dev->vdev.num);
+	PDEBUG(D_PROBE, "%s disconnect",
+		video_device_node_name(&gspca_dev->vdev));
 	mutex_lock(&gspca_dev->usb_lock);
 	gspca_dev->present = 0;
 
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 1816173..59c7941d 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -45,11 +45,20 @@
 /* image transfers */
 #define MAX_NURBS 4		/* max number of URBs */
 
+
+/* used to list framerates supported by a camera mode (resolution) */
+struct framerates {
+	int *rates;
+	int nrates;
+};
+
 /* device information - set at probe time */
 struct cam {
 	int bulk_size;		/* buffer size when image transfer by bulk */
 	const struct v4l2_pix_format *cam_mode;	/* size nmodes */
 	char nmodes;
+	const struct framerates *mode_framerates; /* must have size nmode,
+						   * just like cam_mode */
 	__u8 bulk_nurbs;	/* number of URBs in bulk mode
 				 * - cannot be > MAX_NURBS
 				 * - when 0 and bulk_size != 0 means
@@ -171,6 +180,7 @@
 	struct mutex usb_lock;		/* usb exchange protection */
 	struct mutex read_lock;		/* read protection */
 	struct mutex queue_lock;	/* ISOC queue protection */
+	int usb_err;			/* USB error - protected by usb_lock */
 #ifdef CONFIG_PM
 	char frozen;			/* suspend - resume */
 #endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
index 844fc1d8..4294c75 100644
--- a/drivers/media/video/gspca/m5602/m5602_core.c
+++ b/drivers/media/video/gspca/m5602/m5602_core.c
@@ -81,7 +81,7 @@
 	return (err < 0) ? err : 0;
 }
 
-int m5602_wait_for_i2c(struct sd *sd)
+static int m5602_wait_for_i2c(struct sd *sd)
 {
 	int err;
 	u8 data;
@@ -388,7 +388,7 @@
 			       THIS_MODULE);
 }
 
-void m5602_disconnect(struct usb_interface *intf)
+static void m5602_disconnect(struct usb_interface *intf)
 {
 	struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
 	struct sd *sd = (struct sd *) gspca_dev;
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
index c2739d6..923cdd5 100644
--- a/drivers/media/video/gspca/m5602/m5602_ov9650.c
+++ b/drivers/media/video/gspca/m5602/m5602_ov9650.c
@@ -439,7 +439,7 @@
 			err = m5602_write_bridge(sd, res_init_ov9650[i][1],
 				res_init_ov9650[i][2]);
 		else if (res_init_ov9650[i][0] == SENSOR) {
-			u8 data = res_init_ov9650[i][2];
+			data = res_init_ov9650[i][2];
 			err = m5602_write_sensor(sd,
 				res_init_ov9650[i][1], &data, 1);
 		}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
index a27afeb..aa2f3c7e 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
@@ -525,7 +525,10 @@
 	err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
 	if (err < 0)
 		return err;
-	data = (data & 0xfe) | !val;
+	if (val)
+		data &= 0xfe;
+	else
+		data |= 0x01;
 	err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
 	return err;
 }
@@ -570,7 +573,10 @@
 	err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
 	if (err < 0)
 		return err;
-	data = (data & 0xfe) | !val;
+	if (val)
+		data &= 0xfe;
+	else
+		data |= 0x01;
 	err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
 	return err;
 }
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
index 126d968..9154870 100644
--- a/drivers/media/video/gspca/mr97310a.c
+++ b/drivers/media/video/gspca/mr97310a.c
@@ -67,7 +67,7 @@
 MODULE_LICENSE("GPL");
 
 /* global parameters */
-int force_sensor_type = -1;
+static int force_sensor_type = -1;
 module_param(force_sensor_type, int, 0644);
 MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
 
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index ad9ec33..b4f9657 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -1982,7 +1982,7 @@
 {
 	int ret;
 
-	*((u32 *)sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
+	*((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
 
 	ret = usb_control_msg(sd->gspca_dev.dev,
 			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
@@ -2021,9 +2021,9 @@
 		if (rc < 0)
 			return rc;
 
-		do
+		do {
 			rc = reg_r(sd, R511_I2C_CTL);
-		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
 
 		if (rc < 0)
 			return rc;
@@ -2055,9 +2055,9 @@
 		if (rc < 0)
 			return rc;
 
-		do
+		do {
 			rc = reg_r(sd, R511_I2C_CTL);
-		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
 
 		if (rc < 0)
 			return rc;
@@ -2081,9 +2081,9 @@
 		if (rc < 0)
 			return rc;
 
-		do
+		do {
 			rc = reg_r(sd, R511_I2C_CTL);
-		while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
 
 		if (rc < 0)
 			return rc;
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
index 74accee..de0b66c 100644
--- a/drivers/media/video/gspca/pac7302.c
+++ b/drivers/media/video/gspca/pac7302.c
@@ -90,6 +90,9 @@
 	unsigned char autogain;
 	__u8 hflip;
 	__u8 vflip;
+	u8 flags;
+#define FL_HFLIP 0x01		/* mirrored by default */
+#define FL_VFLIP 0x02		/* vertical flipped by default */
 
 	u8 sof_read;
 	u8 autogain_ignore_frames;
@@ -552,6 +555,7 @@
 	sd->autogain = AUTOGAIN_DEF;
 	sd->hflip = HFLIP_DEF;
 	sd->vflip = VFLIP_DEF;
+	sd->flags = id->driver_info;
 	return 0;
 }
 
@@ -708,10 +712,17 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	int ret;
-	__u8 data;
+	u8 data, hflip, vflip;
+
+	hflip = sd->hflip;
+	if (sd->flags & FL_HFLIP)
+		hflip = !hflip;
+	vflip = sd->vflip;
+	if (sd->flags & FL_VFLIP)
+		vflip = !vflip;
 
 	ret = reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
-	data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
+	data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
 	if (0 <= ret)
 		ret = reg_w(gspca_dev, 0x21, data);
 	/* load registers to sensor (Bit 0, auto clear) */
@@ -1218,15 +1229,15 @@
 };
 
 /* -- module initialisation -- */
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x06f8, 0x3009)},
 	{USB_DEVICE(0x093a, 0x2620)},
 	{USB_DEVICE(0x093a, 0x2621)},
-	{USB_DEVICE(0x093a, 0x2622)},
-	{USB_DEVICE(0x093a, 0x2624)},
+	{USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
+	{USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
 	{USB_DEVICE(0x093a, 0x2626)},
 	{USB_DEVICE(0x093a, 0x2628)},
-	{USB_DEVICE(0x093a, 0x2629)},
+	{USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
 	{USB_DEVICE(0x093a, 0x262a)},
 	{USB_DEVICE(0x093a, 0x262c)},
 	{}
@@ -1234,7 +1245,7 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index e5697a6..42cfcdf 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -863,7 +863,7 @@
 };
 
 /* -- module initialisation -- */
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x093a, 0x2600)},
 	{USB_DEVICE(0x093a, 0x2601)},
 	{USB_DEVICE(0x093a, 0x2603)},
@@ -875,7 +875,7 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index b1944a7..4cff803 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -1158,7 +1158,7 @@
 	return i2c_w(gspca_dev, row);
 }
 
-int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
+static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 row[8];
@@ -1183,7 +1183,7 @@
 	return 0;
 }
 
-int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
+static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 row[8];
@@ -1476,8 +1476,9 @@
 	if (input_register_device(sd->input_dev))
 		return -EINVAL;
 
-	sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
-				     gspca_dev->vdev.minor);
+	sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s",
+				     gspca_dev->dev->bus->bus_name,
+				     gspca_dev->dev->devpath);
 
 	if (IS_ERR(sd->input_task))
 		return -EINVAL;
@@ -2174,8 +2175,7 @@
 }
 
 #define HW_WIN(mode, hstart, vstart) \
-((const u8 []){hstart & 0xff, hstart >> 8, \
-vstart & 0xff, vstart >> 8, \
+((const u8 []){hstart, 0, vstart, 0, \
 (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
 (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
 
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 5be95bc..ddff2b5 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -1226,7 +1226,7 @@
 	.driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
 
 
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
 	{USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
@@ -1257,7 +1257,7 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
index ab28cc2..39257e4 100644
--- a/drivers/media/video/gspca/spca506.c
+++ b/drivers/media/video/gspca/spca506.c
@@ -685,7 +685,7 @@
 };
 
 /* -- module initialisation -- */
-static __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] __devinitconst = {
 	{USB_DEVICE(0x06e1, 0xa190)},
 /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
 	{USB_DEVICE(0x0733, 0x0430)}, */
@@ -696,7 +696,7 @@
 MODULE_DEVICE_TABLE(usb, device_table);
 
 /* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
+static int __devinit sd_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
index 8e23320..2e29355 100644
--- a/drivers/media/video/gspca/stk014.c
+++ b/drivers/media/video/gspca/stk014.c
@@ -126,12 +126,14 @@
 };
 
 /* -- read a register -- */
-static int reg_r(struct gspca_dev *gspca_dev,
+static u8 reg_r(struct gspca_dev *gspca_dev,
 			__u16 index)
 {
 	struct usb_device *dev = gspca_dev->dev;
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return 0;
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			0x00,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -141,18 +143,21 @@
 			500);
 	if (ret < 0) {
 		PDEBUG(D_ERR, "reg_r err %d", ret);
-		return ret;
+		gspca_dev->usb_err = ret;
+		return 0;
 	}
 	return gspca_dev->usb_buf[0];
 }
 
 /* -- write a register -- */
-static int reg_w(struct gspca_dev *gspca_dev,
+static void reg_w(struct gspca_dev *gspca_dev,
 			__u16 index, __u16 value)
 {
 	struct usb_device *dev = gspca_dev->dev;
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return;
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			0x01,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -161,13 +166,14 @@
 			NULL,
 			0,
 			500);
-	if (ret < 0)
+	if (ret < 0) {
 		PDEBUG(D_ERR, "reg_w err %d", ret);
-	return ret;
+		gspca_dev->usb_err = ret;
+	}
 }
 
 /* -- get a bulk value (4 bytes) -- */
-static int rcv_val(struct gspca_dev *gspca_dev,
+static void rcv_val(struct gspca_dev *gspca_dev,
 			int ads)
 {
 	struct usb_device *dev = gspca_dev->dev;
@@ -182,17 +188,22 @@
 	reg_w(gspca_dev, 0x63a, 0);
 	reg_w(gspca_dev, 0x63b, 0);
 	reg_w(gspca_dev, 0x630, 5);
+	if (gspca_dev->usb_err < 0)
+		return;
 	ret = usb_bulk_msg(dev,
 			usb_rcvbulkpipe(dev, 0x05),
 			gspca_dev->usb_buf,
 			4,		/* length */
 			&alen,
 			500);		/* timeout in milliseconds */
-	return ret;
+	if (ret < 0) {
+		PDEBUG(D_ERR, "rcv_val err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 }
 
 /* -- send a bulk value -- */
-static int snd_val(struct gspca_dev *gspca_dev,
+static void snd_val(struct gspca_dev *gspca_dev,
 			int ads,
 			unsigned int val)
 {
@@ -201,16 +212,9 @@
 	__u8 seq = 0;
 
 	if (ads == 0x003f08) {
-		ret = reg_r(gspca_dev, 0x0704);
-		if (ret < 0)
-			goto ko;
-		ret = reg_r(gspca_dev, 0x0705);
-		if (ret < 0)
-			goto ko;
-		seq = ret;		/* keep the sequence number */
-		ret = reg_r(gspca_dev, 0x0650);
-		if (ret < 0)
-			goto ko;
+		reg_r(gspca_dev, 0x0704);
+		seq = reg_r(gspca_dev, 0x0705);
+		reg_r(gspca_dev, 0x0650);
 		reg_w(gspca_dev, 0x654, seq);
 	} else {
 		reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
@@ -223,6 +227,8 @@
 	reg_w(gspca_dev, 0x65a, 0);
 	reg_w(gspca_dev, 0x65b, 0);
 	reg_w(gspca_dev, 0x650, 5);
+	if (gspca_dev->usb_err < 0)
+		return;
 	gspca_dev->usb_buf[0] = val >> 24;
 	gspca_dev->usb_buf[1] = val >> 16;
 	gspca_dev->usb_buf[2] = val >> 8;
@@ -233,24 +239,23 @@
 			4,
 			&alen,
 			500);	/* timeout in milliseconds */
-	if (ret < 0)
-		goto ko;
-	if (ads == 0x003f08) {
-		seq += 4;
-		seq &= 0x3f;
-		reg_w(gspca_dev, 0x705, seq);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "snd_val err %d", ret);
+		gspca_dev->usb_err = ret;
+	} else {
+		if (ads == 0x003f08) {
+			seq += 4;
+			seq &= 0x3f;
+			reg_w(gspca_dev, 0x705, seq);
+		}
 	}
-	return ret;
-ko:
-	PDEBUG(D_ERR, "snd_val err %d", ret);
-	return ret;
 }
 
 /* set a camera parameter */
-static int set_par(struct gspca_dev *gspca_dev,
+static void set_par(struct gspca_dev *gspca_dev,
 		   int parval)
 {
-	return snd_val(gspca_dev, 0x003f08, parval);
+	snd_val(gspca_dev, 0x003f08, parval);
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -311,18 +316,18 @@
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	int ret;
+	u8 ret;
 
 	/* check if the device responds */
 	usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
 	ret = reg_r(gspca_dev, 0x0740);
-	if (ret < 0)
-		return ret;
-	if (ret != 0xff) {
-		PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret);
-		return -1;
+	if (gspca_dev->usb_err >= 0) {
+		if (ret != 0xff) {
+			PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret);
+			gspca_dev->usb_err = -EIO;
+		}
 	}
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 /* -- start the camera -- */
@@ -357,15 +362,12 @@
 	if (ret < 0) {
 		PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
 			gspca_dev->iface, gspca_dev->alt);
+		gspca_dev->usb_err = ret;
 		goto out;
 	}
-	ret = reg_r(gspca_dev, 0x0630);
-	if (ret < 0)
-		goto out;
+	 reg_r(gspca_dev, 0x0630);
 	rcv_val(gspca_dev, 0x000020);	/* << (value ff ff ff ff) */
-	ret = reg_r(gspca_dev, 0x0650);
-	if (ret < 0)
-		goto out;
+	reg_r(gspca_dev, 0x0650);
 	snd_val(gspca_dev, 0x000020, 0xffffffff);
 	reg_w(gspca_dev, 0x0620, 0);
 	reg_w(gspca_dev, 0x0630, 0);
@@ -384,11 +386,11 @@
 	/* start the video flow */
 	set_par(gspca_dev, 0x01000000);
 	set_par(gspca_dev, 0x01000000);
-	PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
-	return 0;
+	if (gspca_dev->usb_err >= 0)
+		PDEBUG(D_STREAM, "camera started alt: 0x%02x",
+				gspca_dev->alt);
 out:
-	PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
-	return ret;
+	return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -456,7 +458,7 @@
 	sd->brightness = val;
 	if (gspca_dev->streaming)
 		setbrightness(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -474,7 +476,7 @@
 	sd->contrast = val;
 	if (gspca_dev->streaming)
 		setcontrast(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
@@ -492,7 +494,7 @@
 	sd->colors = val;
 	if (gspca_dev->streaming)
 		setcolors(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
@@ -510,7 +512,7 @@
 	sd->lightfreq = val;
 	if (gspca_dev->streaming)
 		setfreq(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
@@ -552,7 +554,7 @@
 		sd->quality = jcomp->quality;
 	if (gspca_dev->streaming)
 		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
index 72bf3b4..716df6b 100644
--- a/drivers/media/video/gspca/sunplus.c
+++ b/drivers/media/video/gspca/sunplus.c
@@ -460,13 +460,17 @@
 		  u16 index,
 		  u16 len)
 {
+	int ret;
+
 #ifdef GSPCA_DEBUG
 	if (len > USB_BUF_SZ) {
 		err("reg_r: buffer overflow");
 		return;
 	}
 #endif
-	usb_control_msg(gspca_dev->dev,
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
 			req,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -474,6 +478,10 @@
 			index,
 			len ? gspca_dev->usb_buf : NULL, len,
 			500);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "reg_r err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 }
 
 /* write one byte */
@@ -483,40 +491,55 @@
 		   u16 index,
 		   u16 byte)
 {
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
 	gspca_dev->usb_buf[0] = byte;
-	usb_control_msg(gspca_dev->dev,
+	ret = usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
 			req,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index,
 			gspca_dev->usb_buf, 1,
 			500);
+	if (ret < 0) {
+		PDEBUG(D_ERR, "reg_w_1 err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
 }
 
 /* write req / index / value */
-static int reg_w_riv(struct usb_device *dev,
+static void reg_w_riv(struct gspca_dev *gspca_dev,
 		     u8 req, u16 index, u16 value)
 {
+	struct usb_device *dev = gspca_dev->dev;
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return;
 	ret = usb_control_msg(dev,
 			usb_sndctrlpipe(dev, 0),
 			req,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			value, index, NULL, 0, 500);
-	PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
-		req, index, value, ret);
-	if (ret < 0)
-		PDEBUG(D_ERR, "reg write: error %d", ret);
-	return ret;
+	if (ret < 0) {
+		PDEBUG(D_ERR, "reg_w_riv err %d", ret);
+		gspca_dev->usb_err = ret;
+		return;
+	}
+	PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
+		req, index, value);
 }
 
 /* read 1 byte */
-static int reg_r_1(struct gspca_dev *gspca_dev,
+static u8 reg_r_1(struct gspca_dev *gspca_dev,
 			u16 value)	/* wValue */
 {
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return 0;
 	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
 			0x20,			/* request */
@@ -527,19 +550,22 @@
 			500);			/* timeout */
 	if (ret < 0) {
 		PDEBUG(D_ERR, "reg_r_1 err %d", ret);
+		gspca_dev->usb_err = ret;
 		return 0;
 	}
 	return gspca_dev->usb_buf[0];
 }
 
-/* read 1 or 2 bytes - returns < 0 if error */
-static int reg_r_12(struct gspca_dev *gspca_dev,
+/* read 1 or 2 bytes */
+static u16 reg_r_12(struct gspca_dev *gspca_dev,
 			u8 req,		/* bRequest */
 			u16 index,	/* wIndex */
 			u16 length)	/* wLength (1 or 2 only) */
 {
 	int ret;
 
+	if (gspca_dev->usb_err < 0)
+		return 0;
 	gspca_dev->usb_buf[1] = 0;
 	ret = usb_control_msg(gspca_dev->dev,
 			usb_rcvctrlpipe(gspca_dev->dev, 0),
@@ -550,62 +576,44 @@
 			gspca_dev->usb_buf, length,
 			500);
 	if (ret < 0) {
-		PDEBUG(D_ERR, "reg_read err %d", ret);
-		return -1;
+		PDEBUG(D_ERR, "reg_r_12 err %d", ret);
+		gspca_dev->usb_err = ret;
+		return 0;
 	}
 	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
 }
 
-static int write_vector(struct gspca_dev *gspca_dev,
+static void write_vector(struct gspca_dev *gspca_dev,
 			const struct cmd *data, int ncmds)
 {
-	struct usb_device *dev = gspca_dev->dev;
-	int ret;
-
 	while (--ncmds >= 0) {
-		ret = reg_w_riv(dev, data->req, data->idx, data->val);
-		if (ret < 0) {
-			PDEBUG(D_ERR,
-			   "Register write failed for 0x%02x, 0x%04x, 0x%04x",
-				data->req, data->val, data->idx);
-			return ret;
-		}
+		reg_w_riv(gspca_dev, data->req, data->idx, data->val);
 		data++;
 	}
-	return 0;
 }
 
-static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
-				const u8 qtable[2][64])
+static void setup_qtable(struct gspca_dev *gspca_dev,
+			const u8 qtable[2][64])
 {
-	struct usb_device *dev = gspca_dev->dev;
-	int i, err;
+	int i;
 
 	/* loop over y components */
-	for (i = 0; i < 64; i++) {
-		err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]);
-		if (err < 0)
-			return err;
-	}
+	for (i = 0; i < 64; i++)
+		 reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
 
 	/* loop over c components */
-	for (i = 0; i < 64; i++) {
-		err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]);
-		if (err < 0)
-			return err;
-	}
-	return 0;
+	for (i = 0; i < 64; i++)
+		reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
 }
 
 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
 			     u8 req, u16 idx, u16 val)
 {
-	struct usb_device *dev = gspca_dev->dev;
-	int notdone;
+	u16 notdone;
 
-	reg_w_riv(dev, req, idx, val);
+	reg_w_riv(gspca_dev, req, idx, val);
 	notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
-	reg_w_riv(dev, req, idx, val);
+	reg_w_riv(gspca_dev, req, idx, val);
 
 	PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
 
@@ -616,23 +624,22 @@
 
 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
 			u8 req,
-			u16 idx, u16 val, u8 stat, u8 count)
+			u16 idx, u16 val, u16 endcode, u8 count)
 {
-	struct usb_device *dev = gspca_dev->dev;
-	int status;
-	u8 endcode;
+	u16 status;
 
-	reg_w_riv(dev, req, idx, val);
+	reg_w_riv(gspca_dev, req, idx, val);
 	status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
-	endcode = stat;
-	PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat);
+	if (gspca_dev->usb_err < 0)
+		return;
+	PDEBUG(D_FRAM, "Status 0x%04x Need 0x%04x", status, endcode);
 	if (!count)
 		return;
 	count = 200;
 	while (--count > 0) {
 		msleep(10);
 		/* gsmart mini2 write a each wait setting 1 ms is enough */
-/*		reg_w_riv(dev, req, idx, val); */
+/*		reg_w_riv(gspca_dev, req, idx, val); */
 		status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
 		if (status == endcode) {
 			PDEBUG(D_FRAM, "status 0x%04x after wait %d",
@@ -642,7 +649,7 @@
 	}
 }
 
-static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
+static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
 {
 	int count = 10;
 
@@ -652,7 +659,6 @@
 			break;
 		msleep(10);
 	}
-	return gspca_dev->usb_buf[0];
 }
 
 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
@@ -686,28 +692,26 @@
 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	u8 Size;
-	int rc;
 
 	Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
 	switch (sd->bridge) {
 	case BRIDGE_SPCA533:
-		reg_w_riv(dev, 0x31, 0, 0);
+		reg_w_riv(gspca_dev, 0x31, 0, 0);
 		spca504B_WaitCmdStatus(gspca_dev);
-		rc = spca504B_PollingDataReady(gspca_dev);
+		spca504B_PollingDataReady(gspca_dev);
 		spca50x_GetFirmware(gspca_dev);
 		reg_w_1(gspca_dev, 0x24, 0, 8, 2);		/* type */
 		reg_r(gspca_dev, 0x24, 8, 1);
 
 		reg_w_1(gspca_dev, 0x25, 0, 4, Size);
 		reg_r(gspca_dev, 0x25, 4, 1);			/* size */
-		rc = spca504B_PollingDataReady(gspca_dev);
+		spca504B_PollingDataReady(gspca_dev);
 
 		/* Init the cam width height with some values get on init ? */
-		reg_w_riv(dev, 0x31, 0, 0x04);
+		reg_w_riv(gspca_dev, 0x31, 0, 0x04);
 		spca504B_WaitCmdStatus(gspca_dev);
-		rc = spca504B_PollingDataReady(gspca_dev);
+		spca504B_PollingDataReady(gspca_dev);
 		break;
 	default:
 /* case BRIDGE_SPCA504B: */
@@ -716,7 +720,7 @@
 		reg_r(gspca_dev, 0x25, 4, 1);			/* size */
 		reg_w_1(gspca_dev, 0x27, 0, 0, 6);
 		reg_r(gspca_dev, 0x27, 0, 1);			/* type */
-		rc = spca504B_PollingDataReady(gspca_dev);
+		spca504B_PollingDataReady(gspca_dev);
 		break;
 	case BRIDGE_SPCA504:
 		Size += 3;
@@ -733,8 +737,8 @@
 		break;
 	case BRIDGE_SPCA504C:
 		/* capture mode */
-		reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
-		reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
+		reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
+		reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
 		break;
 	}
 }
@@ -762,37 +766,33 @@
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	u16 reg;
 
 	reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
-	reg_w_riv(dev, 0x00, reg, sd->brightness);
+	reg_w_riv(gspca_dev, 0x00, reg, sd->brightness);
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	u16 reg;
 
 	reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
-	reg_w_riv(dev, 0x00, reg, sd->contrast);
+	reg_w_riv(gspca_dev, 0x00, reg, sd->contrast);
 }
 
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	u16 reg;
 
 	reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
-	reg_w_riv(dev, 0x00, reg, sd->colors);
+	reg_w_riv(gspca_dev, 0x00, reg, sd->colors);
 }
 
 static void init_ctl_reg(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int pollreg = 1;
 
 	setbrightness(gspca_dev);
@@ -807,14 +807,14 @@
 	default:
 /*	case BRIDGE_SPCA533: */
 /*	case BRIDGE_SPCA504B: */
-		reg_w_riv(dev, 0, 0x00, 0x21ad);	/* hue */
-		reg_w_riv(dev, 0, 0x01, 0x21ac);	/* sat/hue */
-		reg_w_riv(dev, 0, 0x00, 0x21a3);	/* gamma */
+		reg_w_riv(gspca_dev, 0, 0x00, 0x21ad);	/* hue */
+		reg_w_riv(gspca_dev, 0, 0x01, 0x21ac);	/* sat/hue */
+		reg_w_riv(gspca_dev, 0, 0x00, 0x21a3);	/* gamma */
 		break;
 	case BRIDGE_SPCA536:
-		reg_w_riv(dev, 0, 0x40, 0x20f5);
-		reg_w_riv(dev, 0, 0x01, 0x20f4);
-		reg_w_riv(dev, 0, 0x00, 0x2089);
+		reg_w_riv(gspca_dev, 0, 0x40, 0x20f5);
+		reg_w_riv(gspca_dev, 0, 0x01, 0x20f4);
+		reg_w_riv(gspca_dev, 0, 0x00, 0x2089);
 		break;
 	}
 	if (pollreg)
@@ -881,18 +881,17 @@
 static int sd_init(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
-	int i, err_code;
+	int i;
 	u8 info[6];
 
 	switch (sd->bridge) {
 	case BRIDGE_SPCA504B:
-		reg_w_riv(dev, 0x1d, 0x00, 0);
-		reg_w_riv(dev, 0, 0x01, 0x2306);
-		reg_w_riv(dev, 0, 0x00, 0x0d04);
-		reg_w_riv(dev, 0, 0x00, 0x2000);
-		reg_w_riv(dev, 0, 0x13, 0x2301);
-		reg_w_riv(dev, 0, 0x00, 0x2306);
+		reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
+		reg_w_riv(gspca_dev, 0, 0x01, 0x2306);
+		reg_w_riv(gspca_dev, 0, 0x00, 0x0d04);
+		reg_w_riv(gspca_dev, 0, 0x00, 0x2000);
+		reg_w_riv(gspca_dev, 0, 0x13, 0x2301);
+		reg_w_riv(gspca_dev, 0, 0x00, 0x2306);
 		/* fall thru */
 	case BRIDGE_SPCA533:
 		spca504B_PollingDataReady(gspca_dev);
@@ -904,13 +903,13 @@
 		reg_w_1(gspca_dev, 0x24, 0, 0, 0);
 		reg_r(gspca_dev, 0x24, 0, 1);
 		spca504B_PollingDataReady(gspca_dev);
-		reg_w_riv(dev, 0x34, 0, 0);
+		reg_w_riv(gspca_dev, 0x34, 0, 0);
 		spca504B_WaitCmdStatus(gspca_dev);
 		break;
 	case BRIDGE_SPCA504C:	/* pccam600 */
 		PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
-		reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
-		reg_w_riv(dev, 0xe0, 0x0000, 0x0001);	/* reset */
+		reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
+		reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);	/* reset */
 		spca504_wait_status(gspca_dev);
 		if (sd->subtype == LogitechClickSmart420)
 			write_vector(gspca_dev,
@@ -919,12 +918,7 @@
 		else
 			write_vector(gspca_dev, spca504_pccam600_open_data,
 				ARRAY_SIZE(spca504_pccam600_open_data));
-		err_code = spca50x_setup_qtable(gspca_dev,
-						qtable_creative_pccam);
-		if (err_code < 0) {
-			PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
-			return err_code;
-		}
+		setup_qtable(gspca_dev, qtable_creative_pccam);
 		break;
 	default:
 /*	case BRIDGE_SPCA504: */
@@ -958,29 +952,24 @@
 							6, 0, 0x86, 1); */
 /*			spca504A_acknowledged_command (gspca_dev, 0x24,
 							0, 0, 0x9D, 1); */
-			reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
-			reg_w_riv(dev, 0x00, 0x2310, 0x05);
+			reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
+							/* L92 sno1t.txt */
+			reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 			spca504A_acknowledged_command(gspca_dev, 0x01,
 							0x0f, 0, 0xff, 0);
 		}
 		/* setup qtable */
-		reg_w_riv(dev, 0, 0x2000, 0);
-		reg_w_riv(dev, 0, 0x2883, 1);
-		err_code = spca50x_setup_qtable(gspca_dev,
-						qtable_spca504_default);
-		if (err_code < 0) {
-			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-			return err_code;
-		}
+		reg_w_riv(gspca_dev, 0, 0x2000, 0);
+		reg_w_riv(gspca_dev, 0, 0x2883, 1);
+		setup_qtable(gspca_dev, qtable_spca504_default);
 		break;
 	}
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 	int enable;
 	int i;
 	u8 info[6];
@@ -1005,13 +994,13 @@
 		case MegapixV4:
 		case LogitechClickSmart820:
 		case MegaImageVI:
-			reg_w_riv(dev, 0xf0, 0, 0);
+			reg_w_riv(gspca_dev, 0xf0, 0, 0);
 			spca504B_WaitCmdStatus(gspca_dev);
 			reg_r(gspca_dev, 0xf0, 4, 0);
 			spca504B_WaitCmdStatus(gspca_dev);
 			break;
 		default:
-			reg_w_riv(dev, 0x31, 0, 0x04);
+			reg_w_riv(gspca_dev, 0x31, 0, 0x04);
 			spca504B_WaitCmdStatus(gspca_dev);
 			spca504B_PollingDataReady(gspca_dev);
 			break;
@@ -1048,8 +1037,9 @@
 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
 		}
 		spca504B_SetSizeType(gspca_dev);
-		reg_w_riv(dev, 0x00, 0x270c, 0x05);	/* L92 sno1t.txt */
-		reg_w_riv(dev, 0x00, 0x2310, 0x05);
+		reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
+							/* L92 sno1t.txt */
+		reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
 		break;
 	case BRIDGE_SPCA504C:
 		if (sd->subtype == LogitechClickSmart420) {
@@ -1061,36 +1051,37 @@
 				ARRAY_SIZE(spca504_pccam600_init_data));
 		}
 		enable = (sd->autogain ? 0x04 : 0x01);
-		reg_w_riv(dev, 0x0c, 0x0000, enable);	/* auto exposure */
-		reg_w_riv(dev, 0xb0, 0x0000, enable);	/* auto whiteness */
+		reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
+							/* auto exposure */
+		reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
+							/* auto whiteness */
 
 		/* set default exposure compensation and whiteness balance */
-		reg_w_riv(dev, 0x30, 0x0001, 800);	/* ~ 20 fps */
-		reg_w_riv(dev, 0x30, 0x0002, 1600);
+		reg_w_riv(gspca_dev, 0x30, 0x0001, 800);	/* ~ 20 fps */
+		reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
 		spca504B_SetSizeType(gspca_dev);
 		break;
 	}
 	init_ctl_reg(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct usb_device *dev = gspca_dev->dev;
 
 	switch (sd->bridge) {
 	default:
 /*	case BRIDGE_SPCA533: */
 /*	case BRIDGE_SPCA536: */
 /*	case BRIDGE_SPCA504B: */
-		reg_w_riv(dev, 0x31, 0, 0);
+		reg_w_riv(gspca_dev, 0x31, 0, 0);
 		spca504B_WaitCmdStatus(gspca_dev);
 		spca504B_PollingDataReady(gspca_dev);
 		break;
 	case BRIDGE_SPCA504:
 	case BRIDGE_SPCA504C:
-		reg_w_riv(dev, 0x00, 0x2000, 0x0000);
+		reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
 
 		if (sd->subtype == AiptekMiniPenCam13) {
 			/* spca504a aiptek */
@@ -1102,7 +1093,7 @@
 							0x0f, 0x00, 0xff, 1);
 		} else {
 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
-			reg_w_riv(dev, 0x01, 0x000f, 0x0000);
+			reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
 		}
 		break;
 	}
@@ -1216,7 +1207,7 @@
 	sd->brightness = val;
 	if (gspca_dev->streaming)
 		setbrightness(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
@@ -1234,7 +1225,7 @@
 	sd->contrast = val;
 	if (gspca_dev->streaming)
 		setcontrast(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
@@ -1252,7 +1243,7 @@
 	sd->colors = val;
 	if (gspca_dev->streaming)
 		setcolors(gspca_dev);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
@@ -1292,7 +1283,7 @@
 		sd->quality = jcomp->quality;
 	if (gspca_dev->streaming)
 		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
-	return 0;
+	return gspca_dev->usb_err;
 }
 
 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 69e5dc4..1a800fc 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -5345,9 +5345,6 @@
 	{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
 	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
 	{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-	{0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
-	{0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
-
 	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
 	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
 	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
@@ -5364,27 +5361,27 @@
 	{0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
 	{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 	{0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-	{0xa0, 0x95, ZC3XX_R18D_YTARGET},
+	{0xa0, 0x70, ZC3XX_R18D_YTARGET},
 	{0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
 	{0xa0, 0x00, 0x01ad},
 	{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
 	{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
 	{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 	{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+	{0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
+	{0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
 	{}
 };
 static const struct usb_action tas5130cxx_Initial[] = {	/* 640x480 */
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
 	{0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
-	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+	{0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
 	{0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
 	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
 	{0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
 	{0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
 	{0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
 	{0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-	{0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
-	{0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
 	{0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
 	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
 	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
@@ -5400,13 +5397,15 @@
 	{0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
 	{0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
 	{0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-	{0xa0, 0x95, ZC3XX_R18D_YTARGET},
+	{0xa0, 0x70, ZC3XX_R18D_YTARGET},
 	{0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
 	{0xa0, 0x00, 0x01ad},
 	{0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
 	{0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
 	{0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
 	{0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+	{0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
+	{0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
 	{}
 };
 static const struct usb_action tas5130cxx_50HZ[] = {
@@ -6424,11 +6423,11 @@
 	if (retword != 0)
 		return 0x0e;			/* PAS202BCB */
 
-	start_2wr_probe(dev, 0x02);		/* ?? */
+	start_2wr_probe(dev, 0x02);		/* TAS5130C */
 	i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
 	retword = i2c_read(gspca_dev, 0x01);
 	if (retword != 0)
-		return 0x02;			/* ?? */
+		return 0x02;			/* TAS5130C */
 ov_check:
 	reg_r(gspca_dev, 0x0010);		/* ?? */
 	reg_r(gspca_dev, 0x0010);
@@ -6505,6 +6504,8 @@
 	reg_r(gspca_dev, 0x0010);
 	/* value 0x4001 is meaningless */
 	if (retword != 0x4001) {
+		if ((retword & 0xff00) == 0x6400)
+			return 0x02;		/* TAS5130C */
 		for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
 			if (chipset_revision_sensor[i].revision == retword) {
 				sd->chip_revision = retword;
@@ -6515,7 +6516,7 @@
 		}
 	}
 
-	reg_w(dev, 0x01, 0x0000);	/* check ?? */
+	reg_w(dev, 0x01, 0x0000);	/* check PB0330 */
 	reg_w(dev, 0x01, 0x0001);
 	reg_w(dev, 0xdd, 0x008b);
 	reg_w(dev, 0x0a, 0x0010);
@@ -6524,7 +6525,7 @@
 	retword = i2c_read(gspca_dev, 0x00);
 	if (retword != 0) {
 		PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
-		return 0x0a;			/* ?? */
+		return 0x0a;			/* PB0330 */
 	}
 
 	reg_w(dev, 0x01, 0x0000);
@@ -6673,6 +6674,10 @@
 			PDEBUG(D_PROBE, "Find Sensor HV7131B");
 			sd->sensor = SENSOR_HV7131B;
 			break;
+		case 0x02:
+			PDEBUG(D_PROBE, "Sensor TAS5130C");
+			sd->sensor = SENSOR_TAS5130CXX;
+			break;
 		case 0x04:
 			PDEBUG(D_PROBE, "Find Sensor CS2102");
 			sd->sensor = SENSOR_CS2102;
@@ -6866,11 +6871,14 @@
 	case SENSOR_GC0305:
 	case SENSOR_OV7620:
 	case SENSOR_PO2030:
+	case SENSOR_TAS5130CXX:
 	case SENSOR_TAS5130C_VF0250:
 /*		msleep(100);			 * ?? */
 		reg_r(gspca_dev, 0x0002);	/* --> 0x40 */
 		reg_w(dev, 0x09, 0x01ad);	/* (from win traces) */
 		reg_w(dev, 0x15, 0x01ae);
+		if (sd->sensor == SENSOR_TAS5130CXX)
+			break;
 		reg_w(dev, 0x0d, 0x003a);
 		reg_w(dev, 0x02, 0x003b);
 		reg_w(dev, 0x00, 0x0038);
@@ -6887,6 +6895,7 @@
 		break;
 	case SENSOR_PAS202B:
 	case SENSOR_GC0305:
+	case SENSOR_TAS5130CXX:
 		reg_r(gspca_dev, 0x0008);
 		/* fall thru */
 	case SENSOR_PO2030:
@@ -6928,6 +6937,7 @@
 		reg_w(dev, 0x40, 0x0117);
 		break;
 	case SENSOR_GC0305:
+	case SENSOR_TAS5130CXX:
 		reg_w(dev, 0x09, 0x01ad);	/* (from win traces) */
 		reg_w(dev, 0x15, 0x01ae);
 		/* fall thru */
@@ -7220,7 +7230,7 @@
 	{USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
 	{USB_DEVICE(0x0ac8, 0x301b)},
 	{USB_DEVICE(0x0ac8, 0x303b)},
-	{USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
+	{USB_DEVICE(0x0ac8, 0x305b)},
 	{USB_DEVICE(0x0ac8, 0x307b)},
 	{USB_DEVICE(0x10fd, 0x0128)},
 	{USB_DEVICE(0x10fd, 0x804d)},
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
index 1c9bc94..51f393d 100644
--- a/drivers/media/video/hdpvr/hdpvr-core.c
+++ b/drivers/media/video/hdpvr/hdpvr-core.c
@@ -145,7 +145,7 @@
 #ifdef HDPVR_DEBUG
 	else {
 		hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf,
-				   sizeof(print_buf), 0);
+				   5*buf_size+1, 0);
 		v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
 			 "Status request returned, len %d: %s\n",
 			 ret, print_buf);
@@ -168,13 +168,13 @@
 
 	response = dev->usbc_buf+38;
 #ifdef HDPVR_DEBUG
-	hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0);
+	hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
 	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n",
 		 print_buf);
 #endif
 	challenge(response);
 #ifdef HDPVR_DEBUG
-	hex_dump_to_buffer(response, 8, 16, 1, print_buf, sizeof(print_buf), 0);
+	hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
 	v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
 		 print_buf);
 #endif
@@ -376,8 +376,8 @@
 	usb_set_intfdata(interface, dev);
 
 	/* let the user know what node this device is now attached to */
-	v4l2_info(&dev->v4l2_dev, "device now attached to /dev/video%d\n",
-		  dev->video_dev->minor);
+	v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
+		  video_device_node_name(dev->video_dev));
 	return 0;
 
 error:
@@ -391,13 +391,10 @@
 static void hdpvr_disconnect(struct usb_interface *interface)
 {
 	struct hdpvr_device *dev;
-	int minor;
 
 	dev = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 
-	minor = dev->video_dev->minor;
-
 	/* prevent more I/O from starting and stop any ongoing */
 	mutex_lock(&dev->io_mutex);
 	dev->status = STATUS_DISCONNECTED;
@@ -425,7 +422,8 @@
 
 	atomic_dec(&dev_nr);
 
-	v4l2_info(&dev->v4l2_dev, "device /dev/video%d disconnected\n", minor);
+	v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
+		  video_device_node_name(dev->video_dev));
 
 	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev->usbc_buf);
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index b5439ca..fdd7820 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -523,7 +523,7 @@
 
 	mutex_lock(&dev->io_mutex);
 
-	if (video_is_unregistered(dev->video_dev)) {
+	if (!video_is_registered(dev->video_dev)) {
 		mutex_unlock(&dev->io_mutex);
 		return -EIO;
 	}
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 64360d2..b86e353 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -353,6 +353,7 @@
 		ir_type     = IR_TYPE_RC5;
 		ir_codes    = &ir_codes_fusionhdtv_mce_table;
 		break;
+	case 0x0b:
 	case 0x47:
 	case 0x71:
 		if (adap->id == I2C_HW_B_CX2388x ||
@@ -422,7 +423,7 @@
 
 	/* Make sure we are all setup before going on */
 	if (!name || !ir->get_key || !ir_type || !ir_codes) {
-		dprintk(1, DEVNAME ": Unsupported device at address 0x%02x\n",
+		dprintk(1, ": Unsupported device at address 0x%02x\n",
 			addr);
 		err = -ENODEV;
 		goto err_out_free;
@@ -437,7 +438,7 @@
 		 dev_name(&client->dev));
 
 	/* init + register input device */
-	err = ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, ir_type);
 	if (err < 0)
 		goto err_out_free;
 
@@ -445,7 +446,7 @@
 	input_dev->name       = ir->name;
 	input_dev->phys       = ir->phys;
 
-	err = input_register_device(ir->input);
+	err = ir_input_register(ir->input, ir->ir_codes);
 	if (err)
 		goto err_out_free;
 
@@ -459,8 +460,6 @@
 	return 0;
 
  err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -473,8 +472,7 @@
 	cancel_delayed_work_sync(&ir->work);
 
 	/* unregister device */
-	ir_input_free(ir->input);
-	input_unregister_device(ir->input);
+	ir_input_unregister(ir->input);
 
 	/* free memory */
 	kfree(ir);
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index e707ef3..babcabd 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -985,8 +985,8 @@
 
 	mutex_lock(&itv->serialize_lock);
 	if (ivtv_init_on_first_open(itv)) {
-		IVTV_ERR("Failed to initialize on minor %d\n",
-				vdev->minor);
+		IVTV_ERR("Failed to initialize on device %s\n",
+			 video_device_node_name(vdev));
 		mutex_unlock(&itv->serialize_lock);
 		return -ENXIO;
 	}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 67699e3..e12c602 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -245,6 +245,7 @@
 {
 	struct ivtv_stream *s = &itv->streams[type];
 	int vfl_type = ivtv_stream_info[type].vfl_type;
+	const char *name;
 	int num;
 
 	if (s->vdev == NULL)
@@ -268,24 +269,24 @@
 		s->vdev = NULL;
 		return -ENOMEM;
 	}
-	num = s->vdev->num;
+	name = video_device_node_name(s->vdev);
 
 	switch (vfl_type) {
 	case VFL_TYPE_GRABBER:
-		IVTV_INFO("Registered device video%d for %s (%d kB)\n",
-			num, s->name, itv->options.kilobytes[type]);
+		IVTV_INFO("Registered device %s for %s (%d kB)\n",
+			name, s->name, itv->options.kilobytes[type]);
 		break;
 	case VFL_TYPE_RADIO:
-		IVTV_INFO("Registered device radio%d for %s\n",
-			num, s->name);
+		IVTV_INFO("Registered device %s for %s\n",
+			name, s->name);
 		break;
 	case VFL_TYPE_VBI:
 		if (itv->options.kilobytes[type])
-			IVTV_INFO("Registered device vbi%d for %s (%d kB)\n",
-				num, s->name, itv->options.kilobytes[type]);
+			IVTV_INFO("Registered device %s for %s (%d kB)\n",
+				name, s->name, itv->options.kilobytes[type]);
 		else
-			IVTV_INFO("Registered device vbi%d for %s\n",
-				num, s->name);
+			IVTV_INFO("Registered device %s for %s\n",
+				name, s->name);
 		break;
 	}
 	return 0;
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 01e1eef..6ffa64c 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1681,7 +1681,6 @@
 	.fops		= &meye_fops,
 	.ioctl_ops 	= &meye_ioctl_ops,
 	.release	= video_device_release,
-	.minor		= -1,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 45388d2..b62c0bd 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -17,9 +17,11 @@
 #include <media/v4l2-chip-ident.h>
 #include <media/soc_camera.h>
 
-/* mt9m001 i2c address 0x5d
+/*
+ * mt9m001 i2c address 0x5d
  * The platform has to define ctruct i2c_board_info objects and link to them
- * from struct soc_camera_link */
+ * from struct soc_camera_link
+ */
 
 /* mt9m001 selected register addresses */
 #define MT9M001_CHIP_VERSION		0x00
@@ -46,42 +48,50 @@
 #define MT9M001_COLUMN_SKIP		20
 #define MT9M001_ROW_SKIP		12
 
-static const struct soc_camera_data_format mt9m001_colour_formats[] = {
-	/* Order important: first natively supported,
-	 * second supported with a GPIO extender */
-	{
-		.name		= "Bayer (sRGB) 10 bit",
-		.depth		= 10,
-		.fourcc		= V4L2_PIX_FMT_SBGGR16,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}, {
-		.name		= "Bayer (sRGB) 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_SBGGR8,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}
+/* MT9M001 has only one fixed colorspace per pixelcode */
+struct mt9m001_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
 };
 
-static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
+/* Find a data format by a pixel code in an array */
+static const struct mt9m001_datafmt *mt9m001_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct mt9m001_datafmt mt9m001_colour_fmts[] = {
+	/*
+	 * Order important: first natively supported,
+	 * second supported with a GPIO extender
+	 */
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
 	/* Order important - see above */
-	{
-		.name		= "Monochrome 10 bit",
-		.depth		= 10,
-		.fourcc		= V4L2_PIX_FMT_Y16,
-	}, {
-		.name		= "Monochrome 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_GREY,
-	},
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 struct mt9m001 {
 	struct v4l2_subdev subdev;
 	struct v4l2_rect rect;	/* Sensor window */
-	__u32 fourcc;
+	const struct mt9m001_datafmt *fmt;
+	const struct mt9m001_datafmt *fmts;
+	int num_fmts;
 	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
 	unsigned int gain;
 	unsigned int exposure;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
 	unsigned char autoexposure;
 };
 
@@ -204,8 +214,7 @@
 	const u16 hblank = 9, vblank = 25;
 	unsigned int total_h;
 
-	if (mt9m001->fourcc == V4L2_PIX_FMT_SBGGR8 ||
-	    mt9m001->fourcc == V4L2_PIX_FMT_SBGGR16)
+	if (mt9m001->fmts == mt9m001_colour_fmts)
 		/*
 		 * Bayer format - even number of rows for simplicity,
 		 * but let the user play with the top row.
@@ -222,15 +231,17 @@
 	soc_camera_limit_side(&rect.top, &rect.height,
 		     MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
 
-	total_h = rect.height + icd->y_skip_top + vblank;
+	total_h = rect.height + mt9m001->y_skip_top + vblank;
 
 	/* Blanking and start values - default... */
 	ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
 	if (!ret)
 		ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
 
-	/* The caller provides a supported format, as verified per
-	 * call to icd->try_fmt() */
+	/*
+	 * The caller provides a supported format, as verified per
+	 * call to icd->try_fmt()
+	 */
 	if (!ret)
 		ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
 	if (!ret)
@@ -239,7 +250,7 @@
 		ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1);
 	if (!ret)
 		ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
-				rect.height + icd->y_skip_top - 1);
+				rect.height + mt9m001->y_skip_top - 1);
 	if (!ret && mt9m001->autoexposure) {
 		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, total_h);
 		if (!ret) {
@@ -283,32 +294,32 @@
 	return 0;
 }
 
-static int mt9m001_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m001_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->width		= mt9m001->rect.width;
-	pix->height		= mt9m001->rect.height;
-	pix->pixelformat	= mt9m001->fourcc;
-	pix->field		= V4L2_FIELD_NONE;
-	pix->colorspace		= V4L2_COLORSPACE_SRGB;
+	mf->width	= mt9m001->rect.width;
+	mf->height	= mt9m001->rect.height;
+	mf->code	= mt9m001->fmt->code;
+	mf->colorspace	= mt9m001->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m001_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9m001 *mt9m001 = to_mt9m001(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct v4l2_crop a = {
 		.c = {
 			.left	= mt9m001->rect.left,
 			.top	= mt9m001->rect.top,
-			.width	= pix->width,
-			.height	= pix->height,
+			.width	= mf->width,
+			.height	= mf->height,
 		},
 	};
 	int ret;
@@ -316,28 +327,39 @@
 	/* No support for scaling so far, just crop. TODO: use skipping */
 	ret = mt9m001_s_crop(sd, &a);
 	if (!ret) {
-		pix->width = mt9m001->rect.width;
-		pix->height = mt9m001->rect.height;
-		mt9m001->fourcc = pix->pixelformat;
+		mf->width	= mt9m001->rect.width;
+		mf->height	= mt9m001->rect.height;
+		mt9m001->fmt	= mt9m001_find_datafmt(mf->code,
+					mt9m001->fmts, mt9m001->num_fmts);
+		mf->colorspace	= mt9m001->fmt->colorspace;
 	}
 
 	return ret;
 }
 
-static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m001_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	const struct mt9m001_datafmt *fmt;
 
-	v4l_bound_align_image(&pix->width, MT9M001_MIN_WIDTH,
+	v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
 		MT9M001_MAX_WIDTH, 1,
-		&pix->height, MT9M001_MIN_HEIGHT + icd->y_skip_top,
-		MT9M001_MAX_HEIGHT + icd->y_skip_top, 0, 0);
+		&mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
+		MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0);
 
-	if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8 ||
-	    pix->pixelformat == V4L2_PIX_FMT_SBGGR16)
-		pix->height = ALIGN(pix->height - 1, 2);
+	if (mt9m001->fmts == mt9m001_colour_fmts)
+		mf->height = ALIGN(mf->height - 1, 2);
+
+	fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts,
+				   mt9m001->num_fmts);
+	if (!fmt) {
+		fmt = mt9m001->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->colorspace	= fmt->colorspace;
 
 	return 0;
 }
@@ -552,7 +574,7 @@
 		if (ctrl->value) {
 			const u16 vblank = 25;
 			unsigned int total_h = mt9m001->rect.height +
-				icd->y_skip_top + vblank;
+				mt9m001->y_skip_top + vblank;
 			if (reg_write(client, MT9M001_SHUTTER_WIDTH,
 				      total_h) < 0)
 				return -EIO;
@@ -568,8 +590,10 @@
 	return 0;
 }
 
-/* Interface active, can use i2c. If it fails, it can indeed mean, that
- * this wasn't our capture interface, so, we wait for the right one */
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
 static int mt9m001_video_probe(struct soc_camera_device *icd,
 			       struct i2c_client *client)
 {
@@ -579,8 +603,10 @@
 	unsigned long flags;
 	int ret;
 
-	/* We must have a parent by now. And it cannot be a wrong one.
-	 * So this entire test is completely redundant. */
+	/*
+	 * We must have a parent by now. And it cannot be a wrong one.
+	 * So this entire test is completely redundant.
+	 */
 	if (!icd->dev.parent ||
 	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
 		return -ENODEV;
@@ -597,11 +623,11 @@
 	case 0x8411:
 	case 0x8421:
 		mt9m001->model = V4L2_IDENT_MT9M001C12ST;
-		icd->formats = mt9m001_colour_formats;
+		mt9m001->fmts = mt9m001_colour_fmts;
 		break;
 	case 0x8431:
 		mt9m001->model = V4L2_IDENT_MT9M001C12STM;
-		icd->formats = mt9m001_monochrome_formats;
+		mt9m001->fmts = mt9m001_monochrome_fmts;
 		break;
 	default:
 		dev_err(&client->dev,
@@ -609,7 +635,7 @@
 		return -ENODEV;
 	}
 
-	icd->num_formats = 0;
+	mt9m001->num_fmts = 0;
 
 	/*
 	 * This is a 10bit sensor, so by default we only allow 10bit.
@@ -622,14 +648,14 @@
 		flags = SOCAM_DATAWIDTH_10;
 
 	if (flags & SOCAM_DATAWIDTH_10)
-		icd->num_formats++;
+		mt9m001->num_fmts++;
 	else
-		icd->formats++;
+		mt9m001->fmts++;
 
 	if (flags & SOCAM_DATAWIDTH_8)
-		icd->num_formats++;
+		mt9m001->num_fmts++;
 
-	mt9m001->fourcc = icd->formats->fourcc;
+	mt9m001->fmt = &mt9m001->fmts[0];
 
 	dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
 		 data == 0x8431 ? "C12STM" : "C12ST");
@@ -655,6 +681,16 @@
 		icl->free_bus(icl);
 }
 
+static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	*lines = mt9m001->y_skip_top;
+
+	return 0;
+}
+
 static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
 	.g_ctrl		= mt9m001_g_ctrl,
 	.s_ctrl		= mt9m001_s_ctrl,
@@ -665,19 +701,38 @@
 #endif
 };
 
+static int mt9m001_enum_fmt(struct v4l2_subdev *sd, int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	if ((unsigned int)index >= mt9m001->num_fmts)
+		return -EINVAL;
+
+	*code = mt9m001->fmts[index].code;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
 	.s_stream	= mt9m001_s_stream,
-	.s_fmt		= mt9m001_s_fmt,
-	.g_fmt		= mt9m001_g_fmt,
-	.try_fmt	= mt9m001_try_fmt,
+	.s_mbus_fmt	= mt9m001_s_fmt,
+	.g_mbus_fmt	= mt9m001_g_fmt,
+	.try_mbus_fmt	= mt9m001_try_fmt,
 	.s_crop		= mt9m001_s_crop,
 	.g_crop		= mt9m001_g_crop,
 	.cropcap	= mt9m001_cropcap,
+	.enum_mbus_fmt	= mt9m001_enum_fmt,
+};
+
+static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9m001_g_skip_top_lines,
 };
 
 static struct v4l2_subdev_ops mt9m001_subdev_ops = {
 	.core	= &mt9m001_subdev_core_ops,
 	.video	= &mt9m001_subdev_video_ops,
+	.sensor	= &mt9m001_subdev_sensor_ops,
 };
 
 static int mt9m001_probe(struct i2c_client *client,
@@ -714,15 +769,17 @@
 
 	/* Second stage probe - when a capture adapter is there */
 	icd->ops		= &mt9m001_ops;
-	icd->y_skip_top		= 0;
 
+	mt9m001->y_skip_top	= 0;
 	mt9m001->rect.left	= MT9M001_COLUMN_SKIP;
 	mt9m001->rect.top	= MT9M001_ROW_SKIP;
 	mt9m001->rect.width	= MT9M001_MAX_WIDTH;
 	mt9m001->rect.height	= MT9M001_MAX_HEIGHT;
 
-	/* Simulated autoexposure. If enabled, we calculate shutter width
-	 * ourselves in the driver based on vertical blanking and frame width */
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
 	mt9m001->autoexposure = 1;
 
 	ret = mt9m001_video_probe(icd, client);
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index 90da699..d35f536 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -123,23 +123,34 @@
 #define MT9M111_MAX_HEIGHT	1024
 #define MT9M111_MAX_WIDTH	1280
 
-#define COL_FMT(_name, _depth, _fourcc, _colorspace) \
-	{ .name = _name, .depth = _depth, .fourcc = _fourcc, \
-	.colorspace = _colorspace }
-#define RGB_FMT(_name, _depth, _fourcc) \
-	COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_SRGB)
-#define JPG_FMT(_name, _depth, _fourcc) \
-	COL_FMT(_name, _depth, _fourcc, V4L2_COLORSPACE_JPEG)
+/* MT9M111 has only one fixed colorspace per pixelcode */
+struct mt9m111_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
 
-static const struct soc_camera_data_format mt9m111_colour_formats[] = {
-	JPG_FMT("CbYCrY 16 bit", 16, V4L2_PIX_FMT_UYVY),
-	JPG_FMT("CrYCbY 16 bit", 16, V4L2_PIX_FMT_VYUY),
-	JPG_FMT("YCbYCr 16 bit", 16, V4L2_PIX_FMT_YUYV),
-	JPG_FMT("YCrYCb 16 bit", 16, V4L2_PIX_FMT_YVYU),
-	RGB_FMT("RGB 565", 16, V4L2_PIX_FMT_RGB565),
-	RGB_FMT("RGB 555", 16, V4L2_PIX_FMT_RGB555),
-	RGB_FMT("Bayer (sRGB) 10 bit", 10, V4L2_PIX_FMT_SBGGR16),
-	RGB_FMT("Bayer (sRGB) 8 bit", 8, V4L2_PIX_FMT_SBGGR8),
+/* Find a data format by a pixel code in an array */
+static const struct mt9m111_datafmt *mt9m111_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
+	{V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YUYV8_2X8_BE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8_BE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
 };
 
 enum mt9m111_context {
@@ -152,7 +163,7 @@
 	int model;	/* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
 	enum mt9m111_context context;
 	struct v4l2_rect rect;
-	u32 pixfmt;
+	const struct mt9m111_datafmt *fmt;
 	unsigned int gain;
 	unsigned char autoexposure;
 	unsigned char datawidth;
@@ -258,8 +269,8 @@
 	int width = rect->width;
 	int height = rect->height;
 
-	if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 ||
-	    mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16)
+	if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+	    mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE)
 		is_raw_format = 1;
 	else
 		is_raw_format = 0;
@@ -307,7 +318,8 @@
 
 static int mt9m111_setfmt_bayer8(struct i2c_client *client)
 {
-	return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER);
+	return mt9m111_setup_pixfmt(client, MT9M111_OUTFMT_PROCESSED_BAYER |
+				    MT9M111_OUTFMT_RGB);
 }
 
 static int mt9m111_setfmt_bayer10(struct i2c_client *client)
@@ -401,8 +413,8 @@
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
 
-	if (mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR8 ||
-	    mt9m111->pixfmt == V4L2_PIX_FMT_SBGGR16) {
+	if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+	    mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
 		/* Bayer format - even size lengths */
 		rect->width	= ALIGN(rect->width, 2);
 		rect->height	= ALIGN(rect->height, 2);
@@ -460,120 +472,139 @@
 	return 0;
 }
 
-static int mt9m111_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m111_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->width		= mt9m111->rect.width;
-	pix->height		= mt9m111->rect.height;
-	pix->pixelformat	= mt9m111->pixfmt;
-	pix->field		= V4L2_FIELD_NONE;
-	pix->colorspace		= V4L2_COLORSPACE_SRGB;
+	mf->width	= mt9m111->rect.width;
+	mf->height	= mt9m111->rect.height;
+	mf->code	= mt9m111->fmt->code;
+	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int mt9m111_set_pixfmt(struct i2c_client *client, u32 pixfmt)
+static int mt9m111_set_pixfmt(struct i2c_client *client,
+			      enum v4l2_mbus_pixelcode code)
 {
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
 	int ret;
 
-	switch (pixfmt) {
-	case V4L2_PIX_FMT_SBGGR8:
+	switch (code) {
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
 		ret = mt9m111_setfmt_bayer8(client);
 		break;
-	case V4L2_PIX_FMT_SBGGR16:
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
 		ret = mt9m111_setfmt_bayer10(client);
 		break;
-	case V4L2_PIX_FMT_RGB555:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 		ret = mt9m111_setfmt_rgb555(client);
 		break;
-	case V4L2_PIX_FMT_RGB565:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		ret = mt9m111_setfmt_rgb565(client);
 		break;
-	case V4L2_PIX_FMT_UYVY:
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
 		mt9m111->swap_yuv_y_chromas = 0;
 		mt9m111->swap_yuv_cb_cr = 0;
 		ret = mt9m111_setfmt_yuv(client);
 		break;
-	case V4L2_PIX_FMT_VYUY:
+	case V4L2_MBUS_FMT_YVYU8_2X8_BE:
 		mt9m111->swap_yuv_y_chromas = 0;
 		mt9m111->swap_yuv_cb_cr = 1;
 		ret = mt9m111_setfmt_yuv(client);
 		break;
-	case V4L2_PIX_FMT_YUYV:
+	case V4L2_MBUS_FMT_YUYV8_2X8_LE:
 		mt9m111->swap_yuv_y_chromas = 1;
 		mt9m111->swap_yuv_cb_cr = 0;
 		ret = mt9m111_setfmt_yuv(client);
 		break;
-	case V4L2_PIX_FMT_YVYU:
+	case V4L2_MBUS_FMT_YVYU8_2X8_LE:
 		mt9m111->swap_yuv_y_chromas = 1;
 		mt9m111->swap_yuv_cb_cr = 1;
 		ret = mt9m111_setfmt_yuv(client);
 		break;
 	default:
 		dev_err(&client->dev, "Pixel format not handled : %x\n",
-			pixfmt);
+			code);
 		ret = -EINVAL;
 	}
 
-	if (!ret)
-		mt9m111->pixfmt = pixfmt;
-
 	return ret;
 }
 
-static int mt9m111_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m111_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
+	const struct mt9m111_datafmt *fmt;
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct v4l2_rect rect = {
 		.left	= mt9m111->rect.left,
 		.top	= mt9m111->rect.top,
-		.width	= pix->width,
-		.height	= pix->height,
+		.width	= mf->width,
+		.height	= mf->height,
 	};
 	int ret;
 
+	fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
+				   ARRAY_SIZE(mt9m111_colour_fmts));
+	if (!fmt)
+		return -EINVAL;
+
 	dev_dbg(&client->dev,
-		"%s fmt=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
-		pix->pixelformat, rect.left, rect.top, rect.width, rect.height);
+		"%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__,
+		mf->code, rect.left, rect.top, rect.width, rect.height);
 
 	ret = mt9m111_make_rect(client, &rect);
 	if (!ret)
-		ret = mt9m111_set_pixfmt(client, pix->pixelformat);
-	if (!ret)
-		mt9m111->rect = rect;
+		ret = mt9m111_set_pixfmt(client, mf->code);
+	if (!ret) {
+		mt9m111->rect	= rect;
+		mt9m111->fmt	= fmt;
+		mf->colorspace	= fmt->colorspace;
+	}
+
 	return ret;
 }
 
-static int mt9m111_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9m111_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
 {
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	bool bayer = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 ||
-		pix->pixelformat == V4L2_PIX_FMT_SBGGR16;
+	struct i2c_client *client = sd->priv;
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
+	const struct mt9m111_datafmt *fmt;
+	bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
+
+	fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts,
+				   ARRAY_SIZE(mt9m111_colour_fmts));
+	if (!fmt) {
+		fmt = mt9m111->fmt;
+		mf->code = fmt->code;
+	}
 
 	/*
 	 * With Bayer format enforce even side lengths, but let the user play
 	 * with the starting pixel
 	 */
 
-	if (pix->height > MT9M111_MAX_HEIGHT)
-		pix->height = MT9M111_MAX_HEIGHT;
-	else if (pix->height < 2)
-		pix->height = 2;
+	if (mf->height > MT9M111_MAX_HEIGHT)
+		mf->height = MT9M111_MAX_HEIGHT;
+	else if (mf->height < 2)
+		mf->height = 2;
 	else if (bayer)
-		pix->height = ALIGN(pix->height, 2);
+		mf->height = ALIGN(mf->height, 2);
 
-	if (pix->width > MT9M111_MAX_WIDTH)
-		pix->width = MT9M111_MAX_WIDTH;
-	else if (pix->width < 2)
-		pix->width = 2;
+	if (mf->width > MT9M111_MAX_WIDTH)
+		mf->width = MT9M111_MAX_WIDTH;
+	else if (mf->width < 2)
+		mf->width = 2;
 	else if (bayer)
-		pix->width = ALIGN(pix->width, 2);
+		mf->width = ALIGN(mf->width, 2);
+
+	mf->colorspace = fmt->colorspace;
 
 	return 0;
 }
@@ -863,7 +894,7 @@
 	struct mt9m111 *mt9m111 = to_mt9m111(client);
 
 	mt9m111_set_context(client, mt9m111->context);
-	mt9m111_set_pixfmt(client, mt9m111->pixfmt);
+	mt9m111_set_pixfmt(client, mt9m111->fmt->code);
 	mt9m111_setup_rect(client, &mt9m111->rect);
 	mt9m111_set_flip(client, mt9m111->hflip, MT9M111_RMB_MIRROR_COLS);
 	mt9m111_set_flip(client, mt9m111->vflip, MT9M111_RMB_MIRROR_ROWS);
@@ -952,9 +983,6 @@
 		goto ei2c;
 	}
 
-	icd->formats = mt9m111_colour_formats;
-	icd->num_formats = ARRAY_SIZE(mt9m111_colour_formats);
-
 	dev_info(&client->dev, "Detected a MT9M11x chip ID %x\n", data);
 
 ei2c:
@@ -971,13 +999,24 @@
 #endif
 };
 
+static int mt9m111_enum_fmt(struct v4l2_subdev *sd, int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(mt9m111_colour_fmts))
+		return -EINVAL;
+
+	*code = mt9m111_colour_fmts[index].code;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
-	.s_fmt		= mt9m111_s_fmt,
-	.g_fmt		= mt9m111_g_fmt,
-	.try_fmt	= mt9m111_try_fmt,
+	.s_mbus_fmt	= mt9m111_s_fmt,
+	.g_mbus_fmt	= mt9m111_g_fmt,
+	.try_mbus_fmt	= mt9m111_try_fmt,
 	.s_crop		= mt9m111_s_crop,
 	.g_crop		= mt9m111_g_crop,
 	.cropcap	= mt9m111_cropcap,
+	.enum_mbus_fmt	= mt9m111_enum_fmt,
 };
 
 static struct v4l2_subdev_ops mt9m111_subdev_ops = {
@@ -1019,12 +1058,12 @@
 
 	/* Second stage probe - when a capture adapter is there */
 	icd->ops		= &mt9m111_ops;
-	icd->y_skip_top		= 0;
 
 	mt9m111->rect.left	= MT9M111_MIN_DARK_COLS;
 	mt9m111->rect.top	= MT9M111_MIN_DARK_ROWS;
 	mt9m111->rect.width	= MT9M111_MAX_WIDTH;
 	mt9m111->rect.height	= MT9M111_MAX_HEIGHT;
+	mt9m111->fmt		= &mt9m111_colour_fmts[0];
 
 	ret = mt9m111_video_probe(icd, client);
 	if (ret) {
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 6966f64..a9061bf 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -17,9 +17,11 @@
 #include <media/v4l2-chip-ident.h>
 #include <media/soc_camera.h>
 
-/* mt9t031 i2c address 0x5d
+/*
+ * mt9t031 i2c address 0x5d
  * The platform has to define i2c_board_info and link to it from
- * struct soc_camera_link */
+ * struct soc_camera_link
+ */
 
 /* mt9t031 selected register addresses */
 #define MT9T031_CHIP_VERSION		0x00
@@ -58,15 +60,6 @@
 	SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |	\
 	SOCAM_MASTER | SOCAM_DATAWIDTH_10)
 
-static const struct soc_camera_data_format mt9t031_colour_formats[] = {
-	{
-		.name		= "Bayer (sRGB) 10 bit",
-		.depth		= 10,
-		.fourcc		= V4L2_PIX_FMT_SGRBG10,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}
-};
-
 struct mt9t031 {
 	struct v4l2_subdev subdev;
 	struct v4l2_rect rect;	/* Sensor window */
@@ -74,6 +67,7 @@
 	u16 xskip;
 	u16 yskip;
 	unsigned int gain;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
 	unsigned int exposure;
 	unsigned char autoexposure;
 };
@@ -207,6 +201,71 @@
 	return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
 }
 
+enum {
+	MT9T031_CTRL_VFLIP,
+	MT9T031_CTRL_HFLIP,
+	MT9T031_CTRL_GAIN,
+	MT9T031_CTRL_EXPOSURE,
+	MT9T031_CTRL_EXPOSURE_AUTO,
+};
+
+static const struct v4l2_queryctrl mt9t031_controls[] = {
+	[MT9T031_CTRL_VFLIP] = {
+		.id		= V4L2_CID_VFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Vertically",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+	[MT9T031_CTRL_HFLIP] = {
+		.id		= V4L2_CID_HFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Horizontally",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+	[MT9T031_CTRL_GAIN] = {
+		.id		= V4L2_CID_GAIN,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain",
+		.minimum	= 0,
+		.maximum	= 127,
+		.step		= 1,
+		.default_value	= 64,
+		.flags		= V4L2_CTRL_FLAG_SLIDER,
+	},
+	[MT9T031_CTRL_EXPOSURE] = {
+		.id		= V4L2_CID_EXPOSURE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Exposure",
+		.minimum	= 1,
+		.maximum	= 255,
+		.step		= 1,
+		.default_value	= 255,
+		.flags		= V4L2_CTRL_FLAG_SLIDER,
+	},
+	[MT9T031_CTRL_EXPOSURE_AUTO] = {
+		.id		= V4L2_CID_EXPOSURE_AUTO,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Automatic Exposure",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 1,
+	}
+};
+
+static struct soc_camera_ops mt9t031_ops = {
+	.set_bus_param		= mt9t031_set_bus_param,
+	.query_bus_param	= mt9t031_query_bus_param,
+	.controls		= mt9t031_controls,
+	.num_controls		= ARRAY_SIZE(mt9t031_controls),
+};
+
 /* target must be _even_ */
 static u16 mt9t031_skip(s32 *source, s32 target, s32 max)
 {
@@ -226,10 +285,9 @@
 }
 
 /* rect is the sensor rectangle, the caller guarantees parameter validity */
-static int mt9t031_set_params(struct soc_camera_device *icd,
+static int mt9t031_set_params(struct i2c_client *client,
 			      struct v4l2_rect *rect, u16 xskip, u16 yskip)
 {
-	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
 	int ret;
 	u16 xbin, ybin;
@@ -291,8 +349,10 @@
 	dev_dbg(&client->dev, "new physical left %u, top %u\n",
 		rect->left, rect->top);
 
-	/* The caller provides a supported format, as guaranteed by
-	 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
+	/*
+	 * The caller provides a supported format, as guaranteed by
+	 * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap()
+	 */
 	if (ret >= 0)
 		ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
 	if (ret >= 0)
@@ -301,15 +361,14 @@
 		ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1);
 	if (ret >= 0)
 		ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
-				rect->height + icd->y_skip_top - 1);
+				rect->height + mt9t031->y_skip_top - 1);
 	if (ret >= 0 && mt9t031->autoexposure) {
-		unsigned int total_h = rect->height + icd->y_skip_top + vblank;
+		unsigned int total_h = rect->height + mt9t031->y_skip_top + vblank;
 		ret = set_shutter(client, total_h);
 		if (ret >= 0) {
 			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
 			const struct v4l2_queryctrl *qctrl =
-				soc_camera_find_qctrl(icd->ops,
-						      V4L2_CID_EXPOSURE);
+				&mt9t031_controls[MT9T031_CTRL_EXPOSURE];
 			mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
 				 (qctrl->maximum - qctrl->minimum)) /
 				shutter_max + qctrl->minimum;
@@ -334,7 +393,6 @@
 	struct v4l2_rect rect = a->c;
 	struct i2c_client *client = sd->priv;
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 
 	rect.width = ALIGN(rect.width, 2);
 	rect.height = ALIGN(rect.height, 2);
@@ -345,7 +403,7 @@
 	soc_camera_limit_side(&rect.top, &rect.height,
 		     MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT);
 
-	return mt9t031_set_params(icd, &rect, mt9t031->xskip, mt9t031->yskip);
+	return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip);
 }
 
 static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
@@ -373,27 +431,26 @@
 	return 0;
 }
 
-static int mt9t031_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9t031_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->width		= mt9t031->rect.width / mt9t031->xskip;
-	pix->height		= mt9t031->rect.height / mt9t031->yskip;
-	pix->pixelformat	= V4L2_PIX_FMT_SGRBG10;
-	pix->field		= V4L2_FIELD_NONE;
-	pix->colorspace		= V4L2_COLORSPACE_SRGB;
+	mf->width	= mt9t031->rect.width / mt9t031->xskip;
+	mf->height	= mt9t031->rect.height / mt9t031->yskip;
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
+	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int mt9t031_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9t031_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	u16 xskip, yskip;
 	struct v4l2_rect rect = mt9t031->rect;
 
@@ -401,24 +458,29 @@
 	 * try_fmt has put width and height within limits.
 	 * S_FMT: use binning and skipping for scaling
 	 */
-	xskip = mt9t031_skip(&rect.width, pix->width, MT9T031_MAX_WIDTH);
-	yskip = mt9t031_skip(&rect.height, pix->height, MT9T031_MAX_HEIGHT);
+	xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
+	yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT);
+
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
 
 	/* mt9t031_set_params() doesn't change width and height */
-	return mt9t031_set_params(icd, &rect, xskip, yskip);
+	return mt9t031_set_params(client, &rect, xskip, yskip);
 }
 
 /*
  * If a user window larger than sensor window is requested, we'll increase the
  * sensor window.
  */
-static int mt9t031_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9t031_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
 {
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
 	v4l_bound_align_image(
-		&pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
-		&pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
+		&mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+		&mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
+
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
 
 	return 0;
 }
@@ -479,59 +541,6 @@
 }
 #endif
 
-static const struct v4l2_queryctrl mt9t031_controls[] = {
-	{
-		.id		= V4L2_CID_VFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Vertically",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_HFLIP,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Flip Horizontally",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 0,
-	}, {
-		.id		= V4L2_CID_GAIN,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Gain",
-		.minimum	= 0,
-		.maximum	= 127,
-		.step		= 1,
-		.default_value	= 64,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE,
-		.type		= V4L2_CTRL_TYPE_INTEGER,
-		.name		= "Exposure",
-		.minimum	= 1,
-		.maximum	= 255,
-		.step		= 1,
-		.default_value	= 255,
-		.flags		= V4L2_CTRL_FLAG_SLIDER,
-	}, {
-		.id		= V4L2_CID_EXPOSURE_AUTO,
-		.type		= V4L2_CTRL_TYPE_BOOLEAN,
-		.name		= "Automatic Exposure",
-		.minimum	= 0,
-		.maximum	= 1,
-		.step		= 1,
-		.default_value	= 1,
-	}
-};
-
-static struct soc_camera_ops mt9t031_ops = {
-	.set_bus_param		= mt9t031_set_bus_param,
-	.query_bus_param	= mt9t031_query_bus_param,
-	.controls		= mt9t031_controls,
-	.num_controls		= ARRAY_SIZE(mt9t031_controls),
-};
-
 static int mt9t031_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	struct i2c_client *client = sd->priv;
@@ -568,15 +577,9 @@
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
-	struct soc_camera_device *icd = client->dev.platform_data;
 	const struct v4l2_queryctrl *qctrl;
 	int data;
 
-	qctrl = soc_camera_find_qctrl(&mt9t031_ops, ctrl->id);
-
-	if (!qctrl)
-		return -EINVAL;
-
 	switch (ctrl->id) {
 	case V4L2_CID_VFLIP:
 		if (ctrl->value)
@@ -595,6 +598,7 @@
 			return -EIO;
 		break;
 	case V4L2_CID_GAIN:
+		qctrl = &mt9t031_controls[MT9T031_CTRL_GAIN];
 		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
 			return -EINVAL;
 		/* See Datasheet Table 7, Gain settings. */
@@ -634,6 +638,7 @@
 		mt9t031->gain = ctrl->value;
 		break;
 	case V4L2_CID_EXPOSURE:
+		qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
 		/* mt9t031 has maximum == default */
 		if (ctrl->value > qctrl->maximum || ctrl->value < qctrl->minimum)
 			return -EINVAL;
@@ -657,11 +662,11 @@
 			const u16 vblank = MT9T031_VERTICAL_BLANK;
 			const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
 			unsigned int total_h = mt9t031->rect.height +
-				icd->y_skip_top + vblank;
+				mt9t031->y_skip_top + vblank;
 
 			if (set_shutter(client, total_h) < 0)
 				return -EIO;
-			qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+			qctrl = &mt9t031_controls[MT9T031_CTRL_EXPOSURE];
 			mt9t031->exposure = (shutter_max / 2 + (total_h - 1) *
 				 (qctrl->maximum - qctrl->minimum)) /
 				shutter_max + qctrl->minimum;
@@ -669,15 +674,18 @@
 		} else
 			mt9t031->autoexposure = 0;
 		break;
+	default:
+		return -EINVAL;
 	}
 	return 0;
 }
 
-/* Interface active, can use i2c. If it fails, it can indeed mean, that
- * this wasn't our capture interface, so, we wait for the right one */
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
 static int mt9t031_video_probe(struct i2c_client *client)
 {
-	struct soc_camera_device *icd = client->dev.platform_data;
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
 	s32 data;
 	int ret;
@@ -692,8 +700,6 @@
 	switch (data) {
 	case 0x1621:
 		mt9t031->model = V4L2_IDENT_MT9T031;
-		icd->formats = mt9t031_colour_formats;
-		icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
 		break;
 	default:
 		dev_err(&client->dev,
@@ -714,6 +720,16 @@
 	return ret;
 }
 
+static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	*lines = mt9t031->y_skip_top;
+
+	return 0;
+}
+
 static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
 	.g_ctrl		= mt9t031_g_ctrl,
 	.s_ctrl		= mt9t031_s_ctrl,
@@ -724,19 +740,35 @@
 #endif
 };
 
+static int mt9t031_enum_fmt(struct v4l2_subdev *sd, int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_SBGGR10_1X10;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
 	.s_stream	= mt9t031_s_stream,
-	.s_fmt		= mt9t031_s_fmt,
-	.g_fmt		= mt9t031_g_fmt,
-	.try_fmt	= mt9t031_try_fmt,
+	.s_mbus_fmt	= mt9t031_s_fmt,
+	.g_mbus_fmt	= mt9t031_g_fmt,
+	.try_mbus_fmt	= mt9t031_try_fmt,
 	.s_crop		= mt9t031_s_crop,
 	.g_crop		= mt9t031_g_crop,
 	.cropcap	= mt9t031_cropcap,
+	.enum_mbus_fmt	= mt9t031_enum_fmt,
+};
+
+static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9t031_g_skip_top_lines,
 };
 
 static struct v4l2_subdev_ops mt9t031_subdev_ops = {
 	.core	= &mt9t031_subdev_core_ops,
 	.video	= &mt9t031_subdev_video_ops,
+	.sensor	= &mt9t031_subdev_sensor_ops,
 };
 
 static int mt9t031_probe(struct i2c_client *client,
@@ -745,18 +777,16 @@
 	struct mt9t031 *mt9t031;
 	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-	struct soc_camera_link *icl;
 	int ret;
 
-	if (!icd) {
-		dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
-		return -EINVAL;
-	}
+	if (icd) {
+		struct soc_camera_link *icl = to_soc_camera_link(icd);
+		if (!icl) {
+			dev_err(&client->dev, "MT9T031 driver needs platform data\n");
+			return -EINVAL;
+		}
 
-	icl = to_soc_camera_link(icd);
-	if (!icl) {
-		dev_err(&client->dev, "MT9T031 driver needs platform data\n");
-		return -EINVAL;
+		icd->ops = &mt9t031_ops;
 	}
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -771,17 +801,16 @@
 
 	v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops);
 
-	/* Second stage probe - when a capture adapter is there */
-	icd->ops		= &mt9t031_ops;
-	icd->y_skip_top		= 0;
-
+	mt9t031->y_skip_top	= 0;
 	mt9t031->rect.left	= MT9T031_COLUMN_SKIP;
 	mt9t031->rect.top	= MT9T031_ROW_SKIP;
 	mt9t031->rect.width	= MT9T031_MAX_WIDTH;
 	mt9t031->rect.height	= MT9T031_MAX_HEIGHT;
 
-	/* Simulated autoexposure. If enabled, we calculate shutter width
-	 * ourselves in the driver based on vertical blanking and frame width */
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
 	mt9t031->autoexposure = 1;
 
 	mt9t031->xskip = 1;
@@ -794,7 +823,8 @@
 	mt9t031_disable(client);
 
 	if (ret) {
-		icd->ops = NULL;
+		if (icd)
+			icd->ops = NULL;
 		i2c_set_clientdata(client, NULL);
 		kfree(mt9t031);
 	}
@@ -807,7 +837,8 @@
 	struct mt9t031 *mt9t031 = to_mt9t031(client);
 	struct soc_camera_device *icd = client->dev.platform_data;
 
-	icd->ops = NULL;
+	if (icd)
+		icd->ops = NULL;
 	i2c_set_clientdata(client, NULL);
 	client->driver = NULL;
 	kfree(mt9t031);
diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c
new file mode 100644
index 0000000..fc4dd60
--- /dev/null
+++ b/drivers/media/video/mt9t112.c
@@ -0,0 +1,1177 @@
+/*
+ * mt9t112 Camera Driver
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov772x driver, mt9m111 driver,
+ *
+ * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9t112.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+
+/* you can check PLL/clock info */
+/* #define EXT_CLOCK 24000000 */
+
+/************************************************************************
+
+
+			macro
+
+
+************************************************************************/
+/*
+ * frame size
+ */
+#define MAX_WIDTH   2048
+#define MAX_HEIGHT  1536
+
+#define VGA_WIDTH   640
+#define VGA_HEIGHT  480
+
+/*
+ * macro of read/write
+ */
+#define ECHECKER(ret, x)		\
+	do {				\
+		(ret) = (x);		\
+		if ((ret) < 0)		\
+			return (ret);	\
+	} while (0)
+
+#define mt9t112_reg_write(ret, client, a, b) \
+	ECHECKER(ret, __mt9t112_reg_write(client, a, b))
+#define mt9t112_mcu_write(ret, client, a, b) \
+	ECHECKER(ret, __mt9t112_mcu_write(client, a, b))
+
+#define mt9t112_reg_mask_set(ret, client, a, b, c) \
+	ECHECKER(ret, __mt9t112_reg_mask_set(client, a, b, c))
+#define mt9t112_mcu_mask_set(ret, client, a, b, c) \
+	ECHECKER(ret, __mt9t112_mcu_mask_set(client, a, b, c))
+
+#define mt9t112_reg_read(ret, client, a) \
+	ECHECKER(ret, __mt9t112_reg_read(client, a))
+
+/*
+ * Logical address
+ */
+#define _VAR(id, offset, base)	(base | (id & 0x1f) << 10 | (offset & 0x3ff))
+#define VAR(id, offset)  _VAR(id, offset, 0x0000)
+#define VAR8(id, offset) _VAR(id, offset, 0x8000)
+
+/************************************************************************
+
+
+			struct
+
+
+************************************************************************/
+struct mt9t112_frame_size {
+	u16 width;
+	u16 height;
+};
+
+struct mt9t112_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u16 fmt;
+	u16 order;
+};
+
+struct mt9t112_priv {
+	struct v4l2_subdev		 subdev;
+	struct mt9t112_camera_info	*info;
+	struct i2c_client		*client;
+	struct soc_camera_device	 icd;
+	struct mt9t112_frame_size	 frame;
+	const struct mt9t112_format	*format;
+	int				 model;
+	u32				 flags;
+/* for flags */
+#define INIT_DONE  (1<<0)
+};
+
+/************************************************************************
+
+
+			supported format
+
+
+************************************************************************/
+
+static const struct mt9t112_format mt9t112_cfmts[] = {
+	{
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 0,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 1,
+	}, {
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 2,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 3,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.fmt		= 8,
+		.order		= 2,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.fmt		= 4,
+		.order		= 2,
+	},
+};
+
+/************************************************************************
+
+
+			general function
+
+
+************************************************************************/
+static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client),
+			    struct mt9t112_priv,
+			    subdev);
+}
+
+static int __mt9t112_reg_read(const struct i2c_client *client, u16 command)
+{
+	struct i2c_msg msg[2];
+	u8 buf[2];
+	int ret;
+
+	command = swab16(command);
+
+	msg[0].addr  = client->addr;
+	msg[0].flags = 0;
+	msg[0].len   = 2;
+	msg[0].buf   = (u8 *)&command;
+
+	msg[1].addr  = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len   = 2;
+	msg[1].buf   = buf;
+
+	/*
+	 * if return value of this function is < 0,
+	 * it mean error.
+	 * else, under 16bit is valid data.
+	 */
+	ret = i2c_transfer(client->adapter, msg, 2);
+	if (ret < 0)
+		return ret;
+
+	memcpy(&ret, buf, 2);
+	return swab16(ret);
+}
+
+static int __mt9t112_reg_write(const struct i2c_client *client,
+			       u16 command, u16 data)
+{
+	struct i2c_msg msg;
+	u8 buf[4];
+	int ret;
+
+	command = swab16(command);
+	data = swab16(data);
+
+	memcpy(buf + 0, &command, 2);
+	memcpy(buf + 2, &data,    2);
+
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 4;
+	msg.buf   = buf;
+
+	/*
+	 * i2c_transfer return message length,
+	 * but this function should return 0 if correct case
+	 */
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret >= 0)
+		ret = 0;
+
+	return ret;
+}
+
+static int __mt9t112_reg_mask_set(const struct i2c_client *client,
+				  u16  command,
+				  u16  mask,
+				  u16  set)
+{
+	int val = __mt9t112_reg_read(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return __mt9t112_reg_write(client, command, val);
+}
+
+/* mcu access */
+static int __mt9t112_mcu_read(const struct i2c_client *client, u16 command)
+{
+	int ret;
+
+	ret = __mt9t112_reg_write(client, 0x098E, command);
+	if (ret < 0)
+		return ret;
+
+	return __mt9t112_reg_read(client, 0x0990);
+}
+
+static int __mt9t112_mcu_write(const struct i2c_client *client,
+			       u16 command, u16 data)
+{
+	int ret;
+
+	ret = __mt9t112_reg_write(client, 0x098E, command);
+	if (ret < 0)
+		return ret;
+
+	return __mt9t112_reg_write(client, 0x0990, data);
+}
+
+static int __mt9t112_mcu_mask_set(const struct i2c_client *client,
+				  u16  command,
+				  u16  mask,
+				  u16  set)
+{
+	int val = __mt9t112_mcu_read(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return __mt9t112_mcu_write(client, command, val);
+}
+
+static int mt9t112_reset(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0001);
+	msleep(1);
+	mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0000);
+
+	return ret;
+}
+
+#ifndef EXT_CLOCK
+#define CLOCK_INFO(a, b)
+#else
+#define CLOCK_INFO(a, b) mt9t112_clock_info(a, b)
+static int mt9t112_clock_info(const struct i2c_client *client, u32 ext)
+{
+	int m, n, p1, p2, p3, p4, p5, p6, p7;
+	u32 vco, clk;
+	char *enable;
+
+	ext /= 1000; /* kbyte order */
+
+	mt9t112_reg_read(n, client, 0x0012);
+	p1 = n & 0x000f;
+	n = n >> 4;
+	p2 = n & 0x000f;
+	n = n >> 4;
+	p3 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x002a);
+	p4 = n & 0x000f;
+	n = n >> 4;
+	p5 = n & 0x000f;
+	n = n >> 4;
+	p6 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x002c);
+	p7 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x0010);
+	m = n & 0x00ff;
+	n = (n >> 8) & 0x003f;
+
+	enable = ((6000 > ext) || (54000 < ext)) ? "X" : "";
+	dev_info(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
+
+	vco = 2 * m * ext / (n+1);
+	enable = ((384000 > vco) || (768000 < vco)) ? "X" : "";
+	dev_info(&client->dev, "VCO             : %10u K %s\n", vco, enable);
+
+	clk = vco / (p1+1) / (p2+1);
+	enable = (96000 < clk) ? "X" : "";
+	dev_info(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
+
+	clk = vco / (p3+1);
+	enable = (768000 < clk) ? "X" : "";
+	dev_info(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p6+1);
+	enable = (96000 < clk) ? "X" : "";
+	dev_info(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p5+1);
+	enable = (54000 < clk) ? "X" : "";
+	dev_info(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p4+1);
+	enable = (70000 < clk) ? "X" : "";
+	dev_info(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
+
+	clk = vco / (p7+1);
+	dev_info(&client->dev, "External sensor : %10u K\n", clk);
+
+	clk = ext / (n+1);
+	enable = ((2000 > clk) || (24000 < clk)) ? "X" : "";
+	dev_info(&client->dev, "PFD             : %10u K %s\n", clk, enable);
+
+	return 0;
+}
+#endif
+
+static void mt9t112_frame_check(u32 *width, u32 *height)
+{
+	if (*width > MAX_WIDTH)
+		*width = MAX_WIDTH;
+
+	if (*height > MAX_HEIGHT)
+		*height = MAX_HEIGHT;
+}
+
+static int mt9t112_set_a_frame_size(const struct i2c_client *client,
+				   u16 width,
+				   u16 height)
+{
+	int ret;
+	u16 wstart = (MAX_WIDTH - width) / 2;
+	u16 hstart = (MAX_HEIGHT - height) / 2;
+
+	/* (Context A) Image Width/Height */
+	mt9t112_mcu_write(ret, client, VAR(26, 0), width);
+	mt9t112_mcu_write(ret, client, VAR(26, 2), height);
+
+	/* (Context A) Output Width/Height */
+	mt9t112_mcu_write(ret, client, VAR(18, 43), 8 + width);
+	mt9t112_mcu_write(ret, client, VAR(18, 45), 8 + height);
+
+	/* (Context A) Start Row/Column */
+	mt9t112_mcu_write(ret, client, VAR(18, 2), 4 + hstart);
+	mt9t112_mcu_write(ret, client, VAR(18, 4), 4 + wstart);
+
+	/* (Context A) End Row/Column */
+	mt9t112_mcu_write(ret, client, VAR(18, 6), 11 + height + hstart);
+	mt9t112_mcu_write(ret, client, VAR(18, 8), 11 + width  + wstart);
+
+	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+	return ret;
+}
+
+static int mt9t112_set_pll_dividers(const struct i2c_client *client,
+				    u8 m, u8 n,
+				    u8 p1, u8 p2, u8 p3,
+				    u8 p4, u8 p5, u8 p6,
+				    u8 p7)
+{
+	int ret;
+	u16 val;
+
+	/* N/M */
+	val = (n << 8) |
+	      (m << 0);
+	mt9t112_reg_mask_set(ret, client, 0x0010, 0x3fff, val);
+
+	/* P1/P2/P3 */
+	val = ((p3 & 0x0F) << 8) |
+	      ((p2 & 0x0F) << 4) |
+	      ((p1 & 0x0F) << 0);
+	mt9t112_reg_mask_set(ret, client, 0x0012, 0x0fff, val);
+
+	/* P4/P5/P6 */
+	val = (0x7         << 12) |
+	      ((p6 & 0x0F) <<  8) |
+	      ((p5 & 0x0F) <<  4) |
+	      ((p4 & 0x0F) <<  0);
+	mt9t112_reg_mask_set(ret, client, 0x002A, 0x7fff, val);
+
+	/* P7 */
+	val = (0x1         << 12) |
+	      ((p7 & 0x0F) <<  0);
+	mt9t112_reg_mask_set(ret, client, 0x002C, 0x100f, val);
+
+	return ret;
+}
+
+static int mt9t112_init_pll(const struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	int data, i, ret;
+
+	mt9t112_reg_mask_set(ret, client, 0x0014, 0x003, 0x0001);
+
+	/* PLL control: BYPASS PLL = 8517 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x2145);
+
+	/* Replace these registers when new timing parameters are generated */
+	mt9t112_set_pll_dividers(client,
+				 priv->info->divider.m,
+				 priv->info->divider.n,
+				 priv->info->divider.p1,
+				 priv->info->divider.p2,
+				 priv->info->divider.p3,
+				 priv->info->divider.p4,
+				 priv->info->divider.p5,
+				 priv->info->divider.p6,
+				 priv->info->divider.p7);
+
+	/*
+	 * TEST_BYPASS  on
+	 * PLL_ENABLE   on
+	 * SEL_LOCK_DET on
+	 * TEST_BYPASS  off
+	 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x2525);
+	mt9t112_reg_write(ret, client, 0x0014, 0x2527);
+	mt9t112_reg_write(ret, client, 0x0014, 0x3427);
+	mt9t112_reg_write(ret, client, 0x0014, 0x3027);
+
+	mdelay(10);
+
+	/*
+	 * PLL_BYPASS off
+	 * Reference clock count
+	 * I2C Master Clock Divider
+	 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x3046);
+	mt9t112_reg_write(ret, client, 0x0022, 0x0190);
+	mt9t112_reg_write(ret, client, 0x3B84, 0x0212);
+
+	/* External sensor clock is PLL bypass */
+	mt9t112_reg_write(ret, client, 0x002E, 0x0500);
+
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0002, 0x0002);
+	mt9t112_reg_mask_set(ret, client, 0x3B82, 0x0004, 0x0004);
+
+	/* MCU disabled */
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0x0004);
+
+	/* out of standby */
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0);
+
+	mdelay(50);
+
+	/*
+	 * Standby Workaround
+	 * Disable Secondary I2C Pads
+	 */
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+
+	/* poll to verify out of standby. Must Poll this bit */
+	for (i = 0; i < 100; i++) {
+		mt9t112_reg_read(data, client, 0x0018);
+		if (0x4000 & data)
+			break;
+
+		mdelay(10);
+	}
+
+	return ret;
+}
+
+static int mt9t112_init_setting(const struct i2c_client *client)
+{
+
+	int ret;
+
+	/* Adaptive Output Clock (A) */
+	mt9t112_mcu_mask_set(ret, client, VAR(26, 160), 0x0040, 0x0000);
+
+	/* Read Mode (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 12), 0x0024);
+
+	/* Fine Correction (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 15), 0x00CC);
+
+	/* Fine IT Min (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 17), 0x01f1);
+
+	/* Fine IT Max Margin (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 19), 0x00fF);
+
+	/* Base Frame Lines (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 29), 0x032D);
+
+	/* Min Line Length (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 31), 0x073a);
+
+	/* Line Length (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 37), 0x07d0);
+
+	/* Adaptive Output Clock (B) */
+	mt9t112_mcu_mask_set(ret, client, VAR(27, 160), 0x0040, 0x0000);
+
+	/* Row Start (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 74), 0x004);
+
+	/* Column Start (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 76), 0x004);
+
+	/* Row End (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 78), 0x60B);
+
+	/* Column End (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 80), 0x80B);
+
+	/* Fine Correction (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 87), 0x008C);
+
+	/* Fine IT Min (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 89), 0x01F1);
+
+	/* Fine IT Max Margin (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 91), 0x00FF);
+
+	/* Base Frame Lines (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 101), 0x0668);
+
+	/* Min Line Length (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 103), 0x0AF0);
+
+	/* Line Length (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 109), 0x0AF0);
+
+	/*
+	 * Flicker Dectection registers
+	 * This section should be replaced whenever new Timing file is generated
+	 * All the following registers need to be replaced
+	 * Following registers are generated from Register Wizard but user can
+	 * modify them. For detail see auto flicker detection tuning
+	 */
+
+	/* FD_FDPERIOD_SELECT */
+	mt9t112_mcu_write(ret, client, VAR8(8, 5), 0x01);
+
+	/* PRI_B_CONFIG_FD_ALGO_RUN */
+	mt9t112_mcu_write(ret, client, VAR(27, 17), 0x0003);
+
+	/* PRI_A_CONFIG_FD_ALGO_RUN */
+	mt9t112_mcu_write(ret, client, VAR(26, 17), 0x0003);
+
+	/*
+	 * AFD range detection tuning registers
+	 */
+
+	/* search_f1_50 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 165), 0x25);
+
+	/* search_f2_50 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 166), 0x28);
+
+	/* search_f1_60 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 167), 0x2C);
+
+	/* search_f2_60 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 168), 0x2F);
+
+	/* period_50Hz (A) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 68), 0xBA);
+
+	/* secret register by aptina */
+	/* period_50Hz (A MSB) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 303), 0x00);
+
+	/* period_60Hz (A) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 69), 0x9B);
+
+	/* secret register by aptina */
+	/* period_60Hz (A MSB) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 301), 0x00);
+
+	/* period_50Hz (B) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 140), 0x82);
+
+	/* secret register by aptina */
+	/* period_50Hz (B) MSB */
+	mt9t112_mcu_write(ret, client, VAR8(18, 304), 0x00);
+
+	/* period_60Hz (B) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 141), 0x6D);
+
+	/* secret register by aptina */
+	/* period_60Hz (B) MSB */
+	mt9t112_mcu_write(ret, client, VAR8(18, 302), 0x00);
+
+	/* FD Mode */
+	mt9t112_mcu_write(ret, client, VAR8(8, 2), 0x10);
+
+	/* Stat_min */
+	mt9t112_mcu_write(ret, client, VAR8(8, 9), 0x02);
+
+	/* Stat_max */
+	mt9t112_mcu_write(ret, client, VAR8(8, 10), 0x03);
+
+	/* Min_amplitude */
+	mt9t112_mcu_write(ret, client, VAR8(8, 12), 0x0A);
+
+	/* RX FIFO Watermark (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 70), 0x0014);
+
+	/* RX FIFO Watermark (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 142), 0x0014);
+
+	/* MCLK: 16MHz
+	 * PCLK: 73MHz
+	 * CorePixCLK: 36.5 MHz
+	 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x0044), 133);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x0045), 110);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x008c), 130);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x008d), 108);
+
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00A5), 27);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a6), 30);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a7), 32);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a8), 35);
+
+	return ret;
+}
+
+static int mt9t112_auto_focus_setting(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_mcu_write(ret, client, VAR(12, 13),	0x000F);
+	mt9t112_mcu_write(ret, client, VAR(12, 23),	0x0F0F);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x06);
+
+	mt9t112_reg_write(ret, client, 0x0614, 0x0000);
+
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x05);
+	mt9t112_mcu_write(ret, client, VAR8(12, 2),	0x02);
+	mt9t112_mcu_write(ret, client, VAR(12, 3),	0x0002);
+	mt9t112_mcu_write(ret, client, VAR(17, 3),	0x8001);
+	mt9t112_mcu_write(ret, client, VAR(17, 11),	0x0025);
+	mt9t112_mcu_write(ret, client, VAR(17, 13),	0x0193);
+	mt9t112_mcu_write(ret, client, VAR8(17, 33),	0x18);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x05);
+
+	return ret;
+}
+
+static int mt9t112_auto_focus_trigger(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_mcu_write(ret, client, VAR8(12, 25), 0x01);
+
+	return ret;
+}
+
+static int mt9t112_init_camera(const struct i2c_client *client)
+{
+	int ret;
+
+	ECHECKER(ret, mt9t112_reset(client));
+
+	ECHECKER(ret, mt9t112_init_pll(client));
+
+	ECHECKER(ret, mt9t112_init_setting(client));
+
+	ECHECKER(ret, mt9t112_auto_focus_setting(client));
+
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0);
+
+	/* Analog setting B */
+	mt9t112_reg_write(ret, client, 0x3084, 0x2409);
+	mt9t112_reg_write(ret, client, 0x3092, 0x0A49);
+	mt9t112_reg_write(ret, client, 0x3094, 0x4949);
+	mt9t112_reg_write(ret, client, 0x3096, 0x4950);
+
+	/*
+	 * Disable adaptive clock
+	 * PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	 * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	 */
+	mt9t112_mcu_write(ret, client, VAR(26, 160), 0x0A2E);
+	mt9t112_mcu_write(ret, client, VAR(27, 160), 0x0A2E);
+
+	/* Configure STatus in Status_before_length Format and enable header */
+	/* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */
+	mt9t112_mcu_write(ret, client, VAR(27, 144), 0x0CB4);
+
+	/* Enable JPEG in context B */
+	/* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */
+	mt9t112_mcu_write(ret, client, VAR8(27, 142), 0x01);
+
+	/* Disable Dac_TXLO */
+	mt9t112_reg_write(ret, client, 0x316C, 0x350F);
+
+	/* Set max slew rates */
+	mt9t112_reg_write(ret, client, 0x1E, 0x777);
+
+	return ret;
+}
+
+/************************************************************************
+
+
+			soc_camera_ops
+
+
+************************************************************************/
+static int mt9t112_set_bus_param(struct soc_camera_device *icd,
+				 unsigned long	flags)
+{
+	return 0;
+}
+
+static unsigned long mt9t112_query_bus_param(struct soc_camera_device *icd)
+{
+	struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct soc_camera_link *icl = to_soc_camera_link(icd);
+	unsigned long flags = SOCAM_MASTER | SOCAM_VSYNC_ACTIVE_HIGH |
+		SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH;
+
+	flags |= (priv->info->flags & MT9T112_FLAG_PCLK_RISING_EDGE) ?
+		SOCAM_PCLK_SAMPLE_RISING : SOCAM_PCLK_SAMPLE_FALLING;
+
+	if (priv->info->flags & MT9T112_FLAG_DATAWIDTH_8)
+		flags |= SOCAM_DATAWIDTH_8;
+	else
+		flags |= SOCAM_DATAWIDTH_10;
+
+	return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static struct soc_camera_ops mt9t112_ops = {
+	.set_bus_param		= mt9t112_set_bus_param,
+	.query_bus_param	= mt9t112_query_bus_param,
+};
+
+/************************************************************************
+
+
+			v4l2_subdev_core_ops
+
+
+************************************************************************/
+static int mt9t112_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	id->ident    = priv->model;
+	id->revision = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9t112_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = sd->priv;
+	int                ret;
+
+	reg->size = 2;
+	mt9t112_reg_read(ret, client, reg->reg);
+
+	reg->val = (__u64)ret;
+
+	return 0;
+}
+
+static int mt9t112_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = sd->priv;
+	int ret;
+
+	mt9t112_reg_write(ret, client, reg->reg, reg->val);
+
+	return ret;
+}
+#endif
+
+static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
+	.g_chip_ident	= mt9t112_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9t112_g_register,
+	.s_register	= mt9t112_s_register,
+#endif
+};
+
+
+/************************************************************************
+
+
+			v4l2_subdev_video_ops
+
+
+************************************************************************/
+static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	int ret = 0;
+
+	if (!enable) {
+		/* FIXME
+		 *
+		 * If user selected large output size,
+		 * and used it long time,
+		 * mt9t112 camera will be very warm.
+		 *
+		 * But current driver can not stop mt9t112 camera.
+		 * So, set small size here to solve this problem.
+		 */
+		mt9t112_set_a_frame_size(client, VGA_WIDTH, VGA_HEIGHT);
+		return ret;
+	}
+
+	if (!(priv->flags & INIT_DONE)) {
+		u16 param = (MT9T112_FLAG_PCLK_RISING_EDGE &
+			     priv->info->flags) ? 0x0001 : 0x0000;
+
+		ECHECKER(ret, mt9t112_init_camera(client));
+
+		/* Invert PCLK (Data sampled on falling edge of pixclk) */
+		mt9t112_reg_write(ret, client, 0x3C20, param);
+
+		mdelay(5);
+
+		priv->flags |= INIT_DONE;
+	}
+
+	mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
+	mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+	mt9t112_set_a_frame_size(client,
+				 priv->frame.width,
+				 priv->frame.height);
+
+	ECHECKER(ret, mt9t112_auto_focus_trigger(client));
+
+	dev_dbg(&client->dev, "format : %d\n", priv->format->code);
+	dev_dbg(&client->dev, "size   : %d x %d\n",
+		priv->frame.width,
+		priv->frame.height);
+
+	CLOCK_INFO(client, EXT_CLOCK);
+
+	return ret;
+}
+
+static int mt9t112_set_params(struct i2c_client *client, u32 width, u32 height,
+			      enum v4l2_mbus_pixelcode code)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	int i;
+
+	priv->format = NULL;
+
+	/*
+	 * frame size check
+	 */
+	mt9t112_frame_check(&width, &height);
+
+	/*
+	 * get color format
+	 */
+	for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
+		if (mt9t112_cfmts[i].code == code)
+			break;
+
+	if (i == ARRAY_SIZE(mt9t112_cfmts))
+		return -EINVAL;
+
+	priv->frame.width  = (u16)width;
+	priv->frame.height = (u16)height;
+
+	priv->format = mt9t112_cfmts + i;
+
+	return 0;
+}
+
+static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= VGA_WIDTH;
+	a->bounds.height		= VGA_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left	= 0;
+	a->c.top	= 0;
+	a->c.width	= VGA_WIDTH;
+	a->c.height	= VGA_HEIGHT;
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = sd->priv;
+	struct v4l2_rect *rect = &a->c;
+
+	return mt9t112_set_params(client, rect->width, rect->height,
+				 V4L2_MBUS_FMT_YUYV8_2X8_BE);
+}
+
+static int mt9t112_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	if (!priv->format) {
+		int ret = mt9t112_set_params(client, VGA_WIDTH, VGA_HEIGHT,
+					     V4L2_MBUS_FMT_YUYV8_2X8_BE);
+		if (ret < 0)
+			return ret;
+	}
+
+	mf->width	= priv->frame.width;
+	mf->height	= priv->frame.height;
+	/* TODO: set colorspace */
+	mf->code	= priv->format->code;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9t112_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = sd->priv;
+
+	/* TODO: set colorspace */
+	return mt9t112_set_params(client, mf->width, mf->height, mf->code);
+}
+
+static int mt9t112_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	mt9t112_frame_check(&mf->width, &mf->height);
+
+	/* TODO: set colorspace */
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9t112_enum_fmt(struct v4l2_subdev *sd, int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(mt9t112_cfmts))
+		return -EINVAL;
+
+	*code = mt9t112_cfmts[index].code;
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
+	.s_stream	= mt9t112_s_stream,
+	.g_mbus_fmt	= mt9t112_g_fmt,
+	.s_mbus_fmt	= mt9t112_s_fmt,
+	.try_mbus_fmt	= mt9t112_try_fmt,
+	.cropcap	= mt9t112_cropcap,
+	.g_crop		= mt9t112_g_crop,
+	.s_crop		= mt9t112_s_crop,
+	.enum_mbus_fmt	= mt9t112_enum_fmt,
+};
+
+/************************************************************************
+
+
+			i2c driver
+
+
+************************************************************************/
+static struct v4l2_subdev_ops mt9t112_subdev_ops = {
+	.core	= &mt9t112_subdev_core_ops,
+	.video	= &mt9t112_subdev_video_ops,
+};
+
+static int mt9t112_camera_probe(struct soc_camera_device *icd,
+				struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	const char          *devname;
+	int                  chipid;
+
+	/*
+	 * We must have a parent by now. And it cannot be a wrong one.
+	 * So this entire test is completely redundant.
+	 */
+	if (!icd->dev.parent ||
+	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+		return -ENODEV;
+
+	/*
+	 * check and show chip ID
+	 */
+	mt9t112_reg_read(chipid, client, 0x0000);
+
+	switch (chipid) {
+	case 0x2680:
+		devname = "mt9t111";
+		priv->model = V4L2_IDENT_MT9T111;
+		break;
+	case 0x2682:
+		devname = "mt9t112";
+		priv->model = V4L2_IDENT_MT9T112;
+		break;
+	default:
+		dev_err(&client->dev, "Product ID error %04x\n", chipid);
+		return -ENODEV;
+	}
+
+	dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid);
+
+	return 0;
+}
+
+static int mt9t112_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9t112_priv        *priv;
+	struct soc_camera_device   *icd = client->dev.platform_data;
+	struct soc_camera_link     *icl;
+	int                         ret;
+
+	if (!icd) {
+		dev_err(&client->dev, "mt9t112: missing soc-camera data!\n");
+		return -EINVAL;
+	}
+
+	icl = to_soc_camera_link(icd);
+	if (!icl || !icl->priv)
+		return -EINVAL;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->info = icl->priv;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);
+
+	icd->ops = &mt9t112_ops;
+
+	ret = mt9t112_camera_probe(icd, client);
+	if (ret) {
+		icd->ops = NULL;
+		i2c_set_clientdata(client, NULL);
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int mt9t112_remove(struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct soc_camera_device *icd = client->dev.platform_data;
+
+	icd->ops = NULL;
+	i2c_set_clientdata(client, NULL);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id mt9t112_id[] = {
+	{ "mt9t112", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t112_id);
+
+static struct i2c_driver mt9t112_i2c_driver = {
+	.driver = {
+		.name = "mt9t112",
+	},
+	.probe    = mt9t112_probe,
+	.remove   = mt9t112_remove,
+	.id_table = mt9t112_id,
+};
+
+/************************************************************************
+
+
+			module function
+
+
+************************************************************************/
+static int __init mt9t112_module_init(void)
+{
+	return i2c_add_driver(&mt9t112_i2c_driver);
+}
+
+static void __exit mt9t112_module_exit(void)
+{
+	i2c_del_driver(&mt9t112_i2c_driver);
+}
+
+module_init(mt9t112_module_init);
+module_exit(mt9t112_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera driver for mt9t112");
+MODULE_AUTHOR("Kuninori Morimoto");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 995607f..91df7ec 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -18,9 +18,11 @@
 #include <media/v4l2-chip-ident.h>
 #include <media/soc_camera.h>
 
-/* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
+/*
+ * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
  * The platform has to define ctruct i2c_board_info objects and link to them
- * from struct soc_camera_link */
+ * from struct soc_camera_link
+ */
 
 static char *sensor_type;
 module_param(sensor_type, charp, S_IRUGO);
@@ -62,41 +64,49 @@
 #define MT9V022_COLUMN_SKIP		1
 #define MT9V022_ROW_SKIP		4
 
-static const struct soc_camera_data_format mt9v022_colour_formats[] = {
-	/* Order important: first natively supported,
-	 * second supported with a GPIO extender */
-	{
-		.name		= "Bayer (sRGB) 10 bit",
-		.depth		= 10,
-		.fourcc		= V4L2_PIX_FMT_SBGGR16,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}, {
-		.name		= "Bayer (sRGB) 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_SBGGR8,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}
+/* MT9V022 has only one fixed colorspace per pixelcode */
+struct mt9v022_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
 };
 
-static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
+/* Find a data format by a pixel code in an array */
+static const struct mt9v022_datafmt *mt9v022_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct mt9v022_datafmt mt9v022_colour_fmts[] = {
+	/*
+	 * Order important: first natively supported,
+	 * second supported with a GPIO extender
+	 */
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
 	/* Order important - see above */
-	{
-		.name		= "Monochrome 10 bit",
-		.depth		= 10,
-		.fourcc		= V4L2_PIX_FMT_Y16,
-	}, {
-		.name		= "Monochrome 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_GREY,
-	},
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 struct mt9v022 {
 	struct v4l2_subdev subdev;
 	struct v4l2_rect rect;	/* Sensor window */
-	__u32 fourcc;
+	const struct mt9v022_datafmt *fmt;
+	const struct mt9v022_datafmt *fmts;
+	int num_fmts;
 	int model;	/* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
 	u16 chip_control;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
 };
 
 static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
@@ -143,9 +153,11 @@
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
 	int ret;
 
-	/* Almost the default mode: master, parallel, simultaneous, and an
+	/*
+	 * Almost the default mode: master, parallel, simultaneous, and an
 	 * undocumented bit 0x200, which is present in table 7, but not in 8,
-	 * plus snapshot mode to disable scan for now */
+	 * plus snapshot mode to disable scan for now
+	 */
 	mt9v022->chip_control |= 0x10;
 	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
 	if (!ret)
@@ -265,12 +277,10 @@
 	struct i2c_client *client = sd->priv;
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
 	struct v4l2_rect rect = a->c;
-	struct soc_camera_device *icd = client->dev.platform_data;
 	int ret;
 
 	/* Bayer format - even size lengths */
-	if (mt9v022->fourcc == V4L2_PIX_FMT_SBGGR8 ||
-	    mt9v022->fourcc == V4L2_PIX_FMT_SBGGR16) {
+	if (mt9v022->fmts == mt9v022_colour_fmts) {
 		rect.width	= ALIGN(rect.width, 2);
 		rect.height	= ALIGN(rect.height, 2);
 		/* Let the user play with the starting pixel */
@@ -287,10 +297,10 @@
 	if (ret >= 0) {
 		if (ret & 1) /* Autoexposure */
 			ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
-					rect.height + icd->y_skip_top + 43);
+					rect.height + mt9v022->y_skip_top + 43);
 		else
 			ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-					rect.height + icd->y_skip_top + 43);
+					rect.height + mt9v022->y_skip_top + 43);
 	}
 	/* Setup frame format: defaults apart from width and height */
 	if (!ret)
@@ -298,8 +308,10 @@
 	if (!ret)
 		ret = reg_write(client, MT9V022_ROW_START, rect.top);
 	if (!ret)
-		/* Default 94, Phytec driver says:
-		 * "width + horizontal blank >= 660" */
+		/*
+		 * Default 94, Phytec driver says:
+		 * "width + horizontal blank >= 660"
+		 */
 		ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
 				rect.width > 660 - 43 ? 43 :
 				660 - rect.width);
@@ -309,7 +321,7 @@
 		ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
 	if (!ret)
 		ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
-				rect.height + icd->y_skip_top);
+				rect.height + mt9v022->y_skip_top);
 
 	if (ret < 0)
 		return ret;
@@ -346,46 +358,48 @@
 	return 0;
 }
 
-static int mt9v022_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9v022_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->width		= mt9v022->rect.width;
-	pix->height		= mt9v022->rect.height;
-	pix->pixelformat	= mt9v022->fourcc;
-	pix->field		= V4L2_FIELD_NONE;
-	pix->colorspace		= V4L2_COLORSPACE_SRGB;
+	mf->width	= mt9v022->rect.width;
+	mf->height	= mt9v022->rect.height;
+	mf->code	= mt9v022->fmt->code;
+	mf->colorspace	= mt9v022->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int mt9v022_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9v022_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct mt9v022 *mt9v022 = to_mt9v022(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct v4l2_crop a = {
 		.c = {
 			.left	= mt9v022->rect.left,
 			.top	= mt9v022->rect.top,
-			.width	= pix->width,
-			.height	= pix->height,
+			.width	= mf->width,
+			.height	= mf->height,
 		},
 	};
 	int ret;
 
-	/* The caller provides a supported format, as verified per call to
-	 * icd->try_fmt(), datawidth is from our supported format list */
-	switch (pix->pixelformat) {
-	case V4L2_PIX_FMT_GREY:
-	case V4L2_PIX_FMT_Y16:
+	/*
+	 * The caller provides a supported format, as verified per call to
+	 * icd->try_fmt(), datawidth is from our supported format list
+	 */
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_GREY8_1X8:
+	case V4L2_MBUS_FMT_Y10_1X10:
 		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
 			return -EINVAL;
 		break;
-	case V4L2_PIX_FMT_SBGGR8:
-	case V4L2_PIX_FMT_SBGGR16:
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
 		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
 			return -EINVAL;
 		break;
@@ -399,26 +413,38 @@
 	/* No support for scaling on this camera, just crop. */
 	ret = mt9v022_s_crop(sd, &a);
 	if (!ret) {
-		pix->width = mt9v022->rect.width;
-		pix->height = mt9v022->rect.height;
-		mt9v022->fourcc = pix->pixelformat;
+		mf->width	= mt9v022->rect.width;
+		mf->height	= mt9v022->rect.height;
+		mt9v022->fmt	= mt9v022_find_datafmt(mf->code,
+					mt9v022->fmts, mt9v022->num_fmts);
+		mf->colorspace	= mt9v022->fmt->colorspace;
 	}
 
 	return ret;
 }
 
-static int mt9v022_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int mt9v022_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
-	struct soc_camera_device *icd = client->dev.platform_data;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int align = pix->pixelformat == V4L2_PIX_FMT_SBGGR8 ||
-		pix->pixelformat == V4L2_PIX_FMT_SBGGR16;
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	const struct mt9v022_datafmt *fmt;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
 
-	v4l_bound_align_image(&pix->width, MT9V022_MIN_WIDTH,
+	v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
 		MT9V022_MAX_WIDTH, align,
-		&pix->height, MT9V022_MIN_HEIGHT + icd->y_skip_top,
-		MT9V022_MAX_HEIGHT + icd->y_skip_top, align, 0);
+		&mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
+		MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0);
+
+	fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts,
+				   mt9v022->num_fmts);
+	if (!fmt) {
+		fmt = mt9v022->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->colorspace	= fmt->colorspace;
 
 	return 0;
 }
@@ -635,8 +661,10 @@
 					      48 + range / 2) / range + 16;
 			if (gain >= 32)
 				gain &= ~1;
-			/* The user wants to set gain manually, hope, she
-			 * knows, what she's doing... Switch AGC off. */
+			/*
+			 * The user wants to set gain manually, hope, she
+			 * knows, what she's doing... Switch AGC off.
+			 */
 
 			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
 				return -EIO;
@@ -655,8 +683,10 @@
 			unsigned long range = qctrl->maximum - qctrl->minimum;
 			unsigned long shutter = ((ctrl->value - qctrl->minimum) *
 						 479 + range / 2) / range + 1;
-			/* The user wants to set shutter width manually, hope,
-			 * she knows, what she's doing... Switch AEC off. */
+			/*
+			 * The user wants to set shutter width manually, hope,
+			 * she knows, what she's doing... Switch AEC off.
+			 */
 
 			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
 				return -EIO;
@@ -689,8 +719,10 @@
 	return 0;
 }
 
-/* Interface active, can use i2c. If it fails, it can indeed mean, that
- * this wasn't our capture interface, so, we wait for the right one */
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
 static int mt9v022_video_probe(struct soc_camera_device *icd,
 			       struct i2c_client *client)
 {
@@ -733,17 +765,17 @@
 			    !strcmp("color", sensor_type))) {
 		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
-		icd->formats = mt9v022_colour_formats;
+		mt9v022->fmts = mt9v022_colour_fmts;
 	} else {
 		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
 		mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
-		icd->formats = mt9v022_monochrome_formats;
+		mt9v022->fmts = mt9v022_monochrome_fmts;
 	}
 
 	if (ret < 0)
 		goto ei2c;
 
-	icd->num_formats = 0;
+	mt9v022->num_fmts = 0;
 
 	/*
 	 * This is a 10bit sensor, so by default we only allow 10bit.
@@ -756,14 +788,14 @@
 		flags = SOCAM_DATAWIDTH_10;
 
 	if (flags & SOCAM_DATAWIDTH_10)
-		icd->num_formats++;
+		mt9v022->num_fmts++;
 	else
-		icd->formats++;
+		mt9v022->fmts++;
 
 	if (flags & SOCAM_DATAWIDTH_8)
-		icd->num_formats++;
+		mt9v022->num_fmts++;
 
-	mt9v022->fourcc = icd->formats->fourcc;
+	mt9v022->fmt = &mt9v022->fmts[0];
 
 	dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
 		 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
@@ -787,6 +819,16 @@
 		icl->free_bus(icl);
 }
 
+static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	*lines = mt9v022->y_skip_top;
+
+	return 0;
+}
+
 static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
 	.g_ctrl		= mt9v022_g_ctrl,
 	.s_ctrl		= mt9v022_s_ctrl,
@@ -797,19 +839,38 @@
 #endif
 };
 
+static int mt9v022_enum_fmt(struct v4l2_subdev *sd, int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	struct i2c_client *client = sd->priv;
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	if ((unsigned int)index >= mt9v022->num_fmts)
+		return -EINVAL;
+
+	*code = mt9v022->fmts[index].code;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
 	.s_stream	= mt9v022_s_stream,
-	.s_fmt		= mt9v022_s_fmt,
-	.g_fmt		= mt9v022_g_fmt,
-	.try_fmt	= mt9v022_try_fmt,
+	.s_mbus_fmt	= mt9v022_s_fmt,
+	.g_mbus_fmt	= mt9v022_g_fmt,
+	.try_mbus_fmt	= mt9v022_try_fmt,
 	.s_crop		= mt9v022_s_crop,
 	.g_crop		= mt9v022_g_crop,
 	.cropcap	= mt9v022_cropcap,
+	.enum_mbus_fmt	= mt9v022_enum_fmt,
+};
+
+static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9v022_g_skip_top_lines,
 };
 
 static struct v4l2_subdev_ops mt9v022_subdev_ops = {
 	.core	= &mt9v022_subdev_core_ops,
 	.video	= &mt9v022_subdev_video_ops,
+	.sensor	= &mt9v022_subdev_sensor_ops,
 };
 
 static int mt9v022_probe(struct i2c_client *client,
@@ -851,8 +912,7 @@
 	 * MT9V022 _really_ corrupts the first read out line.
 	 * TODO: verify on i.MX31
 	 */
-	icd->y_skip_top		= 1;
-
+	mt9v022->y_skip_top	= 1;
 	mt9v022->rect.left	= MT9V022_COLUMN_SKIP;
 	mt9v022->rect.top	= MT9V022_ROW_SKIP;
 	mt9v022->rect.width	= MT9V022_MAX_WIDTH;
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 7280229..2ba14fb 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -37,6 +37,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-dma-contig.h>
+#include <media/soc_mediabus.h>
 
 #include <asm/dma.h>
 #include <asm/fiq.h>
@@ -94,14 +95,16 @@
 /* buffer for one video frame */
 struct mx1_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
-	const struct soc_camera_data_format *fmt;
-	int inwork;
+	struct videobuf_buffer		vb;
+	enum v4l2_mbus_pixelcode	code;
+	int				inwork;
 };
 
-/* i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor
+/*
+ * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor
  * Interface. If anyone ever builds hardware to enable more than
- * one camera, they will have to modify this driver too */
+ * one camera, they will have to modify this driver too
+ */
 struct mx1_camera_dev {
 	struct soc_camera_host		soc_host;
 	struct soc_camera_device	*icd;
@@ -126,9 +129,13 @@
 			      unsigned int *size)
 {
 	struct soc_camera_device *icd = vq->priv_data;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
 
-	*size = icd->user_width * icd->user_height *
-		((icd->current_fmt->depth + 7) >> 3);
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
+	*size = bytes_per_line * icd->user_height;
 
 	if (!*count)
 		*count = 32;
@@ -151,8 +158,10 @@
 	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
 
-	/* This waits until this buffer is out of danger, i.e., until it is no
-	 * longer in STATE_QUEUED or STATE_ACTIVE */
+	/*
+	 * This waits until this buffer is out of danger, i.e., until it is no
+	 * longer in STATE_QUEUED or STATE_ACTIVE
+	 */
 	videobuf_waiton(vb, 0, 0);
 	videobuf_dma_contig_free(vq, vb);
 
@@ -165,6 +174,11 @@
 	struct soc_camera_device *icd = vq->priv_data;
 	struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
 	int ret;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
 
 	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
@@ -174,22 +188,24 @@
 
 	BUG_ON(NULL == icd->current_fmt);
 
-	/* I think, in buf_prepare you only have to protect global data,
-	 * the actual buffer is yours */
+	/*
+	 * I think, in buf_prepare you only have to protect global data,
+	 * the actual buffer is yours
+	 */
 	buf->inwork = 1;
 
-	if (buf->fmt	!= icd->current_fmt ||
+	if (buf->code	!= icd->current_fmt->code ||
 	    vb->width	!= icd->user_width ||
 	    vb->height	!= icd->user_height ||
 	    vb->field	!= field) {
-		buf->fmt	= icd->current_fmt;
+		buf->code	= icd->current_fmt->code;
 		vb->width	= icd->user_width;
 		vb->height	= icd->user_height;
 		vb->field	= field;
 		vb->state	= VIDEOBUF_NEEDS_INIT;
 	}
 
-	vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+	vb->size = bytes_per_line * vb->height;
 	if (0 != vb->baddr && vb->bsize < vb->size) {
 		ret = -EINVAL;
 		goto out;
@@ -381,8 +397,10 @@
 
 	lcdclk = clk_get_rate(pcdev->clk);
 
-	/* We verify platform_mclk_10khz != 0, so if anyone breaks it, here
-	 * they get a nice Oops */
+	/*
+	 * We verify platform_mclk_10khz != 0, so if anyone breaks it, here
+	 * they get a nice Oops
+	 */
 	div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
 
 	dev_dbg(pcdev->icd->dev.parent,
@@ -420,8 +438,10 @@
 	clk_disable(pcdev->clk);
 }
 
-/* The following two functions absolutely depend on the fact, that
- * there can be only one camera on i.MX1/i.MXL camera sensor interface */
+/*
+ * The following two functions absolutely depend on the fact, that
+ * there can be only one camera on i.MX1/i.MXL camera sensor interface
+ */
 static int mx1_camera_add_device(struct soc_camera_device *icd)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
@@ -487,12 +507,10 @@
 
 	/* MX1 supports only 8bit buswidth */
 	common_flags = soc_camera_bus_param_compatible(camera_flags,
-							       CSI_BUS_FLAGS);
+						       CSI_BUS_FLAGS);
 	if (!common_flags)
 		return -EINVAL;
 
-	icd->buswidth = 8;
-
 	/* Make choises, based on platform choice */
 	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
 		(common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
@@ -545,7 +563,8 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	const struct soc_camera_format_xlate *xlate;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
-	int ret;
+	struct v4l2_mbus_framefmt mf;
+	int ret, buswidth;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
 	if (!xlate) {
@@ -554,12 +573,33 @@
 		return -EINVAL;
 	}
 
-	ret = v4l2_subdev_call(sd, video, s_fmt, f);
-	if (!ret) {
-		icd->buswidth = xlate->buswidth;
-		icd->current_fmt = xlate->host_fmt;
+	buswidth = xlate->host_fmt->bits_per_sample;
+	if (buswidth > 8) {
+		dev_warn(icd->dev.parent,
+			 "bits-per-sample %d for format %x unsupported\n",
+			 buswidth, pix->pixelformat);
+		return -EINVAL;
 	}
 
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
+
+	if (mf.code != xlate->code)
+		return -EINVAL;
+
+	pix->width		= mf.width;
+	pix->height		= mf.height;
+	pix->field		= mf.field;
+	pix->colorspace		= mf.colorspace;
+	icd->current_fmt	= xlate;
+
 	return ret;
 }
 
@@ -567,10 +607,36 @@
 			      struct v4l2_format *f)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
+	int ret;
 	/* TODO: limit to mx1 hardware capabilities */
 
+	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+	if (!xlate) {
+		dev_warn(icd->dev.parent, "Format %x not found\n",
+			 pix->pixelformat);
+		return -EINVAL;
+	}
+
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
+
 	/* limit to sensor capabilities */
-	return v4l2_subdev_call(sd, video, try_fmt, f);
+	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
+
+	pix->width	= mf.width;
+	pix->height	= mf.height;
+	pix->field	= mf.field;
+	pix->colorspace	= mf.colorspace;
+
+	return 0;
 }
 
 static int mx1_camera_reqbufs(struct soc_camera_file *icf,
@@ -578,10 +644,12 @@
 {
 	int i;
 
-	/* This is for locking debugging only. I removed spinlocks and now I
+	/*
+	 * This is for locking debugging only. I removed spinlocks and now I
 	 * check whether .prepare is ever called on a linked buffer, or whether
 	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-	 * it hadn't triggered */
+	 * it hadn't triggered
+	 */
 	for (i = 0; i < p->count; i++) {
 		struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i],
 						      struct mx1_buffer, vb);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index 7db82bd..bd297f5 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -23,6 +23,7 @@
 #include <media/v4l2-dev.h>
 #include <media/videobuf-dma-contig.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 
 #include <mach/ipu.h>
 #include <mach/mx3_camera.h>
@@ -63,7 +64,7 @@
 struct mx3_camera_buffer {
 	/* common v4l buffer stuff -- must be first */
 	struct videobuf_buffer			vb;
-	const struct soc_camera_data_format	*fmt;
+	enum v4l2_mbus_pixelcode		code;
 
 	/* One descriptot per scatterlist (per frame) */
 	struct dma_async_tx_descriptor		*txd;
@@ -118,8 +119,6 @@
 	enum ipu_channel	id;
 };
 
-static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt);
-
 static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg)
 {
 	return __raw_readl(mx3->base + reg);
@@ -211,17 +210,16 @@
 	struct soc_camera_device *icd = vq->priv_data;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	/*
-	 * bits-per-pixel (depth) as specified in camera's pixel format does
-	 * not necessarily match what the camera interface writes to RAM, but
-	 * it should be good enough for now.
-	 */
-	unsigned int bpp = DIV_ROUND_UP(icd->current_fmt->depth, 8);
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
 
 	if (!mx3_cam->idmac_channel[0])
 		return -EINVAL;
 
-	*size = icd->user_width * icd->user_height * bpp;
+	*size = bytes_per_line * icd->user_height;
 
 	if (!*count)
 		*count = 32;
@@ -241,21 +239,26 @@
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	struct mx3_camera_buffer *buf =
 		container_of(vb, struct mx3_camera_buffer, vb);
-	/* current_fmt _must_ always be set */
-	size_t new_size = icd->user_width * icd->user_height *
-		((icd->current_fmt->depth + 7) >> 3);
+	size_t new_size;
 	int ret;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
+	new_size = bytes_per_line * icd->user_height;
 
 	/*
 	 * I think, in buf_prepare you only have to protect global data,
 	 * the actual buffer is yours
 	 */
 
-	if (buf->fmt	!= icd->current_fmt ||
+	if (buf->code	!= icd->current_fmt->code ||
 	    vb->width	!= icd->user_width ||
 	    vb->height	!= icd->user_height ||
 	    vb->field	!= field) {
-		buf->fmt	= icd->current_fmt;
+		buf->code	= icd->current_fmt->code;
 		vb->width	= icd->user_width;
 		vb->height	= icd->user_height;
 		vb->field	= field;
@@ -348,13 +351,13 @@
 	struct dma_async_tx_descriptor *txd = buf->txd;
 	struct idmac_channel *ichan = to_idmac_chan(txd->chan);
 	struct idmac_video_param *video = &ichan->params.video;
-	const struct soc_camera_data_format *data_fmt = icd->current_fmt;
 	dma_cookie_t cookie;
+	u32 fourcc = icd->current_fmt->host_fmt->fourcc;
 
 	BUG_ON(!irqs_disabled());
 
 	/* This is the configuration of one sg-element */
-	video->out_pixel_fmt	= fourcc_to_ipu_pix(data_fmt->fourcc);
+	video->out_pixel_fmt	= fourcc_to_ipu_pix(fourcc);
 	video->out_width	= icd->user_width;
 	video->out_height	= icd->user_height;
 	video->out_stride	= icd->user_width;
@@ -564,30 +567,37 @@
 		SOCAM_DATA_ACTIVE_HIGH |
 		SOCAM_DATA_ACTIVE_LOW;
 
-	/* If requested data width is supported by the platform, use it or any
-	 * possible lower value - i.MX31 is smart enough to schift bits */
-	switch (buswidth) {
-	case 15:
-		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15))
-			return -EINVAL;
+	/*
+	 * If requested data width is supported by the platform, use it or any
+	 * possible lower value - i.MX31 is smart enough to schift bits
+	 */
+	if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15)
 		*flags |= SOCAM_DATAWIDTH_15 | SOCAM_DATAWIDTH_10 |
 			SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
-		break;
-	case 10:
-		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10))
-			return -EINVAL;
+	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10)
 		*flags |= SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_8 |
 			SOCAM_DATAWIDTH_4;
+	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8)
+		*flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
+	else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)
+		*flags |= SOCAM_DATAWIDTH_4;
+
+	switch (buswidth) {
+	case 15:
+		if (!(*flags & SOCAM_DATAWIDTH_15))
+			return -EINVAL;
+		break;
+	case 10:
+		if (!(*flags & SOCAM_DATAWIDTH_10))
+			return -EINVAL;
 		break;
 	case 8:
-		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8))
+		if (!(*flags & SOCAM_DATAWIDTH_8))
 			return -EINVAL;
-		*flags |= SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_4;
 		break;
 	case 4:
-		if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4))
+		if (!(*flags & SOCAM_DATAWIDTH_4))
 			return -EINVAL;
-		*flags |= SOCAM_DATAWIDTH_4;
 		break;
 	default:
 		dev_warn(mx3_cam->soc_host.v4l2_dev.dev,
@@ -636,91 +646,92 @@
 		pdata->dma_dev == chan->device->dev;
 }
 
-static const struct soc_camera_data_format mx3_camera_formats[] = {
+static const struct soc_mbus_pixelfmt mx3_camera_formats[] = {
 	{
-		.name		= "Bayer (sRGB) 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_SBGGR8,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.fourcc			= V4L2_PIX_FMT_SBGGR8,
+		.name			= "Bayer BGGR (sRGB) 8 bit",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
 	}, {
-		.name		= "Monochrome 8 bit",
-		.depth		= 8,
-		.fourcc		= V4L2_PIX_FMT_GREY,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fourcc			= V4L2_PIX_FMT_GREY,
+		.name			= "Monochrome 8 bit",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
 	},
 };
 
-static bool buswidth_supported(struct soc_camera_host *ici, int depth)
+/* This will be corrected as we get more formats */
+static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 {
-	struct mx3_camera_dev *mx3_cam = ici->priv;
-
-	switch (depth) {
-	case 4:
-		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4);
-	case 8:
-		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8);
-	case 10:
-		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10);
-	case 15:
-		return !!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15);
-	}
-	return false;
+	return	fmt->packing == SOC_MBUS_PACKING_NONE ||
+		(fmt->bits_per_sample == 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
+		(fmt->bits_per_sample > 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
 static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
 				  struct soc_camera_format_xlate *xlate)
 {
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	int formats = 0, buswidth, ret;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct device *dev = icd->dev.parent;
+	int formats = 0, ret;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *fmt;
 
-	buswidth = icd->formats[idx].depth;
-
-	if (!buswidth_supported(ici, buswidth))
+	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+	if (ret < 0)
+		/* No more formats */
 		return 0;
 
-	ret = mx3_camera_try_bus_param(icd, buswidth);
+	fmt = soc_mbus_get_fmtdesc(code);
+	if (!fmt) {
+		dev_err(icd->dev.parent,
+			"Invalid format code #%d: %d\n", idx, code);
+		return 0;
+	}
+
+	/* This also checks support for the requested bits-per-sample */
+	ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample);
 	if (ret < 0)
 		return 0;
 
-	switch (icd->formats[idx].fourcc) {
-	case V4L2_PIX_FMT_SGRBG10:
+	switch (code) {
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
 		formats++;
 		if (xlate) {
-			xlate->host_fmt = &mx3_camera_formats[0];
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = buswidth;
+			xlate->host_fmt	= &mx3_camera_formats[0];
+			xlate->code	= code;
 			xlate++;
-			dev_dbg(icd->dev.parent,
-				"Providing format %s using %s\n",
-				mx3_camera_formats[0].name,
-				icd->formats[idx].name);
+			dev_dbg(dev, "Providing format %s using code %d\n",
+				mx3_camera_formats[0].name, code);
 		}
-		goto passthrough;
-	case V4L2_PIX_FMT_Y16:
+		break;
+	case V4L2_MBUS_FMT_Y10_1X10:
 		formats++;
 		if (xlate) {
-			xlate->host_fmt = &mx3_camera_formats[1];
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = buswidth;
+			xlate->host_fmt	= &mx3_camera_formats[1];
+			xlate->code	= code;
 			xlate++;
-			dev_dbg(icd->dev.parent,
-				"Providing format %s using %s\n",
-				mx3_camera_formats[0].name,
-				icd->formats[idx].name);
+			dev_dbg(dev, "Providing format %s using code %d\n",
+				mx3_camera_formats[1].name, code);
 		}
+		break;
 	default:
-passthrough:
-		/* Generic pass-through */
-		formats++;
-		if (xlate) {
-			xlate->host_fmt = icd->formats + idx;
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = buswidth;
-			xlate++;
-			dev_dbg(icd->dev.parent,
-				"Providing format %s in pass-through mode\n",
-				icd->formats[idx].name);
-		}
+		if (!mx3_camera_packing_supported(fmt))
+			return 0;
+	}
+
+	/* Generic pass-through */
+	formats++;
+	if (xlate) {
+		xlate->host_fmt	= fmt;
+		xlate->code	= code;
+		xlate++;
+		dev_dbg(dev, "Providing format %x in pass-through mode\n",
+			xlate->host_fmt->fourcc);
 	}
 
 	return formats;
@@ -804,8 +815,7 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
-	struct v4l2_pix_format *pix = &f.fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	int ret;
 
 	soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
@@ -816,19 +826,19 @@
 		return ret;
 
 	/* The capture device might have changed its output  */
-	ret = v4l2_subdev_call(sd, video, g_fmt, &f);
+	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
-	if (pix->width & 7) {
+	if (mf.width & 7) {
 		/* Ouch! We can only handle 8-byte aligned width... */
-		stride_align(&pix->width);
-		ret = v4l2_subdev_call(sd, video, s_fmt, &f);
+		stride_align(&mf.width);
+		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (pix->width != icd->user_width || pix->height != icd->user_height) {
+	if (mf.width != icd->user_width || mf.height != icd->user_height) {
 		/*
 		 * We now know pixel formats and can decide upon DMA-channel(s)
 		 * So far only direct camera-to-memory is supported
@@ -839,14 +849,14 @@
 				return ret;
 		}
 
-		configure_geometry(mx3_cam, pix->width, pix->height);
+		configure_geometry(mx3_cam, mf.width, mf.height);
 	}
 
 	dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
-		pix->width, pix->height);
+		mf.width, mf.height);
 
-	icd->user_width = pix->width;
-	icd->user_height = pix->height;
+	icd->user_width		= mf.width;
+	icd->user_height	= mf.height;
 
 	return ret;
 }
@@ -859,6 +869,7 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	const struct soc_camera_format_xlate *xlate;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
@@ -883,11 +894,24 @@
 
 	configure_geometry(mx3_cam, pix->width, pix->height);
 
-	ret = v4l2_subdev_call(sd, video, s_fmt, f);
-	if (!ret) {
-		icd->buswidth = xlate->buswidth;
-		icd->current_fmt = xlate->host_fmt;
-	}
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
+
+	if (mf.code != xlate->code)
+		return -EINVAL;
+
+	pix->width		= mf.width;
+	pix->height		= mf.height;
+	pix->field		= mf.field;
+	pix->colorspace		= mf.colorspace;
+	icd->current_fmt	= xlate;
 
 	dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height);
 
@@ -900,8 +924,8 @@
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	const struct soc_camera_format_xlate *xlate;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	__u32 pixfmt = pix->pixelformat;
-	enum v4l2_field field;
 	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
@@ -916,23 +940,37 @@
 	if (pix->width > 4096)
 		pix->width = 4096;
 
-	pix->bytesperline = pix->width *
-		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
+	pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+						    xlate->host_fmt);
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
 	pix->sizeimage = pix->height * pix->bytesperline;
 
-	/* camera has to see its format, but the user the original one */
-	pix->pixelformat = xlate->cam_fmt->fourcc;
 	/* limit to sensor capabilities */
-	ret = v4l2_subdev_call(sd, video, try_fmt, f);
-	pix->pixelformat = xlate->host_fmt->fourcc;
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
 
-	field = pix->field;
+	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
 
-	if (field == V4L2_FIELD_ANY) {
+	pix->width	= mf.width;
+	pix->height	= mf.height;
+	pix->colorspace	= mf.colorspace;
+
+	switch (mf.field) {
+	case V4L2_FIELD_ANY:
 		pix->field = V4L2_FIELD_NONE;
-	} else if (field != V4L2_FIELD_NONE) {
-		dev_err(icd->dev.parent, "Field type %d unsupported.\n", field);
-		return -EINVAL;
+		break;
+	case V4L2_FIELD_NONE:
+		break;
+	default:
+		dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+			mf.field);
+		ret = -EINVAL;
 	}
 
 	return ret;
@@ -968,18 +1006,26 @@
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	unsigned long bus_flags, camera_flags, common_flags;
 	u32 dw, sens_conf;
-	int ret = test_platform_param(mx3_cam, icd->buswidth, &bus_flags);
+	const struct soc_mbus_pixelfmt *fmt;
+	int buswidth;
+	int ret;
 	const struct soc_camera_format_xlate *xlate;
 	struct device *dev = icd->dev.parent;
 
+	fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
+	if (!fmt)
+		return -EINVAL;
+
+	buswidth = fmt->bits_per_sample;
+	ret = test_platform_param(mx3_cam, buswidth, &bus_flags);
+
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
 		dev_warn(dev, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
-	dev_dbg(dev, "requested bus width %d bit: %d\n",
-		icd->buswidth, ret);
+	dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret);
 
 	if (ret < 0)
 		return ret;
@@ -1027,8 +1073,10 @@
 			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
 	}
 
-	/* Make the camera work in widest common mode, we'll take care of
-	 * the rest */
+	/*
+	 * Make the camera work in widest common mode, we'll take care of
+	 * the rest
+	 */
 	if (common_flags & SOCAM_DATAWIDTH_15)
 		common_flags = (common_flags & ~SOCAM_DATAWIDTH_MASK) |
 			SOCAM_DATAWIDTH_15;
@@ -1078,7 +1126,7 @@
 		sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT;
 
 	/* Just do what we're asked to do */
-	switch (xlate->host_fmt->depth) {
+	switch (xlate->host_fmt->bits_per_sample) {
 	case 4:
 		dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT;
 		break;
@@ -1152,8 +1200,10 @@
 	if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
 			MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 |
 			MX3_CAMERA_DATAWIDTH_15))) {
-		/* Platform hasn't set available data widths. This is bad.
-		 * Warn and use a default. */
+		/*
+		 * Platform hasn't set available data widths. This is bad.
+		 * Warn and use a default.
+		 */
 		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
 			 "data widths, using default 8 bit\n");
 		mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8;
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 5fc4ac0..7400eac 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1450,12 +1450,11 @@
 
 static int omap24xxcam_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
 	struct omap24xxcam_device *cam = omap24xxcam.priv;
 	struct omap24xxcam_fh *fh;
 	struct v4l2_format format;
 
-	if (!cam || !cam->vfd || (cam->vfd->minor != minor))
+	if (!cam || !cam->vfd)
 		return -ENODEV;
 
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
@@ -1660,7 +1659,6 @@
 
 	strlcpy(vfd->name, CAM_NAME, sizeof(vfd->name));
 	vfd->fops		 = &omap24xxcam_fops;
-	vfd->minor		 = -1;
 	vfd->ioctl_ops		 = &omap24xxcam_ioctl_fops;
 
 	omap24xxcam_hwinit(cam);
@@ -1671,14 +1669,14 @@
 
 	if (video_register_device(vfd, VFL_TYPE_GRABBER, video_nr) < 0) {
 		dev_err(cam->dev, "could not register V4L device\n");
-		vfd->minor = -1;
 		rval = -EBUSY;
 		goto err;
 	}
 
 	omap24xxcam_poweron_reset(cam);
 
-	dev_info(cam->dev, "registered device video%d\n", vfd->minor);
+	dev_info(cam->dev, "registered device %s\n",
+		 video_device_node_name(vfd));
 
 	return 0;
 
@@ -1695,7 +1693,7 @@
 	omap24xxcam_sensor_exit(cam);
 
 	if (cam->vfd) {
-		if (cam->vfd->minor == -1) {
+		if (!video_is_registered(cam->vfd)) {
 			/*
 			 * The device was never registered, so release the
 			 * video_device struct directly.
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 0bc2cf5..e0bce8d 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -4674,7 +4674,6 @@
 	.name =		"OV511 USB Camera",
 	.fops =		&ov511_fops,
 	.release =	video_device_release,
-	.minor =	-1,
 };
 
 /****************************************************************************
@@ -5867,8 +5866,8 @@
 	ov511_devused |= 1 << nr;
 	ov->nr = nr;
 
-	dev_info(&intf->dev, "Device at %s registered to minor %d\n",
-		 ov->usb_path, ov->vdev->minor);
+	dev_info(&intf->dev, "Device at %s registered to %s\n",
+		 ov->usb_path, video_device_node_name(ov->vdev));
 
 	usb_set_intfdata(intf, ov);
 	if (ov_create_sysfs(ov->vdev)) {
@@ -5878,13 +5877,13 @@
 		goto error;
 	}
 
-	mutex_lock(&ov->lock);
+	mutex_unlock(&ov->lock);
 
 	return 0;
 
 error:
 	if (ov->vdev) {
-		if (-1 == ov->vdev->minor)
+		if (!video_is_registered(ov->vdev))
 			video_device_release(ov->vdev);
 		else
 			video_unregister_device(ov->vdev);
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 2052293..3a45e94 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -24,6 +24,7 @@
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-subdev.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/ov772x.h>
 
 /*
@@ -382,7 +383,8 @@
 };
 
 struct ov772x_color_format {
-	const struct soc_camera_data_format *format;
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
 	u8 dsp3;
 	u8 com3;
 	u8 com7;
@@ -399,7 +401,7 @@
 struct ov772x_priv {
 	struct v4l2_subdev                subdev;
 	struct ov772x_camera_info        *info;
-	const struct ov772x_color_format *fmt;
+	const struct ov772x_color_format *cfmt;
 	const struct ov772x_win_size     *win;
 	int                               model;
 	unsigned short                    flag_vflip:1;
@@ -434,93 +436,57 @@
 };
 
 /*
- * supported format list
- */
-
-#define SETFOURCC(type) .name = (#type), .fourcc = (V4L2_PIX_FMT_ ## type)
-static const struct soc_camera_data_format ov772x_fmt_lists[] = {
-	{
-		SETFOURCC(YUYV),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_JPEG,
-	},
-	{
-		SETFOURCC(YVYU),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_JPEG,
-	},
-	{
-		SETFOURCC(UYVY),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_JPEG,
-	},
-	{
-		SETFOURCC(RGB555),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-	},
-	{
-		SETFOURCC(RGB555X),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-	},
-	{
-		SETFOURCC(RGB565),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-	},
-	{
-		SETFOURCC(RGB565X),
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_SRGB,
-	},
-};
-
-/*
- * color format list
+ * supported color format list
  */
 static const struct ov772x_color_format ov772x_cfmts[] = {
 	{
-		.format = &ov772x_fmt_lists[0],
-		.dsp3   = 0x0,
-		.com3   = SWAP_YUV,
-		.com7   = OFMT_YUV,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= 0x0,
+		.com3		= SWAP_YUV,
+		.com7		= OFMT_YUV,
 	},
 	{
-		.format = &ov772x_fmt_lists[1],
-		.dsp3   = UV_ON,
-		.com3   = SWAP_YUV,
-		.com7   = OFMT_YUV,
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= UV_ON,
+		.com3		= SWAP_YUV,
+		.com7		= OFMT_YUV,
 	},
 	{
-		.format = &ov772x_fmt_lists[2],
-		.dsp3   = 0x0,
-		.com3   = 0x0,
-		.com7   = OFMT_YUV,
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= 0x0,
+		.com3		= 0x0,
+		.com7		= OFMT_YUV,
 	},
 	{
-		.format = &ov772x_fmt_lists[3],
-		.dsp3   = 0x0,
-		.com3   = SWAP_RGB,
-		.com7   = FMT_RGB555 | OFMT_RGB,
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.com3		= SWAP_RGB,
+		.com7		= FMT_RGB555 | OFMT_RGB,
 	},
 	{
-		.format = &ov772x_fmt_lists[4],
-		.dsp3   = 0x0,
-		.com3   = 0x0,
-		.com7   = FMT_RGB555 | OFMT_RGB,
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.com3		= 0x0,
+		.com7		= FMT_RGB555 | OFMT_RGB,
 	},
 	{
-		.format = &ov772x_fmt_lists[5],
-		.dsp3   = 0x0,
-		.com3   = SWAP_RGB,
-		.com7   = FMT_RGB565 | OFMT_RGB,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.com3		= SWAP_RGB,
+		.com7		= FMT_RGB565 | OFMT_RGB,
 	},
 	{
-		.format = &ov772x_fmt_lists[6],
-		.dsp3   = 0x0,
-		.com3   = 0x0,
-		.com7   = FMT_RGB565 | OFMT_RGB,
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.com3		= 0x0,
+		.com7		= FMT_RGB565 | OFMT_RGB,
 	},
 };
 
@@ -642,15 +608,15 @@
 		return 0;
 	}
 
-	if (!priv->win || !priv->fmt) {
+	if (!priv->win || !priv->cfmt) {
 		dev_err(&client->dev, "norm or win select error\n");
 		return -EPERM;
 	}
 
 	ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
 
-	dev_dbg(&client->dev, "format %s, win %s\n",
-		priv->fmt->format->name, priv->win->name);
+	dev_dbg(&client->dev, "format %d, win %s\n",
+		priv->cfmt->code, priv->win->name);
 
 	return 0;
 }
@@ -806,8 +772,8 @@
 	return win;
 }
 
-static int ov772x_set_params(struct i2c_client *client,
-			     u32 *width, u32 *height, u32 pixfmt)
+static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
+			     enum v4l2_mbus_pixelcode code)
 {
 	struct ov772x_priv *priv = to_ov772x(client);
 	int ret = -EINVAL;
@@ -817,14 +783,14 @@
 	/*
 	 * select format
 	 */
-	priv->fmt = NULL;
+	priv->cfmt = NULL;
 	for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
-		if (pixfmt == ov772x_cfmts[i].format->fourcc) {
-			priv->fmt = ov772x_cfmts + i;
+		if (code == ov772x_cfmts[i].code) {
+			priv->cfmt = ov772x_cfmts + i;
 			break;
 		}
 	}
-	if (!priv->fmt)
+	if (!priv->cfmt)
 		goto ov772x_set_fmt_error;
 
 	/*
@@ -894,7 +860,7 @@
 	/*
 	 * set DSP_CTRL3
 	 */
-	val = priv->fmt->dsp3;
+	val = priv->cfmt->dsp3;
 	if (val) {
 		ret = ov772x_mask_set(client,
 				      DSP_CTRL3, UV_MASK, val);
@@ -905,7 +871,7 @@
 	/*
 	 * set COM3
 	 */
-	val = priv->fmt->com3;
+	val = priv->cfmt->com3;
 	if (priv->info->flags & OV772X_FLAG_VFLIP)
 		val |= VFLIP_IMG;
 	if (priv->info->flags & OV772X_FLAG_HFLIP)
@@ -923,9 +889,9 @@
 	/*
 	 * set COM7
 	 */
-	val = priv->win->com7_bit | priv->fmt->com7;
+	val = priv->win->com7_bit | priv->cfmt->com7;
 	ret = ov772x_mask_set(client,
-			      COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
+			      COM7, SLCT_MASK | FMT_MASK | OFMT_MASK,
 			      val);
 	if (ret < 0)
 		goto ov772x_set_fmt_error;
@@ -951,7 +917,7 @@
 
 	ov772x_reset(client);
 	priv->win = NULL;
-	priv->fmt = NULL;
+	priv->cfmt = NULL;
 
 	return ret;
 }
@@ -981,54 +947,79 @@
 	return 0;
 }
 
-static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int ov772x_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct ov772x_priv *priv = to_ov772x(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (!priv->win || !priv->fmt) {
+	if (!priv->win || !priv->cfmt) {
 		u32 width = VGA_WIDTH, height = VGA_HEIGHT;
 		int ret = ov772x_set_params(client, &width, &height,
-					    V4L2_PIX_FMT_YUYV);
+					    V4L2_MBUS_FMT_YUYV8_2X8_LE);
 		if (ret < 0)
 			return ret;
 	}
 
-	f->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	pix->width		= priv->win->width;
-	pix->height		= priv->win->height;
-	pix->pixelformat	= priv->fmt->format->fourcc;
-	pix->colorspace		= priv->fmt->format->colorspace;
-	pix->field		= V4L2_FIELD_NONE;
+	mf->width	= priv->win->width;
+	mf->height	= priv->win->height;
+	mf->code	= priv->cfmt->code;
+	mf->colorspace	= priv->cfmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int ov772x_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct ov772x_priv *priv = to_ov772x(client);
+	int ret = ov772x_set_params(client, &mf->width, &mf->height,
+				    mf->code);
 
-	return ov772x_set_params(client, &pix->width, &pix->height,
-				 pix->pixelformat);
+	if (!ret)
+		mf->colorspace = priv->cfmt->colorspace;
+
+	return ret;
 }
 
 static int ov772x_try_fmt(struct v4l2_subdev *sd,
-			  struct v4l2_format *f)
+			  struct v4l2_mbus_framefmt *mf)
 {
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct i2c_client *client = sd->priv;
+	struct ov772x_priv *priv = to_ov772x(client);
 	const struct ov772x_win_size *win;
+	int i;
 
 	/*
 	 * select suitable win
 	 */
-	win = ov772x_select_win(pix->width, pix->height);
+	win = ov772x_select_win(mf->width, mf->height);
 
-	pix->width  = win->width;
-	pix->height = win->height;
-	pix->field  = V4L2_FIELD_NONE;
+	mf->width	= win->width;
+	mf->height	= win->height;
+	mf->field	= V4L2_FIELD_NONE;
+
+	for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++)
+		if (mf->code == ov772x_cfmts[i].code)
+			break;
+
+	if (i == ARRAY_SIZE(ov772x_cfmts)) {
+		/* Unsupported format requested. Propose either */
+		if (priv->cfmt) {
+			/* the current one or */
+			mf->colorspace = priv->cfmt->colorspace;
+			mf->code = priv->cfmt->code;
+		} else {
+			/* the default one */
+			mf->colorspace = ov772x_cfmts[0].colorspace;
+			mf->code = ov772x_cfmts[0].code;
+		}
+	} else {
+		/* Also return the colorspace */
+		mf->colorspace	= ov772x_cfmts[i].colorspace;
+	}
 
 	return 0;
 }
@@ -1057,9 +1048,6 @@
 		return -ENODEV;
 	}
 
-	icd->formats     = ov772x_fmt_lists;
-	icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
@@ -1109,13 +1097,24 @@
 #endif
 };
 
+static int ov772x_enum_fmt(struct v4l2_subdev *sd, int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(ov772x_cfmts))
+		return -EINVAL;
+
+	*code = ov772x_cfmts[index].code;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
 	.s_stream	= ov772x_s_stream,
-	.g_fmt		= ov772x_g_fmt,
-	.s_fmt		= ov772x_s_fmt,
-	.try_fmt	= ov772x_try_fmt,
+	.g_mbus_fmt	= ov772x_g_fmt,
+	.s_mbus_fmt	= ov772x_s_fmt,
+	.try_mbus_fmt	= ov772x_try_fmt,
 	.cropcap	= ov772x_cropcap,
 	.g_crop		= ov772x_g_crop,
+	.enum_mbus_fmt	= ov772x_enum_fmt,
 };
 
 static struct v4l2_subdev_ops ov772x_subdev_ops = {
@@ -1143,10 +1142,10 @@
 	}
 
 	icl = to_soc_camera_link(icd);
-	if (!icl)
+	if (!icl || !icl->priv)
 		return -EINVAL;
 
-	info = container_of(icl, struct ov772x_camera_info, link);
+	info = icl->priv;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&adapter->dev,
diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c
index c81ae219..47bf60c 100644
--- a/drivers/media/video/ov9640.c
+++ b/drivers/media/video/ov9640.c
@@ -154,19 +154,10 @@
 	{ OV9640_MTXS,	0x65 },
 };
 
-/*
- * TODO: this sensor also supports RGB555 and RGB565 formats, but support for
- * them has not yet been sufficiently tested and so it is not included with
- * this version of the driver. To test and debug these formats add two entries
- * to the below array, see ov722x.c for an example.
- */
-static const struct soc_camera_data_format ov9640_fmt_lists[] = {
-	{
-		.name		= "UYVY",
-		.fourcc		= V4L2_PIX_FMT_UYVY,
-		.depth		= 16,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
-	},
+static enum v4l2_mbus_pixelcode ov9640_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8_BE,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
 };
 
 static const struct v4l2_queryctrl ov9640_controls[] = {
@@ -434,20 +425,22 @@
 }
 
 /* Prepare necessary register changes depending on color encoding */
-static void ov9640_alter_regs(u32 pixfmt, struct ov9640_reg_alt *alt)
+static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
+			      struct ov9640_reg_alt *alt)
 {
-	switch (pixfmt) {
-	case V4L2_PIX_FMT_UYVY:
+	switch (code) {
+	default:
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
 		alt->com12	= OV9640_COM12_YUV_AVG;
 		alt->com13	= OV9640_COM13_Y_DELAY_EN |
 					OV9640_COM13_YUV_DLY(0x01);
 		break;
-	case V4L2_PIX_FMT_RGB555:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
 		alt->com7	= OV9640_COM7_RGB;
 		alt->com13	= OV9640_COM13_RGB_AVG;
 		alt->com15	= OV9640_COM15_RGB_555;
 		break;
-	case V4L2_PIX_FMT_RGB565:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		alt->com7	= OV9640_COM7_RGB;
 		alt->com13	= OV9640_COM13_RGB_AVG;
 		alt->com15	= OV9640_COM15_RGB_565;
@@ -456,8 +449,8 @@
 }
 
 /* Setup registers according to resolution and color encoding */
-static int ov9640_write_regs(struct i2c_client *client,
-		u32 width, u32 pixfmt, struct ov9640_reg_alt *alts)
+static int ov9640_write_regs(struct i2c_client *client, u32 width,
+		enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts)
 {
 	const struct ov9640_reg	*ov9640_regs, *matrix_regs;
 	int			ov9640_regs_len, matrix_regs_len;
@@ -500,7 +493,7 @@
 	}
 
 	/* select color matrix configuration for given color encoding */
-	if (pixfmt == V4L2_PIX_FMT_UYVY) {
+	if (code == V4L2_MBUS_FMT_YUYV8_2X8_BE) {
 		matrix_regs	= ov9640_regs_yuv;
 		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_yuv);
 	} else {
@@ -562,15 +555,17 @@
 }
 
 /* set the format we will capture in */
-static int ov9640_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int ov9640_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct ov9640_reg_alt alts = {0};
+	enum v4l2_colorspace cspace;
+	enum v4l2_mbus_pixelcode code = mf->code;
 	int ret;
 
-	ov9640_res_roundup(&pix->width, &pix->height);
-	ov9640_alter_regs(pix->pixelformat, &alts);
+	ov9640_res_roundup(&mf->width, &mf->height);
+	ov9640_alter_regs(mf->code, &alts);
 
 	ov9640_reset(client);
 
@@ -578,16 +573,54 @@
 	if (ret)
 		return ret;
 
-	return ov9640_write_regs(client, pix->width, pix->pixelformat, &alts);
+	switch (code) {
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		cspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		code = V4L2_MBUS_FMT_YUYV8_2X8_BE;
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
+		cspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	ret = ov9640_write_regs(client, mf->width, code, &alts);
+	if (!ret) {
+		mf->code	= code;
+		mf->colorspace	= cspace;
+	}
+
+	return ret;
 }
 
-static int ov9640_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int ov9640_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
 {
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	ov9640_res_roundup(&mf->width, &mf->height);
 
-	ov9640_res_roundup(&pix->width, &pix->height);
-	pix->field  = V4L2_FIELD_NONE;
+	mf->field = V4L2_FIELD_NONE;
 
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE;
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	return 0;
+}
+
+static int ov9640_enum_fmt(struct v4l2_subdev *sd, int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(ov9640_codes))
+		return -EINVAL;
+
+	*code = ov9640_codes[index];
 	return 0;
 }
 
@@ -637,9 +670,6 @@
 		goto err;
 	}
 
-	icd->formats		= ov9640_fmt_lists;
-	icd->num_formats	= ARRAY_SIZE(ov9640_fmt_lists);
-
 	/*
 	 * check and show product ID and manufacturer ID
 	 */
@@ -702,11 +732,12 @@
 };
 
 static struct v4l2_subdev_video_ops ov9640_video_ops = {
-	.s_stream		= ov9640_s_stream,
-	.s_fmt			= ov9640_s_fmt,
-	.try_fmt		= ov9640_try_fmt,
-	.cropcap		= ov9640_cropcap,
-	.g_crop			= ov9640_g_crop,
+	.s_stream	= ov9640_s_stream,
+	.s_mbus_fmt	= ov9640_s_fmt,
+	.try_mbus_fmt	= ov9640_try_fmt,
+	.enum_mbus_fmt	= ov9640_enum_fmt,
+	.cropcap	= ov9640_cropcap,
+	.g_crop		= ov9640_g_crop,
 
 };
 
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 73ec970..11a2c26 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/videodev2.h>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 6aa48e0..cc8ddb2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -151,17 +151,6 @@
 };
 
 
-static const char *get_v4l_name(int v4l_type)
-{
-	switch (v4l_type) {
-	case VFL_TYPE_GRABBER: return "video";
-	case VFL_TYPE_RADIO: return "radio";
-	case VFL_TYPE_VBI: return "vbi";
-	default: return "?";
-	}
-}
-
-
 /*
  * pvr_ioctl()
  *
@@ -891,10 +880,8 @@
 
 static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
 {
-	int num = dip->devbase.num;
 	struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
 	enum pvr2_config cfg = dip->config;
-	int v4l_type = dip->v4l_type;
 
 	pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
 
@@ -906,8 +893,8 @@
 	   are gone. */
 	video_unregister_device(&dip->devbase);
 
-	printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
-	       get_v4l_name(v4l_type), num,
+	printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n",
+	       video_device_node_name(&dip->devbase),
 	       pvr2_config_get_name(cfg));
 
 }
@@ -1317,8 +1304,8 @@
 			": Failed to register pvrusb2 v4l device\n");
 	}
 
-	printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
-	       get_v4l_name(dip->v4l_type), dip->devbase.num,
+	printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
+	       video_device_node_name(&dip->devbase),
 	       pvr2_config_get_name(dip->config));
 
 	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 89b620f..aea7e22 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -169,7 +169,6 @@
 	.name =		"Philips Webcam",	/* Filled in later */
 	.release =	video_device_release,
 	.fops =         &pwc_fops,
-	.minor =        -1,
 };
 
 /***************************************************************************/
@@ -1807,7 +1806,7 @@
 		goto err_video_release;
 	}
 
-	PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num);
+	PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
 
 	/* occupy slot */
 	if (hint < MAX_DEV_HINTS)
@@ -1948,7 +1947,9 @@
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
 MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+#ifdef CONFIG_USB_PWC_DEBUG
 MODULE_PARM_DESC(trace, "For debugging purposes");
+#endif
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 51b683c..294f860 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -32,6 +32,7 @@
 #include <media/v4l2-dev.h>
 #include <media/videobuf-dma-sg.h>
 #include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 
 #include <linux/videodev2.h>
 
@@ -183,23 +184,21 @@
 /* buffer for one video frame */
 struct pxa_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
-
-	const struct soc_camera_data_format        *fmt;
-
+	struct videobuf_buffer		vb;
+	enum v4l2_mbus_pixelcode	code;
 	/* our descriptor lists for Y, U and V channels */
-	struct pxa_cam_dma dmas[3];
-
-	int			inwork;
-
-	enum pxa_camera_active_dma active_dma;
+	struct pxa_cam_dma		dmas[3];
+	int				inwork;
+	enum pxa_camera_active_dma	active_dma;
 };
 
 struct pxa_camera_dev {
 	struct soc_camera_host	soc_host;
-	/* PXA27x is only supposed to handle one camera on its Quick Capture
+	/*
+	 * PXA27x is only supposed to handle one camera on its Quick Capture
 	 * interface. If anyone ever builds hardware to enable more than
-	 * one camera, they will have to modify this driver too */
+	 * one camera, they will have to modify this driver too
+	 */
 	struct soc_camera_device *icd;
 	struct clk		*clk;
 
@@ -241,11 +240,15 @@
 			      unsigned int *size)
 {
 	struct soc_camera_device *icd = vq->priv_data;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
 
 	dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
 
-	*size = roundup(icd->user_width * icd->user_height *
-			((icd->current_fmt->depth + 7) >> 3), 8);
+	*size = bytes_per_line * icd->user_height;
 
 	if (0 == *count)
 		*count = 32;
@@ -267,8 +270,10 @@
 	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		&buf->vb, buf->vb.baddr, buf->vb.bsize);
 
-	/* This waits until this buffer is out of danger, i.e., until it is no
-	 * longer in STATE_QUEUED or STATE_ACTIVE */
+	/*
+	 * This waits until this buffer is out of danger, i.e., until it is no
+	 * longer in STATE_QUEUED or STATE_ACTIVE
+	 */
 	videobuf_waiton(&buf->vb, 0, 0);
 	videobuf_dma_unmap(vq, dma);
 	videobuf_dma_free(dma);
@@ -429,6 +434,11 @@
 	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
 	int ret;
 	int size_y, size_u = 0, size_v = 0;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
 
 	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
 		vb, vb->baddr, vb->bsize);
@@ -437,29 +447,33 @@
 	WARN_ON(!list_empty(&vb->queue));
 
 #ifdef DEBUG
-	/* This can be useful if you want to see if we actually fill
-	 * the buffer with something */
+	/*
+	 * This can be useful if you want to see if we actually fill
+	 * the buffer with something
+	 */
 	memset((void *)vb->baddr, 0xaa, vb->bsize);
 #endif
 
 	BUG_ON(NULL == icd->current_fmt);
 
-	/* I think, in buf_prepare you only have to protect global data,
-	 * the actual buffer is yours */
+	/*
+	 * I think, in buf_prepare you only have to protect global data,
+	 * the actual buffer is yours
+	 */
 	buf->inwork = 1;
 
-	if (buf->fmt	!= icd->current_fmt ||
+	if (buf->code	!= icd->current_fmt->code ||
 	    vb->width	!= icd->user_width ||
 	    vb->height	!= icd->user_height ||
 	    vb->field	!= field) {
-		buf->fmt	= icd->current_fmt;
+		buf->code	= icd->current_fmt->code;
 		vb->width	= icd->user_width;
 		vb->height	= icd->user_height;
 		vb->field	= field;
 		vb->state	= VIDEOBUF_NEEDS_INIT;
 	}
 
-	vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+	vb->size = bytes_per_line * vb->height;
 	if (0 != vb->baddr && vb->bsize < vb->size) {
 		ret = -EINVAL;
 		goto out;
@@ -834,8 +848,10 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
 
-	/* We must pass NULL as dev pointer, then all pci_* dma operations
-	 * transform to normal dma_* ones. */
+	/*
+	 * We must pass NULL as dev pointer, then all pci_* dma operations
+	 * transform to normal dma_* ones.
+	 */
 	videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
 				sizeof(struct pxa_buffer), icd);
@@ -1051,11 +1067,18 @@
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	unsigned long dw, bpp;
-	u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0;
+	u32 cicr0, cicr1, cicr2, cicr3, cicr4 = 0, y_skip_top;
+	int ret = v4l2_subdev_call(sd, sensor, g_skip_top_lines, &y_skip_top);
 
-	/* Datawidth is now guaranteed to be equal to one of the three values.
-	 * We fix bit-per-pixel equal to data-width... */
+	if (ret < 0)
+		y_skip_top = 0;
+
+	/*
+	 * Datawidth is now guaranteed to be equal to one of the three values.
+	 * We fix bit-per-pixel equal to data-width...
+	 */
 	switch (flags & SOCAM_DATAWIDTH_MASK) {
 	case SOCAM_DATAWIDTH_10:
 		dw = 4;
@@ -1066,8 +1089,10 @@
 		bpp = 0x20;
 		break;
 	default:
-		/* Actually it can only be 8 now,
-		 * default is just to silence compiler warnings */
+		/*
+		 * Actually it can only be 8 now,
+		 * default is just to silence compiler warnings
+		 */
 	case SOCAM_DATAWIDTH_8:
 		dw = 2;
 		bpp = 0;
@@ -1118,7 +1143,7 @@
 
 	cicr2 = 0;
 	cicr3 = CICR3_LPF_VAL(icd->user_height - 1) |
-		CICR3_BFW_VAL(min((unsigned short)255, icd->y_skip_top));
+		CICR3_BFW_VAL(min((u32)255, y_skip_top));
 	cicr4 |= pcdev->mclk_divisor;
 
 	__raw_writel(cicr1, pcdev->base + CICR1);
@@ -1138,9 +1163,15 @@
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct pxa_camera_dev *pcdev = ici->priv;
 	unsigned long bus_flags, camera_flags, common_flags;
-	int ret = test_platform_param(pcdev, icd->buswidth, &bus_flags);
+	const struct soc_mbus_pixelfmt *fmt;
+	int ret;
 	struct pxa_cam *cam = icd->host_priv;
 
+	fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code);
+	if (!fmt)
+		return -EINVAL;
+
+	ret = test_platform_param(pcdev, fmt->bits_per_sample, &bus_flags);
 	if (ret < 0)
 		return ret;
 
@@ -1204,59 +1235,49 @@
 	return soc_camera_bus_param_compatible(camera_flags, bus_flags) ? 0 : -EINVAL;
 }
 
-static const struct soc_camera_data_format pxa_camera_formats[] = {
+static const struct soc_mbus_pixelfmt pxa_camera_formats[] = {
 	{
-		.name		= "Planar YUV422 16 bit",
-		.depth		= 16,
-		.fourcc		= V4L2_PIX_FMT_YUV422P,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fourcc			= V4L2_PIX_FMT_YUV422P,
+		.name			= "Planar YUV422 16 bit",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
 	},
 };
 
-static bool buswidth_supported(struct soc_camera_device *icd, int depth)
+/* This will be corrected as we get more formats */
+static bool pxa_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt)
 {
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct pxa_camera_dev *pcdev = ici->priv;
-
-	switch (depth) {
-	case 8:
-		return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8);
-	case 9:
-		return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_9);
-	case 10:
-		return !!(pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_10);
-	}
-	return false;
-}
-
-static int required_buswidth(const struct soc_camera_data_format *fmt)
-{
-	switch (fmt->fourcc) {
-	case V4L2_PIX_FMT_UYVY:
-	case V4L2_PIX_FMT_VYUY:
-	case V4L2_PIX_FMT_YUYV:
-	case V4L2_PIX_FMT_YVYU:
-	case V4L2_PIX_FMT_RGB565:
-	case V4L2_PIX_FMT_RGB555:
-		return 8;
-	default:
-		return fmt->depth;
-	}
+	return	fmt->packing == SOC_MBUS_PACKING_NONE ||
+		(fmt->bits_per_sample == 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
+		(fmt->bits_per_sample > 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
 }
 
 static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
 				  struct soc_camera_format_xlate *xlate)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->dev.parent;
-	int formats = 0, buswidth, ret;
+	int formats = 0, ret;
 	struct pxa_cam *cam;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *fmt;
 
-	buswidth = required_buswidth(icd->formats + idx);
-
-	if (!buswidth_supported(icd, buswidth))
+	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+	if (ret < 0)
+		/* No more formats */
 		return 0;
 
-	ret = pxa_camera_try_bus_param(icd, buswidth);
+	fmt = soc_mbus_get_fmtdesc(code);
+	if (!fmt) {
+		dev_err(dev, "Invalid format code #%d: %d\n", idx, code);
+		return 0;
+	}
+
+	/* This also checks support for the requested bits-per-sample */
+	ret = pxa_camera_try_bus_param(icd, fmt->bits_per_sample);
 	if (ret < 0)
 		return 0;
 
@@ -1270,45 +1291,40 @@
 		cam = icd->host_priv;
 	}
 
-	switch (icd->formats[idx].fourcc) {
-	case V4L2_PIX_FMT_UYVY:
+	switch (code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
 		formats++;
 		if (xlate) {
-			xlate->host_fmt = &pxa_camera_formats[0];
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = buswidth;
+			xlate->host_fmt	= &pxa_camera_formats[0];
+			xlate->code	= code;
 			xlate++;
-			dev_dbg(dev, "Providing format %s using %s\n",
-				pxa_camera_formats[0].name,
-				icd->formats[idx].name);
+			dev_dbg(dev, "Providing format %s using code %d\n",
+				pxa_camera_formats[0].name, code);
 		}
-	case V4L2_PIX_FMT_VYUY:
-	case V4L2_PIX_FMT_YUYV:
-	case V4L2_PIX_FMT_YVYU:
-	case V4L2_PIX_FMT_RGB565:
-	case V4L2_PIX_FMT_RGB555:
-		formats++;
-		if (xlate) {
-			xlate->host_fmt = icd->formats + idx;
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = buswidth;
-			xlate++;
+	case V4L2_MBUS_FMT_YVYU8_2X8_BE:
+	case V4L2_MBUS_FMT_YUYV8_2X8_LE:
+	case V4L2_MBUS_FMT_YVYU8_2X8_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+		if (xlate)
 			dev_dbg(dev, "Providing format %s packed\n",
-				icd->formats[idx].name);
-		}
+				fmt->name);
 		break;
 	default:
-		/* Generic pass-through */
-		formats++;
-		if (xlate) {
-			xlate->host_fmt = icd->formats + idx;
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = icd->formats[idx].depth;
-			xlate++;
+		if (!pxa_camera_packing_supported(fmt))
+			return 0;
+		if (xlate)
 			dev_dbg(dev,
 				"Providing format %s in pass-through mode\n",
-				icd->formats[idx].name);
-		}
+				fmt->name);
+	}
+
+	/* Generic pass-through */
+	formats++;
+	if (xlate) {
+		xlate->host_fmt	= fmt;
+		xlate->code	= code;
+		xlate++;
 	}
 
 	return formats;
@@ -1320,11 +1336,11 @@
 	icd->host_priv = NULL;
 }
 
-static int pxa_camera_check_frame(struct v4l2_pix_format *pix)
+static int pxa_camera_check_frame(u32 width, u32 height)
 {
 	/* limit to pxa hardware capabilities */
-	return pix->height < 32 || pix->height > 2048 || pix->width < 48 ||
-		pix->width > 2048 || (pix->width & 0x01);
+	return height < 32 || height > 2048 || width < 48 || width > 2048 ||
+		(width & 0x01);
 }
 
 static int pxa_camera_set_crop(struct soc_camera_device *icd,
@@ -1339,9 +1355,9 @@
 		.master_clock = pcdev->mclk,
 		.pixel_clock_max = pcdev->ciclk / 4,
 	};
-	struct v4l2_format f;
-	struct v4l2_pix_format *pix = &f.fmt.pix, pix_tmp;
+	struct v4l2_mbus_framefmt mf;
 	struct pxa_cam *cam = icd->host_priv;
+	u32 fourcc = icd->current_fmt->host_fmt->fourcc;
 	int ret;
 
 	/* If PCLK is used to latch data from the sensor, check sense */
@@ -1358,27 +1374,23 @@
 		return ret;
 	}
 
-	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	ret = v4l2_subdev_call(sd, video, g_fmt, &f);
+	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
-	pix_tmp = *pix;
-	if (pxa_camera_check_frame(pix)) {
+	if (pxa_camera_check_frame(mf.width, mf.height)) {
 		/*
 		 * Camera cropping produced a frame beyond our capabilities.
 		 * FIXME: just extract a subframe, that we can process.
 		 */
-		v4l_bound_align_image(&pix->width, 48, 2048, 1,
-			&pix->height, 32, 2048, 0,
-			icd->current_fmt->fourcc == V4L2_PIX_FMT_YUV422P ?
-				4 : 0);
-		ret = v4l2_subdev_call(sd, video, s_fmt, &f);
+		v4l_bound_align_image(&mf.width, 48, 2048, 1,
+			&mf.height, 32, 2048, 0,
+			fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
+		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
 		if (ret < 0)
 			return ret;
 
-		if (pxa_camera_check_frame(pix)) {
+		if (pxa_camera_check_frame(mf.width, mf.height)) {
 			dev_warn(icd->dev.parent,
 				 "Inconsistent state. Use S_FMT to repair\n");
 			return -EINVAL;
@@ -1395,10 +1407,10 @@
 		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
 	}
 
-	icd->user_width = pix->width;
-	icd->user_height = pix->height;
+	icd->user_width		= mf.width;
+	icd->user_height	= mf.height;
 
-	pxa_camera_setup_cicr(icd, cam->flags, icd->current_fmt->fourcc);
+	pxa_camera_setup_cicr(icd, cam->flags, fourcc);
 
 	return ret;
 }
@@ -1410,14 +1422,13 @@
 	struct pxa_camera_dev *pcdev = ici->priv;
 	struct device *dev = icd->dev.parent;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-	const struct soc_camera_data_format *cam_fmt = NULL;
 	const struct soc_camera_format_xlate *xlate = NULL;
 	struct soc_camera_sense sense = {
 		.master_clock = pcdev->mclk,
 		.pixel_clock_max = pcdev->ciclk / 4,
 	};
 	struct v4l2_pix_format *pix = &f->fmt.pix;
-	struct v4l2_format cam_f = *f;
+	struct v4l2_mbus_framefmt mf;
 	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
@@ -1426,26 +1437,31 @@
 		return -EINVAL;
 	}
 
-	cam_fmt = xlate->cam_fmt;
-
 	/* If PCLK is used to latch data from the sensor, check sense */
 	if (pcdev->platform_flags & PXA_CAMERA_PCLK_EN)
+		/* The caller holds a mutex. */
 		icd->sense = &sense;
 
-	cam_f.fmt.pix.pixelformat = cam_fmt->fourcc;
-	ret = v4l2_subdev_call(sd, video, s_fmt, &cam_f);
-	cam_f.fmt.pix.pixelformat = pix->pixelformat;
-	*pix = cam_f.fmt.pix;
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+
+	if (mf.code != xlate->code)
+		return -EINVAL;
 
 	icd->sense = NULL;
 
 	if (ret < 0) {
 		dev_warn(dev, "Failed to configure for format %x\n",
 			 pix->pixelformat);
-	} else if (pxa_camera_check_frame(pix)) {
+	} else if (pxa_camera_check_frame(mf.width, mf.height)) {
 		dev_warn(dev,
 			 "Camera driver produced an unsupported frame %dx%d\n",
-			 pix->width, pix->height);
+			 mf.width, mf.height);
 		ret = -EINVAL;
 	} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
 		if (sense.pixel_clock > sense.pixel_clock_max) {
@@ -1457,10 +1473,14 @@
 		recalculate_fifo_timeout(pcdev, sense.pixel_clock);
 	}
 
-	if (!ret) {
-		icd->buswidth = xlate->buswidth;
-		icd->current_fmt = xlate->host_fmt;
-	}
+	if (ret < 0)
+		return ret;
+
+	pix->width		= mf.width;
+	pix->height		= mf.height;
+	pix->field		= mf.field;
+	pix->colorspace		= mf.colorspace;
+	icd->current_fmt	= xlate;
 
 	return ret;
 }
@@ -1468,17 +1488,16 @@
 static int pxa_camera_try_fmt(struct soc_camera_device *icd,
 			      struct v4l2_format *f)
 {
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	const struct soc_camera_format_xlate *xlate;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	__u32 pixfmt = pix->pixelformat;
-	enum v4l2_field field;
 	int ret;
 
 	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
 	if (!xlate) {
-		dev_warn(ici->v4l2_dev.dev, "Format %x not found\n", pixfmt);
+		dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
 		return -EINVAL;
 	}
 
@@ -1492,22 +1511,36 @@
 			      &pix->height, 32, 2048, 0,
 			      pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
 
-	pix->bytesperline = pix->width *
-		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
+	pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+						    xlate->host_fmt);
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
 	pix->sizeimage = pix->height * pix->bytesperline;
 
-	/* camera has to see its format, but the user the original one */
-	pix->pixelformat = xlate->cam_fmt->fourcc;
 	/* limit to sensor capabilities */
-	ret = v4l2_subdev_call(sd, video, try_fmt, f);
-	pix->pixelformat = pixfmt;
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
 
-	field = pix->field;
+	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
 
-	if (field == V4L2_FIELD_ANY) {
-		pix->field = V4L2_FIELD_NONE;
-	} else if (field != V4L2_FIELD_NONE) {
-		dev_err(icd->dev.parent, "Field type %d unsupported.\n", field);
+	pix->width	= mf.width;
+	pix->height	= mf.height;
+	pix->colorspace	= mf.colorspace;
+
+	switch (mf.field) {
+	case V4L2_FIELD_ANY:
+	case V4L2_FIELD_NONE:
+		pix->field	= V4L2_FIELD_NONE;
+		break;
+	default:
+		/* TODO: support interlaced at least in pass-through mode */
+		dev_err(icd->dev.parent, "Field type %d unsupported.\n",
+			mf.field);
 		return -EINVAL;
 	}
 
@@ -1519,10 +1552,12 @@
 {
 	int i;
 
-	/* This is for locking debugging only. I removed spinlocks and now I
+	/*
+	 * This is for locking debugging only. I removed spinlocks and now I
 	 * check whether .prepare is ever called on a linked buffer, or whether
 	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-	 * it hadn't triggered */
+	 * it hadn't triggered
+	 */
 	for (i = 0; i < p->count; i++) {
 		struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i],
 						      struct pxa_buffer, vb);
@@ -1657,8 +1692,10 @@
 	pcdev->platform_flags = pcdev->pdata->flags;
 	if (!(pcdev->platform_flags & (PXA_CAMERA_DATAWIDTH_8 |
 			PXA_CAMERA_DATAWIDTH_9 | PXA_CAMERA_DATAWIDTH_10))) {
-		/* Platform hasn't set available data widths. This is bad.
-		 * Warn and use a default. */
+		/*
+		 * Platform hasn't set available data widths. This is bad.
+		 * Warn and use a default.
+		 */
 		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
 			 "data widths, using default 10 bit\n");
 		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c
index 373f2a3..7e42989 100644
--- a/drivers/media/video/rj54n1cb0c.c
+++ b/drivers/media/video/rj54n1cb0c.c
@@ -13,9 +13,11 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 
+#include <media/rj54n1cb0c.h>
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
-#include <media/soc_camera.h>
 
 #define RJ54N1_DEV_CODE			0x0400
 #define RJ54N1_DEV_CODE2		0x0401
@@ -38,6 +40,7 @@
 #define RJ54N1_H_OBEN_OFS		0x0413
 #define RJ54N1_V_OBEN_OFS		0x0414
 #define RJ54N1_RESIZE_CONTROL		0x0415
+#define RJ54N1_STILL_CONTROL		0x0417
 #define RJ54N1_INC_USE_SEL_H		0x0425
 #define RJ54N1_INC_USE_SEL_L		0x0426
 #define RJ54N1_MIRROR_STILL_MODE	0x0427
@@ -49,10 +52,21 @@
 #define RJ54N1_RA_SEL_UL		0x0530
 #define RJ54N1_BYTE_SWAP		0x0531
 #define RJ54N1_OUT_SIGPO		0x053b
+#define RJ54N1_WB_SEL_WEIGHT_I		0x054e
+#define RJ54N1_BIT8_WB			0x0569
+#define RJ54N1_HCAPS_WB			0x056a
+#define RJ54N1_VCAPS_WB			0x056b
+#define RJ54N1_HCAPE_WB			0x056c
+#define RJ54N1_VCAPE_WB			0x056d
+#define RJ54N1_EXPOSURE_CONTROL		0x058c
 #define RJ54N1_FRAME_LENGTH_S_H		0x0595
 #define RJ54N1_FRAME_LENGTH_S_L		0x0596
 #define RJ54N1_FRAME_LENGTH_P_H		0x0597
 #define RJ54N1_FRAME_LENGTH_P_L		0x0598
+#define RJ54N1_PEAK_H			0x05b7
+#define RJ54N1_PEAK_50			0x05b8
+#define RJ54N1_PEAK_60			0x05b9
+#define RJ54N1_PEAK_DIFF		0x05ba
 #define RJ54N1_IOC			0x05ef
 #define RJ54N1_TG_BYPASS		0x0700
 #define RJ54N1_PLL_L			0x0701
@@ -68,6 +82,7 @@
 #define RJ54N1_OCLK_SEL_EN		0x0713
 #define RJ54N1_CLK_RST			0x0717
 #define RJ54N1_RESET_STANDBY		0x0718
+#define RJ54N1_FWFLG			0x07fe
 
 #define E_EXCLK				(1 << 7)
 #define SOFT_STDBY			(1 << 4)
@@ -78,29 +93,53 @@
 #define RESIZE_HOLD_SEL			(1 << 2)
 #define RESIZE_GO			(1 << 1)
 
+/*
+ * When cropping, the camera automatically centers the cropped region, there
+ * doesn't seem to be a way to specify an explicit location of the rectangle.
+ */
 #define RJ54N1_COLUMN_SKIP		0
 #define RJ54N1_ROW_SKIP			0
 #define RJ54N1_MAX_WIDTH		1600
 #define RJ54N1_MAX_HEIGHT		1200
 
+#define PLL_L				2
+#define PLL_N				0x31
+
 /* I2C addresses: 0x50, 0x51, 0x60, 0x61 */
 
-static const struct soc_camera_data_format rj54n1_colour_formats[] = {
-	{
-		.name		= "YUYV",
-		.depth		= 16,
-		.fourcc		= V4L2_PIX_FMT_YUYV,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
-	}, {
-		.name		= "RGB565",
-		.depth		= 16,
-		.fourcc		= V4L2_PIX_FMT_RGB565,
-		.colorspace	= V4L2_COLORSPACE_SRGB,
-	}
+/* RJ54N1CB0C has only one fixed colorspace per pixelcode */
+struct rj54n1_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+/* Find a data format by a pixel code in an array */
+static const struct rj54n1_datafmt *rj54n1_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
+	{V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
 };
 
 struct rj54n1_clock_div {
-	u8 ratio_tg;
+	u8 ratio_tg;	/* can be 0 or an odd number */
 	u8 ratio_t;
 	u8 ratio_r;
 	u8 ratio_op;
@@ -109,12 +148,14 @@
 
 struct rj54n1 {
 	struct v4l2_subdev subdev;
+	struct rj54n1_clock_div clk_div;
+	const struct rj54n1_datafmt *fmt;
 	struct v4l2_rect rect;	/* Sensor window */
+	unsigned int tgclk_mhz;
+	bool auto_wb;
 	unsigned short width;	/* Output window */
 	unsigned short height;
 	unsigned short resize;	/* Sensor * 1024 / resize = Output */
-	struct rj54n1_clock_div clk_div;
-	u32 fourcc;
 	unsigned short scale;
 	u8 bank;
 };
@@ -171,7 +212,7 @@
 	{0x714, 0xff},
 	{0x715, 0xff},
 	{0x716, 0x1f},
-	{0x7FE, 0x02},
+	{0x7FE, 2},
 };
 
 const static struct rj54n1_reg_val bank_8[] = {
@@ -359,7 +400,7 @@
 	{0x8BB, 0x00},
 	{0x8BC, 0xFF},
 	{0x8BD, 0x00},
-	{0x8FE, 0x02},
+	{0x8FE, 2},
 };
 
 const static struct rj54n1_reg_val bank_10[] = {
@@ -440,10 +481,22 @@
 	return 0;
 }
 
+static int rj54n1_enum_fmt(struct v4l2_subdev *sd, int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(rj54n1_colour_fmts))
+		return -EINVAL;
+
+	*code = rj54n1_colour_fmts[index].code;
+	return 0;
+}
+
 static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable)
 {
-	/* TODO: start / stop streaming */
-	return 0;
+	struct i2c_client *client = sd->priv;
+
+	/* Switch between preview and still shot modes */
+	return reg_set(client, RJ54N1_STILL_CONTROL, (!enable) << 7, 0x80);
 }
 
 static int rj54n1_set_bus_param(struct soc_camera_device *icd,
@@ -502,6 +555,44 @@
 	return ret;
 }
 
+static int rj54n1_sensor_scale(struct v4l2_subdev *sd, u32 *in_w, u32 *in_h,
+			       u32 *out_w, u32 *out_h);
+
+static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = sd->priv;
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	struct v4l2_rect *rect = &a->c;
+	unsigned int dummy, output_w, output_h,
+		input_w = rect->width, input_h = rect->height;
+	int ret;
+
+	/* arbitrary minimum width and height, edges unimportant */
+	soc_camera_limit_side(&dummy, &input_w,
+		     RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH);
+
+	soc_camera_limit_side(&dummy, &input_h,
+		     RJ54N1_ROW_SKIP, 8, RJ54N1_MAX_HEIGHT);
+
+	output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize;
+	output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize;
+
+	dev_dbg(&client->dev, "Scaling for %ux%u : %u = %ux%u\n",
+		input_w, input_h, rj54n1->resize, output_w, output_h);
+
+	ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h);
+	if (ret < 0)
+		return ret;
+
+	rj54n1->width		= output_w;
+	rj54n1->height		= output_h;
+	rj54n1->resize		= ret;
+	rj54n1->rect.width	= input_w;
+	rj54n1->rect.height	= input_h;
+
+	return 0;
+}
+
 static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
 	struct i2c_client *client = sd->priv;
@@ -527,16 +618,17 @@
 	return 0;
 }
 
-static int rj54n1_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int rj54n1_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct rj54n1 *rj54n1 = to_rj54n1(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->pixelformat	= rj54n1->fourcc;
-	pix->field		= V4L2_FIELD_NONE;
-	pix->width		= rj54n1->width;
-	pix->height		= rj54n1->height;
+	mf->code	= rj54n1->fmt->code;
+	mf->colorspace	= rj54n1->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+	mf->width	= rj54n1->width;
+	mf->height	= rj54n1->height;
 
 	return 0;
 }
@@ -550,11 +642,44 @@
 			       u32 *out_w, u32 *out_h)
 {
 	struct i2c_client *client = sd->priv;
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
 	unsigned int skip, resize, input_w = *in_w, input_h = *in_h,
 		output_w = *out_w, output_h = *out_h;
-	u16 inc_sel;
+	u16 inc_sel, wb_bit8, wb_left, wb_right, wb_top, wb_bottom;
+	unsigned int peak, peak_50, peak_60;
 	int ret;
 
+	/*
+	 * We have a problem with crops, where the window is larger than 512x384
+	 * and output window is larger than a half of the input one. In this
+	 * case we have to either reduce the input window to equal or below
+	 * 512x384 or the output window to equal or below 1/2 of the input.
+	 */
+	if (output_w > max(512U, input_w / 2)) {
+		if (2 * output_w > RJ54N1_MAX_WIDTH) {
+			input_w = RJ54N1_MAX_WIDTH;
+			output_w = RJ54N1_MAX_WIDTH / 2;
+		} else {
+			input_w = output_w * 2;
+		}
+
+		dev_dbg(&client->dev, "Adjusted output width: in %u, out %u\n",
+			input_w, output_w);
+	}
+
+	if (output_h > max(384U, input_h / 2)) {
+		if (2 * output_h > RJ54N1_MAX_HEIGHT) {
+			input_h = RJ54N1_MAX_HEIGHT;
+			output_h = RJ54N1_MAX_HEIGHT / 2;
+		} else {
+			input_h = output_h * 2;
+		}
+
+		dev_dbg(&client->dev, "Adjusted output height: in %u, out %u\n",
+			input_h, output_h);
+	}
+
+	/* Idea: use the read mode for snapshots, handle separate geometries */
 	ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L,
 			      RJ54N1_Y_OUTPUT_SIZE_S_L,
 			      RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h);
@@ -566,17 +691,27 @@
 	if (ret < 0)
 		return ret;
 
-	if (output_w > input_w || output_h > input_h) {
+	if (output_w > input_w && output_h > input_h) {
 		input_w = output_w;
 		input_h = output_h;
 
 		resize = 1024;
 	} else {
 		unsigned int resize_x, resize_y;
-		resize_x = input_w * 1024 / output_w;
-		resize_y = input_h * 1024 / output_h;
+		resize_x = (input_w * 1024 + output_w / 2) / output_w;
+		resize_y = (input_h * 1024 + output_h / 2) / output_h;
 
-		resize = min(resize_x, resize_y);
+		/* We want max(resize_x, resize_y), check if it still fits */
+		if (resize_x > resize_y &&
+		    (output_h * resize_x + 512) / 1024 > RJ54N1_MAX_HEIGHT)
+			resize = (RJ54N1_MAX_HEIGHT * 1024 + output_h / 2) /
+				output_h;
+		else if (resize_y > resize_x &&
+			 (output_w * resize_y + 512) / 1024 > RJ54N1_MAX_WIDTH)
+			resize = (RJ54N1_MAX_WIDTH * 1024 + output_w / 2) /
+				output_w;
+		else
+			resize = max(resize_x, resize_y);
 
 		/* Prohibited value ranges */
 		switch (resize) {
@@ -589,12 +724,9 @@
 		case 8160 ... 8191:
 			resize = 8159;
 			break;
-		case 16320 ... 16383:
+		case 16320 ... 16384:
 			resize = 16319;
 		}
-
-		input_w = output_w * resize / 1024;
-		input_h = output_h * resize / 1024;
 	}
 
 	/* Set scaling */
@@ -607,9 +739,18 @@
 
 	/*
 	 * Configure a skipping bitmask. The sensor will select a skipping value
-	 * among set bits automatically.
+	 * among set bits automatically. This is very unclear in the datasheet
+	 * too. I was told, in this register one enables all skipping values,
+	 * that are required for a specific resize, and the camera selects
+	 * automatically, which ones to use. But it is unclear how to identify,
+	 * which cropping values are needed. Secondly, why don't we just set all
+	 * bits and let the camera choose? Would it increase processing time and
+	 * reduce the framerate? Using 0xfffc for INC_USE_SEL doesn't seem to
+	 * improve the image quality or stability for larger frames (see comment
+	 * above), but I didn't check the framerate.
 	 */
 	skip = min(resize / 1024, (unsigned)15);
+
 	inc_sel = 1 << skip;
 
 	if (inc_sel <= 2)
@@ -621,6 +762,43 @@
 	if (!ret)
 		ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8);
 
+	if (!rj54n1->auto_wb) {
+		/* Auto white balance window */
+		wb_left	  = output_w / 16;
+		wb_right  = (3 * output_w / 4 - 3) / 4;
+		wb_top	  = output_h / 16;
+		wb_bottom = (3 * output_h / 4 - 3) / 4;
+		wb_bit8	  = ((wb_left >> 2) & 0x40) | ((wb_top >> 4) & 0x10) |
+			((wb_right >> 6) & 4) | ((wb_bottom >> 8) & 1);
+
+		if (!ret)
+			ret = reg_write(client, RJ54N1_BIT8_WB, wb_bit8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_HCAPS_WB, wb_left);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_VCAPS_WB, wb_top);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_HCAPE_WB, wb_right);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_VCAPE_WB, wb_bottom);
+	}
+
+	/* Antiflicker */
+	peak = 12 * RJ54N1_MAX_WIDTH * (1 << 14) * resize / rj54n1->tgclk_mhz /
+		10000;
+	peak_50 = peak / 6;
+	peak_60 = peak / 5;
+
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_H,
+				((peak_50 >> 4) & 0xf0) | (peak_60 >> 8));
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_50, peak_50);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_60, peak_60);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_DIFF, peak / 150);
+
 	/* Start resizing */
 	if (!ret)
 		ret = reg_write(client, RJ54N1_RESIZE_CONTROL,
@@ -629,8 +807,6 @@
 	if (ret < 0)
 		return ret;
 
-	dev_dbg(&client->dev, "resize %u, skip %u\n", resize, skip);
-
 	/* Constant taken from manufacturer's example */
 	msleep(230);
 
@@ -638,11 +814,14 @@
 	if (ret < 0)
 		return ret;
 
-	*in_w = input_w;
-	*in_h = input_h;
+	*in_w = (output_w * resize + 512) / 1024;
+	*in_h = (output_h * resize + 512) / 1024;
 	*out_w = output_w;
 	*out_h = output_h;
 
+	dev_dbg(&client->dev, "Scaled for %ux%u : %u = %ux%u, skip %u\n",
+		*in_w, *in_h, resize, output_w, output_h, skip);
+
 	return resize;
 }
 
@@ -653,14 +832,14 @@
 
 	/* Enable external clock */
 	ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY);
-	/* Leave stand-by */
+	/* Leave stand-by. Note: use this when implementing suspend / resume */
 	if (!ret)
 		ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK);
 
 	if (!ret)
-		ret = reg_write(client, RJ54N1_PLL_L, 2);
+		ret = reg_write(client, RJ54N1_PLL_L, PLL_L);
 	if (!ret)
-		ret = reg_write(client, RJ54N1_PLL_N, 0x31);
+		ret = reg_write(client, RJ54N1_PLL_N, PLL_N);
 
 	/* TGCLK dividers */
 	if (!ret)
@@ -719,6 +898,7 @@
 			"Resetting RJ54N1CB0C clock failed: %d!\n", ret);
 		return -EIO;
 	}
+
 	/* Start the PLL */
 	ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1);
 
@@ -731,6 +911,7 @@
 
 static int rj54n1_reg_init(struct i2c_client *client)
 {
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
 	int ret = rj54n1_set_clock(client);
 
 	if (!ret)
@@ -753,14 +934,26 @@
 	if (!ret)
 		ret = reg_write(client, RJ54N1_Y_GAIN, 0x84);
 
-	/* Mirror the image back: default is upside down and left-to-right... */
+	/*
+	 * Mirror the image back: default is upside down and left-to-right...
+	 * Set manual preview / still shot switching
+	 */
 	if (!ret)
-		ret = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 3, 3);
+		ret = reg_write(client, RJ54N1_MIRROR_STILL_MODE, 0x27);
 
 	if (!ret)
 		ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4));
+
+	/* Auto exposure area */
 	if (!ret)
+		ret = reg_write(client, RJ54N1_EXPOSURE_CONTROL, 0x80);
+	/* Check current auto WB config */
+	if (!ret)
+		ret = reg_read(client, RJ54N1_WB_SEL_WEIGHT_I);
+	if (ret >= 0) {
+		rj54n1->auto_wb = ret & 0x80;
 		ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5));
+	}
 	if (!ret)
 		ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8));
 
@@ -777,8 +970,9 @@
 		ret = reg_write(client, RJ54N1_RESET_STANDBY,
 				E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX);
 
+	/* Start register update? Same register as 0x?FE in many bank_* sets */
 	if (!ret)
-		ret = reg_write(client, 0x7fe, 2);
+		ret = reg_write(client, RJ54N1_FWFLG, 2);
 
 	/* Constant taken from manufacturer's example */
 	msleep(700);
@@ -786,27 +980,44 @@
 	return ret;
 }
 
-/* FIXME: streaming output only up to 800x600 is functional */
-static int rj54n1_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int rj54n1_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
 {
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct i2c_client *client = sd->priv;
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	const struct rj54n1_datafmt *fmt;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE;
 
-	pix->field = V4L2_FIELD_NONE;
+	dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
+		__func__, mf->code, mf->width, mf->height);
 
-	if (pix->width > 800)
-		pix->width = 800;
-	if (pix->height > 600)
-		pix->height = 600;
+	fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
+				  ARRAY_SIZE(rj54n1_colour_fmts));
+	if (!fmt) {
+		fmt = rj54n1->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->field	= V4L2_FIELD_NONE;
+	mf->colorspace	= fmt->colorspace;
+
+	v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
+			      &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
 
 	return 0;
 }
 
-static int rj54n1_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int rj54n1_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct rj54n1 *rj54n1 = to_rj54n1(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	unsigned int output_w, output_h,
+	const struct rj54n1_datafmt *fmt;
+	unsigned int output_w, output_h, max_w, max_h,
 		input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
 	int ret;
 
@@ -814,14 +1025,13 @@
 	 * The host driver can call us without .try_fmt(), so, we have to take
 	 * care ourseleves
 	 */
-	ret = rj54n1_try_fmt(sd, f);
+	rj54n1_try_fmt(sd, mf);
 
 	/*
 	 * Verify if the sensor has just been powered on. TODO: replace this
 	 * with proper PM, when a suitable API is available.
 	 */
-	if (!ret)
-		ret = reg_read(client, RJ54N1_RESET_STANDBY);
+	ret = reg_read(client, RJ54N1_RESET_STANDBY);
 	if (ret < 0)
 		return ret;
 
@@ -831,50 +1041,105 @@
 			return ret;
 	}
 
+	dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
+		__func__, mf->code, mf->width, mf->height);
+
 	/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
-	switch (pix->pixelformat) {
-	case V4L2_PIX_FMT_YUYV:
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8_LE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		break;
-	case V4L2_PIX_FMT_RGB565:
+	case V4L2_MBUS_FMT_YVYU8_2X8_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
 		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
 		if (!ret)
 			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
 		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 5);
+		break;
 	default:
 		ret = -EINVAL;
 	}
 
+	/* Special case: a raw mode with 10 bits of data per clock tick */
+	if (!ret)
+		ret = reg_set(client, RJ54N1_OCLK_SEL_EN,
+			      (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2);
+
 	if (ret < 0)
 		return ret;
 
-	/* Supported scales 1:1 - 1:16 */
-	if (pix->width < input_w / 16)
-		pix->width = input_w / 16;
-	if (pix->height < input_h / 16)
-		pix->height = input_h / 16;
+	/* Supported scales 1:1 >= scale > 1:16 */
+	max_w = mf->width * (16 * 1024 - 1) / 1024;
+	if (input_w > max_w)
+		input_w = max_w;
+	max_h = mf->height * (16 * 1024 - 1) / 1024;
+	if (input_h > max_h)
+		input_h = max_h;
 
-	output_w = pix->width;
-	output_h = pix->height;
+	output_w = mf->width;
+	output_h = mf->height;
 
 	ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h);
 	if (ret < 0)
 		return ret;
 
-	rj54n1->fourcc		= pix->pixelformat;
+	fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
+				  ARRAY_SIZE(rj54n1_colour_fmts));
+
+	rj54n1->fmt		= fmt;
 	rj54n1->resize		= ret;
 	rj54n1->rect.width	= input_w;
 	rj54n1->rect.height	= input_h;
 	rj54n1->width		= output_w;
 	rj54n1->height		= output_h;
 
-	pix->width		= output_w;
-	pix->height		= output_h;
-	pix->field		= V4L2_FIELD_NONE;
+	mf->width		= output_w;
+	mf->height		= output_h;
+	mf->field		= V4L2_FIELD_NONE;
+	mf->colorspace		= fmt->colorspace;
 
-	return ret;
+	return 0;
 }
 
 static int rj54n1_g_chip_ident(struct v4l2_subdev *sd,
@@ -963,6 +1228,14 @@
 		.step		= 1,
 		.default_value	= 66,
 		.flags		= V4L2_CTRL_FLAG_SLIDER,
+	}, {
+		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Auto white balance",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 1,
 	},
 };
 
@@ -976,6 +1249,7 @@
 static int rj54n1_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 {
 	struct i2c_client *client = sd->priv;
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
 	int data;
 
 	switch (ctrl->id) {
@@ -998,6 +1272,9 @@
 
 		ctrl->value = data / 2;
 		break;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ctrl->value = rj54n1->auto_wb;
+		break;
 	}
 
 	return 0;
@@ -1007,6 +1284,7 @@
 {
 	int data;
 	struct i2c_client *client = sd->priv;
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
 	const struct v4l2_queryctrl *qctrl;
 
 	qctrl = soc_camera_find_qctrl(&rj54n1_ops, ctrl->id);
@@ -1037,6 +1315,13 @@
 		else if (reg_write(client, RJ54N1_Y_GAIN, ctrl->value * 2) < 0)
 			return -EIO;
 		break;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		/* Auto WB area - whole image */
+		if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->value << 7,
+			    0x80) < 0)
+			return -EIO;
+		rj54n1->auto_wb = ctrl->value;
+		break;
 	}
 
 	return 0;
@@ -1054,10 +1339,12 @@
 
 static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
 	.s_stream	= rj54n1_s_stream,
-	.s_fmt		= rj54n1_s_fmt,
-	.g_fmt		= rj54n1_g_fmt,
-	.try_fmt	= rj54n1_try_fmt,
+	.s_mbus_fmt	= rj54n1_s_fmt,
+	.g_mbus_fmt	= rj54n1_g_fmt,
+	.try_mbus_fmt	= rj54n1_try_fmt,
+	.enum_mbus_fmt	= rj54n1_enum_fmt,
 	.g_crop		= rj54n1_g_crop,
+	.s_crop		= rj54n1_s_crop,
 	.cropcap	= rj54n1_cropcap,
 };
 
@@ -1066,21 +1353,13 @@
 	.video	= &rj54n1_subdev_video_ops,
 };
 
-static int rj54n1_pin_config(struct i2c_client *client)
-{
-	/*
-	 * Experimentally found out IOCTRL wired to 0. TODO: add to platform
-	 * data: 0 or 1 << 7.
-	 */
-	return reg_write(client, RJ54N1_IOC, 0);
-}
-
 /*
  * Interface active, can use i2c. If it fails, it can indeed mean, that
  * this wasn't our capture interface, so, we wait for the right one
  */
 static int rj54n1_video_probe(struct soc_camera_device *icd,
-			      struct i2c_client *client)
+			      struct i2c_client *client,
+			      struct rj54n1_pdata *priv)
 {
 	int data1, data2;
 	int ret;
@@ -1101,7 +1380,8 @@
 		goto ei2c;
 	}
 
-	ret = rj54n1_pin_config(client);
+	/* Configure IOCTL polarity from the platform data: 0 or 1 << 7. */
+	ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7);
 	if (ret < 0)
 		goto ei2c;
 
@@ -1119,6 +1399,7 @@
 	struct soc_camera_device *icd = client->dev.platform_data;
 	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 	struct soc_camera_link *icl;
+	struct rj54n1_pdata *rj54n1_priv;
 	int ret;
 
 	if (!icd) {
@@ -1127,11 +1408,13 @@
 	}
 
 	icl = to_soc_camera_link(icd);
-	if (!icl) {
+	if (!icl || !icl->priv) {
 		dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n");
 		return -EINVAL;
 	}
 
+	rj54n1_priv = icl->priv;
+
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_warn(&adapter->dev,
 			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
@@ -1153,10 +1436,12 @@
 	rj54n1->rect.height	= RJ54N1_MAX_HEIGHT;
 	rj54n1->width		= RJ54N1_MAX_WIDTH;
 	rj54n1->height		= RJ54N1_MAX_HEIGHT;
-	rj54n1->fourcc		= V4L2_PIX_FMT_YUYV;
+	rj54n1->fmt		= &rj54n1_colour_fmts[0];
 	rj54n1->resize		= 1024;
+	rj54n1->tgclk_mhz	= (rj54n1_priv->mclk_freq / PLL_L * PLL_N) /
+		(clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1);
 
-	ret = rj54n1_video_probe(icd, client);
+	ret = rj54n1_video_probe(icd, client, rj54n1_priv);
 	if (ret < 0) {
 		icd->ops = NULL;
 		i2c_set_clientdata(client, NULL);
@@ -1164,9 +1449,6 @@
 		return ret;
 	}
 
-	icd->formats		= rj54n1_colour_formats;
-	icd->num_formats	= ARRAY_SIZE(rj54n1_colour_formats);
-
 	return ret;
 }
 
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 41765f3..fb742f1 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -233,7 +233,6 @@
 
 	struct s2255_dmaqueue	vidq[MAX_CHANNELS];
 	struct video_device	*vdev[MAX_CHANNELS];
-	struct list_head	s2255_devlist;
 	struct timer_list	timer;
 	struct s2255_fw	*fw_data;
 	struct s2255_pipeinfo	pipes[MAX_PIPE_BUFFERS];
@@ -313,8 +312,6 @@
 /* Channels on box are in reverse order */
 static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0};
 
-static LIST_HEAD(s2255_devlist);
-
 static int debug;
 static int *s2255_debug = &debug;
 
@@ -1533,32 +1530,24 @@
 }
 static int s2255_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct s2255_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct s2255_dev *dev = video_drvdata(file);
 	struct s2255_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	int i = 0;
 	int cur_channel = -1;
 	int state;
-	dprintk(1, "s2255: open called (minor=%d)\n", minor);
+
+	dprintk(1, "s2255: open called (dev=%s)\n",
+		video_device_node_name(vdev));
 
 	lock_kernel();
-	list_for_each(list, &s2255_devlist) {
-		h = list_entry(list, struct s2255_dev, s2255_devlist);
-		for (i = 0; i < MAX_CHANNELS; i++) {
-			if (h->vdev[i]->minor == minor) {
-				cur_channel = i;
-				dev = h;
-				type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-			}
-		}
-	}
 
-	if ((NULL == dev) || (cur_channel == -1)) {
-		unlock_kernel();
-		printk(KERN_INFO "s2255: openv4l no dev\n");
-		return -ENODEV;
+	for (i = 0; i < MAX_CHANNELS; i++) {
+		if (dev->vdev[i] == vdev) {
+			cur_channel = i;
+			break;
+		}
 	}
 
 	if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_DISCONNECTING) {
@@ -1662,8 +1651,9 @@
 	for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
 		qctl_regs[i] = s2255_qctrl[i].default_value;
 
-	dprintk(1, "s2255drv: open minor=%d type=%s users=%d\n",
-		minor, v4l2_type_names[type], dev->users[cur_channel]);
+	dprintk(1, "s2255drv: open dev=%s type=%s users=%d\n",
+		video_device_node_name(vdev), v4l2_type_names[type],
+		dev->users[cur_channel]);
 	dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n",
 		(unsigned long)fh, (unsigned long)dev,
 		(unsigned long)&dev->vidq[cur_channel]);
@@ -1699,7 +1689,6 @@
 static void s2255_destroy(struct kref *kref)
 {
 	struct s2255_dev *dev = to_s2255_dev(kref);
-	struct list_head *list;
 	int i;
 	if (!dev) {
 		printk(KERN_ERR "s2255drv: kref problem\n");
@@ -1733,10 +1722,6 @@
 	usb_put_dev(dev->udev);
 	dprintk(1, "%s", __func__);
 
-	while (!list_empty(&s2255_devlist)) {
-		list = s2255_devlist.next;
-		list_del(list);
-	}
 	mutex_unlock(&dev->open_lock);
 	kfree(dev);
 }
@@ -1745,7 +1730,8 @@
 {
 	struct s2255_fh *fh = file->private_data;
 	struct s2255_dev *dev = fh->dev;
-	int minor = video_devdata(file)->minor;
+	struct video_device *vdev = video_devdata(file);
+
 	if (!dev)
 		return -ENODEV;
 
@@ -1765,8 +1751,8 @@
 	mutex_unlock(&dev->open_lock);
 
 	kref_put(&dev->kref, s2255_destroy);
-	dprintk(1, "s2255: close called (minor=%d, users=%d)\n",
-		minor, dev->users[fh->channel]);
+	dprintk(1, "s2255: close called (dev=%s, users=%d)\n",
+		video_device_node_name(vdev), dev->users[fh->channel]);
 	kfree(fh);
 	return 0;
 }
@@ -1830,7 +1816,6 @@
 	.name = "s2255v",
 	.fops = &s2255_fops_v4l,
 	.ioctl_ops = &s2255_ioctl_ops,
-	.minor = -1,
 	.release = video_device_release,
 	.tvnorms = S2255_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
@@ -1843,7 +1828,6 @@
 	int cur_nr = video_nr;
 
 	/* initialize all video 4 linux */
-	list_add_tail(&dev->s2255_devlist, &s2255_devlist);
 	/* register 4 video devices */
 	for (i = 0; i < MAX_CHANNELS; i++) {
 		INIT_LIST_HEAD(&dev->vidq[i].active);
@@ -1853,6 +1837,7 @@
 		dev->vdev[i] = video_device_alloc();
 		memcpy(dev->vdev[i], &template, sizeof(struct video_device));
 		dev->vdev[i]->parent = &dev->interface->dev;
+		video_set_drvdata(dev->vdev[i], dev);
 		if (video_nr == -1)
 			ret = video_register_device(dev->vdev[i],
 						    VFL_TYPE_GRABBER,
@@ -1880,7 +1865,7 @@
 
 	int i;
 	for (i = 0; i < MAX_CHANNELS; i++) {
-		if (-1 != dev->vdev[i]->minor) {
+		if (video_is_registered(dev->vdev[i])) {
 			video_unregister_device(dev->vdev[i]);
 			printk(KERN_INFO "s2255 unregistered\n");
 		} else {
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index b624a4c..5ab6a0f 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -1036,7 +1036,6 @@
 	.name	  = "saa5246a",
 	.fops	  = &saa_fops,
 	.release  = video_device_release,
-	.minor    = -1,
 };
 
 static int saa5246a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 7e40d6d..03f5727 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -7211,9 +7211,31 @@
 	}
 	case SAA7134_BOARD_FLYDVB_TRIO:
 	{
+		u8 temp = 0;
+		int rc;
 		u8 data[] = { 0x3c, 0x33, 0x62};
 		struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
 		i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+		/*
+		 * send weak up message to pic16C505 chip
+		 * @ LifeView FlyDVB Trio
+		 */
+		msg.buf = &temp;
+		msg.addr = 0x0b;
+		msg.len = 1;
+		if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
+			printk(KERN_WARNING "%s: send wake up byte to pic16C505"
+					"(IR chip) failed\n", dev->name);
+		} else {
+			msg.flags = I2C_M_RD;
+			rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
+			printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n",
+				   dev->name, msg.addr,
+				   (1 == rc) ? "yes" : "no");
+			if (rc == 1)
+				dev->has_remote = SAA7134_REMOTE_I2C;
+		}
 		break;
 	}
 	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 0ba7f5a..9f85e91 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -797,27 +797,28 @@
 	vfd->debug   = video_debug;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 dev->name, type, saa7134_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
 	return vfd;
 }
 
 static void saa7134_unregister_video(struct saa7134_dev *dev)
 {
 	if (dev->video_dev) {
-		if (-1 != dev->video_dev->minor)
+		if (video_is_registered(dev->video_dev))
 			video_unregister_device(dev->video_dev);
 		else
 			video_device_release(dev->video_dev);
 		dev->video_dev = NULL;
 	}
 	if (dev->vbi_dev) {
-		if (-1 != dev->vbi_dev->minor)
+		if (video_is_registered(dev->vbi_dev))
 			video_unregister_device(dev->vbi_dev);
 		else
 			video_device_release(dev->vbi_dev);
 		dev->vbi_dev = NULL;
 	}
 	if (dev->radio_dev) {
-		if (-1 != dev->radio_dev->minor)
+		if (video_is_registered(dev->radio_dev))
 			video_unregister_device(dev->radio_dev);
 		else
 			video_device_release(dev->radio_dev);
@@ -1046,8 +1047,8 @@
 		       dev->name);
 		goto fail4;
 	}
-	printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
-	       dev->name, dev->video_dev->num);
+	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+	       dev->name, video_device_node_name(dev->video_dev));
 
 	dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
 
@@ -1055,8 +1056,8 @@
 				    vbi_nr[dev->nr]);
 	if (err < 0)
 		goto fail4;
-	printk(KERN_INFO "%s: registered device vbi%d\n",
-	       dev->name, dev->vbi_dev->num);
+	printk(KERN_INFO "%s: registered device %s\n",
+	       dev->name, video_device_node_name(dev->vbi_dev));
 
 	if (card_has_radio(dev)) {
 		dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
@@ -1064,8 +1065,8 @@
 					    radio_nr[dev->nr]);
 		if (err < 0)
 			goto fail4;
-		printk(KERN_INFO "%s: registered device radio%d\n",
-		       dev->name, dev->radio_dev->num);
+		printk(KERN_INFO "%s: registered device %s\n",
+		       dev->name, video_device_node_name(dev->radio_dev));
 	}
 
 	/* everything worked */
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 296788c..7dfecfc 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -86,19 +86,11 @@
 
 static int ts_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct saa7134_dev *dev;
+	struct video_device *vdev = video_devdata(file);
+	struct saa7134_dev *dev = video_drvdata(file);
 	int err;
 
-	lock_kernel();
-	list_for_each_entry(dev, &saa7134_devlist, devlist)
-		if (dev->empress_dev && dev->empress_dev->minor == minor)
-			goto found;
-	unlock_kernel();
-	return -ENODEV;
- found:
-
-	dprintk("open minor=%d\n",minor);
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
 	err = -EBUSY;
 	if (!mutex_trylock(&dev->empress_tsq.vb_lock))
 		goto done;
@@ -489,7 +481,6 @@
 static struct video_device saa7134_empress_template = {
 	.name          = "saa7134-empress",
 	.fops          = &ts_fops,
-	.minor	       = -1,
 	.ioctl_ops     = &ts_ioctl_ops,
 
 	.tvnorms			= SAA7134_NORMS,
@@ -531,6 +522,7 @@
 
 	INIT_WORK(&dev->empress_workqueue, empress_signal_update);
 
+	video_set_drvdata(dev->empress_dev, dev);
 	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
 				    empress_nr[dev->nr]);
 	if (err < 0) {
@@ -540,8 +532,8 @@
 		dev->empress_dev = NULL;
 		return err;
 	}
-	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
-	       dev->name, dev->empress_dev->num);
+	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+	       dev->name, video_device_node_name(dev->empress_dev));
 
 	videobuf_queue_sg_init(&dev->empress_tsq, &saa7134_ts_qops,
 			    &dev->pci->dev, &dev->slock,
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 744918b..f8e9859 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -127,6 +127,61 @@
 
 /* --------------------- Chip specific I2C key builders ----------------- */
 
+static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	int gpio;
+	int attempt = 0;
+	unsigned char b;
+
+	/* We need this to access GPI Used by the saa_readl macro. */
+	struct saa7134_dev *dev = ir->c->adapter->algo_data;
+
+	if (dev == NULL) {
+		dprintk("get_key_flydvb_trio: "
+			 "gir->c->adapter->algo_data is NULL!\n");
+		return -EIO;
+	}
+
+	/* rising SAA7134_GPIGPRESCAN reads the status */
+	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+	gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+	if (0x40000 & ~gpio)
+		return 0; /* No button press */
+
+	/* No button press - only before first key pressed */
+	if (b == 0xFF)
+		return 0;
+
+	/* poll IR chip */
+	/* weak up the IR chip */
+	b = 0;
+
+	while (1 != i2c_master_send(ir->c, &b, 1)) {
+		if ((attempt++) < 10) {
+			/*
+			 * wait a bit for next attempt -
+			 * I don't know how make it better
+			 */
+			msleep(10);
+			continue;
+		}
+		i2cdprintk("send wake up byte to pic16C505 (IR chip)"
+			   "failed %dx\n", attempt);
+		return -EIO;
+	}
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
+		i2cdprintk("read error\n");
+		return -EIO;
+	}
+
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
+
 static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
 				       u32 *ir_raw)
 {
@@ -622,6 +677,7 @@
 		mask_keyup   = 0x020000;
 		polling      = 50; /* ms */
 		break;
+	break;
 	}
 	if (NULL == ir_codes) {
 		printk("%s: Oops: IR config error [card=%d]\n",
@@ -652,7 +708,7 @@
 	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
 		 pci_name(dev->pci));
 
-	err = ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
+	err = ir_input_init(input_dev, &ir->ir, ir_type);
 	if (err < 0)
 		goto err_out_free;
 
@@ -672,7 +728,7 @@
 	dev->remote = ir;
 	saa7134_ir_start(dev, ir);
 
-	err = input_register_device(ir->dev);
+	err = ir_input_register(ir->dev, ir_codes);
 	if (err)
 		goto err_out_stop;
 
@@ -686,8 +742,6 @@
 	saa7134_ir_stop(dev);
 	dev->remote = NULL;
  err_out_free:
-	ir_input_free(input_dev);
-	input_free_device(input_dev);
 	kfree(ir);
 	return err;
 }
@@ -698,8 +752,7 @@
 		return;
 
 	saa7134_ir_stop(dev);
-	ir_input_free(dev->remote->dev);
-	input_unregister_device(dev->remote->dev);
+	ir_input_unregister(dev->remote->dev);
 	kfree(dev->remote);
 	dev->remote = NULL;
 }
@@ -788,6 +841,12 @@
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
 		info.addr = 0x40;
 		break;
+	case SAA7134_BOARD_FLYDVB_TRIO:
+		dev->init_data.name = "FlyDVB Trio";
+		dev->init_data.get_key = get_key_flydvb_trio;
+		dev->init_data.ir_codes = &ir_codes_flydvb_table;
+		info.addr = 0x0b;
+		break;
 	default:
 		dprintk("No I2C IR support for board %x\n", dev->board);
 		return;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 35f8daa..cb73264 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1326,33 +1326,26 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct saa7134_dev *dev;
+	struct video_device *vdev = video_devdata(file);
+	struct saa7134_dev *dev = video_drvdata(file);
 	struct saa7134_fh *fh;
-	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	enum v4l2_buf_type type = 0;
 	int radio = 0;
 
-	mutex_lock(&saa7134_devlist_lock);
-	list_for_each_entry(dev, &saa7134_devlist, devlist) {
-		if (dev->video_dev && (dev->video_dev->minor == minor))
-			goto found;
-		if (dev->radio_dev && (dev->radio_dev->minor == minor)) {
-			radio = 1;
-			goto found;
-		}
-		if (dev->vbi_dev && (dev->vbi_dev->minor == minor)) {
-			type = V4L2_BUF_TYPE_VBI_CAPTURE;
-			goto found;
-		}
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
 	}
-	mutex_unlock(&saa7134_devlist_lock);
-	return -ENODEV;
 
-found:
-	mutex_unlock(&saa7134_devlist_lock);
-
-	dprintk("open minor=%d radio=%d type=%s\n",minor,radio,
-		v4l2_type_names[type]);
+	dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev),
+		radio, v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
@@ -2502,7 +2495,6 @@
 	.name				= "saa7134-video",
 	.fops				= &video_fops,
 	.ioctl_ops 			= &video_ioctl_ops,
-	.minor				= -1,
 	.tvnorms			= SAA7134_NORMS,
 	.current_norm			= V4L2_STD_PAL,
 };
@@ -2511,7 +2503,6 @@
 	.name			= "saa7134-radio",
 	.fops			= &radio_fops,
 	.ioctl_ops 		= &radio_ioctl_ops,
-	.minor			= -1,
 };
 
 int saa7134_video_init1(struct saa7134_dev *dev)
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index 85ffc2c..41d0166 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -1428,8 +1428,8 @@
 		err("video_register_device failed");
 		return -EIO;
 	}
-	dev_info(&intf->dev, "registered new video device: video%d\n",
-		 se401->vdev.num);
+	dev_info(&intf->dev, "registered new video device: %s\n",
+		 video_device_node_name(&se401->vdev));
 
 	usb_set_intfdata(intf, se401);
 	return 0;
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 961e448..d69363f 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -38,6 +38,8 @@
 #include <media/soc_camera.h>
 #include <media/sh_mobile_ceu.h>
 #include <media/videobuf-dma-contig.h>
+#include <media/v4l2-mediabus.h>
+#include <media/soc_mediabus.h>
 
 /* register offsets for sh7722 / sh7723 */
 
@@ -85,7 +87,7 @@
 /* per video frame buffer */
 struct sh_mobile_ceu_buffer {
 	struct videobuf_buffer vb; /* v4l buffer must be first */
-	const struct soc_camera_data_format *fmt;
+	enum v4l2_mbus_pixelcode code;
 };
 
 struct sh_mobile_ceu_dev {
@@ -105,7 +107,8 @@
 
 	u32 cflcr;
 
-	unsigned int is_interlaced:1;
+	enum v4l2_field field;
+
 	unsigned int image_mode:1;
 	unsigned int is_16bit:1;
 };
@@ -114,8 +117,8 @@
 	struct v4l2_rect ceu_rect;
 	unsigned int cam_width;
 	unsigned int cam_height;
-	const struct soc_camera_data_format *extra_fmt;
-	const struct soc_camera_data_format *camera_fmt;
+	const struct soc_mbus_pixelfmt *extra_fmt;
+	enum v4l2_mbus_pixelcode code;
 };
 
 static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
@@ -197,16 +200,19 @@
 	struct soc_camera_device *icd = vq->priv_data;
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
-	int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
 
-	*size = PAGE_ALIGN(icd->user_width * icd->user_height *
-			   bytes_per_pixel);
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
+	*size = bytes_per_line * icd->user_height;
 
 	if (0 == *count)
 		*count = 2;
 
 	if (pcdev->video_limit) {
-		while (*size * *count > pcdev->video_limit)
+		while (PAGE_ALIGN(*size) * *count > pcdev->video_limit)
 			(*count)--;
 	}
 
@@ -249,10 +255,13 @@
 {
 	struct soc_camera_device *icd = pcdev->icd;
 	dma_addr_t phys_addr_top, phys_addr_bottom;
+	unsigned long top1, top2;
+	unsigned long bottom1, bottom2;
 	u32 status;
 	int ret = 0;
 
-	/* The hardware is _very_ picky about this sequence. Especially
+	/*
+	 * The hardware is _very_ picky about this sequence. Especially
 	 * the CEU_CETCR_MAGIC value. It seems like we need to acknowledge
 	 * several not-so-well documented interrupt sources in CETCR.
 	 */
@@ -276,25 +285,36 @@
 	if (!pcdev->active)
 		return ret;
 
-	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
-	ceu_write(pcdev, CDAYR, phys_addr_top);
-	if (pcdev->is_interlaced) {
-		phys_addr_bottom = phys_addr_top + icd->user_width;
-		ceu_write(pcdev, CDBYR, phys_addr_bottom);
+	if (V4L2_FIELD_INTERLACED_BT == pcdev->field) {
+		top1	= CDBYR;
+		top2	= CDBCR;
+		bottom1	= CDAYR;
+		bottom2	= CDACR;
+	} else {
+		top1	= CDAYR;
+		top2	= CDACR;
+		bottom1	= CDBYR;
+		bottom2	= CDBCR;
 	}
 
-	switch (icd->current_fmt->fourcc) {
+	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
+	ceu_write(pcdev, top1, phys_addr_top);
+	if (V4L2_FIELD_NONE != pcdev->field) {
+		phys_addr_bottom = phys_addr_top + icd->user_width;
+		ceu_write(pcdev, bottom1, phys_addr_bottom);
+	}
+
+	switch (icd->current_fmt->host_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
 		phys_addr_top += icd->user_width *
 			icd->user_height;
-		ceu_write(pcdev, CDACR, phys_addr_top);
-		if (pcdev->is_interlaced) {
-			phys_addr_bottom = phys_addr_top +
-				icd->user_width;
-			ceu_write(pcdev, CDBCR, phys_addr_bottom);
+		ceu_write(pcdev, top2, phys_addr_top);
+		if (V4L2_FIELD_NONE != pcdev->field) {
+			phys_addr_bottom = phys_addr_top + icd->user_width;
+			ceu_write(pcdev, bottom2, phys_addr_bottom);
 		}
 	}
 
@@ -310,8 +330,13 @@
 {
 	struct soc_camera_device *icd = vq->priv_data;
 	struct sh_mobile_ceu_buffer *buf;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
 	int ret;
 
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
 	buf = container_of(vb, struct sh_mobile_ceu_buffer, vb);
 
 	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
@@ -321,25 +346,27 @@
 	WARN_ON(!list_empty(&vb->queue));
 
 #ifdef DEBUG
-	/* This can be useful if you want to see if we actually fill
-	 * the buffer with something */
+	/*
+	 * This can be useful if you want to see if we actually fill
+	 * the buffer with something
+	 */
 	memset((void *)vb->baddr, 0xaa, vb->bsize);
 #endif
 
 	BUG_ON(NULL == icd->current_fmt);
 
-	if (buf->fmt	!= icd->current_fmt ||
+	if (buf->code	!= icd->current_fmt->code ||
 	    vb->width	!= icd->user_width ||
 	    vb->height	!= icd->user_height ||
 	    vb->field	!= field) {
-		buf->fmt	= icd->current_fmt;
+		buf->code	= icd->current_fmt->code;
 		vb->width	= icd->user_width;
 		vb->height	= icd->user_height;
 		vb->field	= field;
 		vb->state	= VIDEOBUF_NEEDS_INIT;
 	}
 
-	vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
+	vb->size = vb->height * bytes_per_line;
 	if (0 != vb->baddr && vb->bsize < vb->size) {
 		ret = -EINVAL;
 		goto out;
@@ -456,6 +483,7 @@
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	int ret;
 
 	if (pcdev->icd)
 		return -EBUSY;
@@ -466,9 +494,11 @@
 
 	pm_runtime_get_sync(ici->v4l2_dev.dev);
 
-	pcdev->icd = icd;
+	ret = sh_mobile_ceu_soft_reset(pcdev);
+	if (!ret)
+		pcdev->icd = icd;
 
-	return sh_mobile_ceu_soft_reset(pcdev);
+	return ret;
 }
 
 /* Called with .video_lock held */
@@ -558,24 +588,35 @@
 			in_width *= 2;
 			left_offset *= 2;
 		}
-		width = cdwdr_width = out_width;
+		width = out_width;
+		cdwdr_width = out_width;
 	} else {
-		unsigned int w_factor = (icd->current_fmt->depth + 7) >> 3;
+		int bytes_per_line = soc_mbus_bytes_per_line(out_width,
+						icd->current_fmt->host_fmt);
+		unsigned int w_factor;
 
-		width = out_width * w_factor / 2;
+		width = out_width;
 
-		if (!pcdev->is_16bit)
-			w_factor *= 2;
+		switch (icd->current_fmt->host_fmt->packing) {
+		case SOC_MBUS_PACKING_2X8_PADHI:
+			w_factor = 2;
+			break;
+		default:
+			w_factor = 1;
+		}
 
-		in_width = rect->width * w_factor / 2;
-		left_offset = left_offset * w_factor / 2;
+		in_width = rect->width * w_factor;
+		left_offset = left_offset * w_factor;
 
-		cdwdr_width = width * 2;
+		if (bytes_per_line < 0)
+			cdwdr_width = out_width;
+		else
+			cdwdr_width = bytes_per_line;
 	}
 
 	height = out_height;
 	in_height = rect->height;
-	if (pcdev->is_interlaced) {
+	if (V4L2_FIELD_NONE != pcdev->field) {
 		height /= 2;
 		in_height /= 2;
 		top_offset /= 2;
@@ -646,6 +687,23 @@
 	if (!common_flags)
 		return -EINVAL;
 
+	/* Make choises, based on platform preferences */
+	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
+	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
+		if (pcdev->pdata->flags & SH_CEU_FLAG_HSYNC_LOW)
+			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
+		else
+			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
+	}
+
+	if ((common_flags & SOCAM_VSYNC_ACTIVE_HIGH) &&
+	    (common_flags & SOCAM_VSYNC_ACTIVE_LOW)) {
+		if (pcdev->pdata->flags & SH_CEU_FLAG_VSYNC_LOW)
+			common_flags &= ~SOCAM_VSYNC_ACTIVE_HIGH;
+		else
+			common_flags &= ~SOCAM_VSYNC_ACTIVE_LOW;
+	}
+
 	ret = icd->ops->set_bus_param(icd, common_flags);
 	if (ret < 0)
 		return ret;
@@ -667,24 +725,24 @@
 	value = 0x00000010; /* data fetch by default */
 	yuv_lineskip = 0;
 
-	switch (icd->current_fmt->fourcc) {
+	switch (icd->current_fmt->host_fmt->fourcc) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
 		yuv_lineskip = 1; /* skip for NV12/21, no skip for NV16/61 */
 		/* fall-through */
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
-		switch (cam->camera_fmt->fourcc) {
-		case V4L2_PIX_FMT_UYVY:
+		switch (cam->code) {
+		case V4L2_MBUS_FMT_YUYV8_2X8_BE:
 			value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */
 			break;
-		case V4L2_PIX_FMT_VYUY:
+		case V4L2_MBUS_FMT_YVYU8_2X8_BE:
 			value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */
 			break;
-		case V4L2_PIX_FMT_YUYV:
+		case V4L2_MBUS_FMT_YUYV8_2X8_LE:
 			value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */
 			break;
-		case V4L2_PIX_FMT_YVYU:
+		case V4L2_MBUS_FMT_YVYU8_2X8_LE:
 			value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */
 			break;
 		default:
@@ -692,8 +750,8 @@
 		}
 	}
 
-	if (icd->current_fmt->fourcc == V4L2_PIX_FMT_NV21 ||
-	    icd->current_fmt->fourcc == V4L2_PIX_FMT_NV61)
+	if (icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV21 ||
+	    icd->current_fmt->host_fmt->fourcc == V4L2_PIX_FMT_NV61)
 		value ^= 0x00000100; /* swap U, V to change from NV1x->NVx1 */
 
 	value |= common_flags & SOCAM_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;
@@ -702,14 +760,27 @@
 	ceu_write(pcdev, CAMCR, value);
 
 	ceu_write(pcdev, CAPCR, 0x00300000);
-	ceu_write(pcdev, CAIFR, pcdev->is_interlaced ? 0x101 : 0);
+
+	switch (pcdev->field) {
+	case V4L2_FIELD_INTERLACED_TB:
+		value = 0x101;
+		break;
+	case V4L2_FIELD_INTERLACED_BT:
+		value = 0x102;
+		break;
+	default:
+		value = 0;
+		break;
+	}
+	ceu_write(pcdev, CAIFR, value);
 
 	sh_mobile_ceu_set_rect(icd, icd->user_width, icd->user_height);
 	mdelay(1);
 
 	ceu_write(pcdev, CFLCR, pcdev->cflcr);
 
-	/* A few words about byte order (observed in Big Endian mode)
+	/*
+	 * A few words about byte order (observed in Big Endian mode)
 	 *
 	 * In data fetch mode bytes are received in chunks of 8 bytes.
 	 * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)
@@ -739,7 +810,8 @@
 	return 0;
 }
 
-static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd)
+static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
+				       unsigned char buswidth)
 {
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -748,48 +820,75 @@
 	camera_flags = icd->ops->query_bus_param(icd);
 	common_flags = soc_camera_bus_param_compatible(camera_flags,
 						       make_bus_param(pcdev));
-	if (!common_flags)
+	if (!common_flags || buswidth > 16 ||
+	    (buswidth > 8 && !(common_flags & SOCAM_DATAWIDTH_16)))
 		return -EINVAL;
 
 	return 0;
 }
 
-static const struct soc_camera_data_format sh_mobile_ceu_formats[] = {
+static const struct soc_mbus_pixelfmt sh_mobile_ceu_formats[] = {
 	{
-		.name		= "NV12",
-		.depth		= 12,
-		.fourcc		= V4L2_PIX_FMT_NV12,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
-	},
-	{
-		.name		= "NV21",
-		.depth		= 12,
-		.fourcc		= V4L2_PIX_FMT_NV21,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
-	},
-	{
-		.name		= "NV16",
-		.depth		= 16,
-		.fourcc		= V4L2_PIX_FMT_NV16,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
-	},
-	{
-		.name		= "NV61",
-		.depth		= 16,
-		.fourcc		= V4L2_PIX_FMT_NV61,
-		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fourcc			= V4L2_PIX_FMT_NV12,
+		.name			= "NV12",
+		.bits_per_sample	= 12,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_NV21,
+		.name			= "NV21",
+		.bits_per_sample	= 12,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_NV16,
+		.name			= "NV16",
+		.bits_per_sample	= 16,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_NV61,
+		.name			= "NV61",
+		.bits_per_sample	= 16,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
 	},
 };
 
+/* This will be corrected as we get more formats */
+static bool sh_mobile_ceu_packing_supported(const struct soc_mbus_pixelfmt *fmt)
+{
+	return	fmt->packing == SOC_MBUS_PACKING_NONE ||
+		(fmt->bits_per_sample == 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) ||
+		(fmt->bits_per_sample > 8 &&
+		 fmt->packing == SOC_MBUS_PACKING_EXTEND16);
+}
+
 static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
 				     struct soc_camera_format_xlate *xlate)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->dev.parent;
 	int ret, k, n;
 	int formats = 0;
 	struct sh_mobile_ceu_cam *cam;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *fmt;
 
-	ret = sh_mobile_ceu_try_bus_param(icd);
+	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+	if (ret < 0)
+		/* No more formats */
+		return 0;
+
+	fmt = soc_mbus_get_fmtdesc(code);
+	if (!fmt) {
+		dev_err(icd->dev.parent,
+			"Invalid format code #%d: %d\n", idx, code);
+		return -EINVAL;
+	}
+
+	ret = sh_mobile_ceu_try_bus_param(icd, fmt->bits_per_sample);
 	if (ret < 0)
 		return 0;
 
@@ -807,13 +906,13 @@
 	if (!idx)
 		cam->extra_fmt = NULL;
 
-	switch (icd->formats[idx].fourcc) {
-	case V4L2_PIX_FMT_UYVY:
-	case V4L2_PIX_FMT_VYUY:
-	case V4L2_PIX_FMT_YUYV:
-	case V4L2_PIX_FMT_YVYU:
+	switch (code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8_BE:
+	case V4L2_MBUS_FMT_YVYU8_2X8_BE:
+	case V4L2_MBUS_FMT_YUYV8_2X8_LE:
+	case V4L2_MBUS_FMT_YVYU8_2X8_LE:
 		if (cam->extra_fmt)
-			goto add_single_format;
+			break;
 
 		/*
 		 * Our case is simple so far: for any of the above four camera
@@ -824,32 +923,31 @@
 		 * the host_priv pointer and check whether the format you're
 		 * going to add now is already there.
 		 */
-		cam->extra_fmt = (void *)sh_mobile_ceu_formats;
+		cam->extra_fmt = sh_mobile_ceu_formats;
 
 		n = ARRAY_SIZE(sh_mobile_ceu_formats);
 		formats += n;
 		for (k = 0; xlate && k < n; k++) {
-			xlate->host_fmt = &sh_mobile_ceu_formats[k];
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = icd->formats[idx].depth;
+			xlate->host_fmt	= &sh_mobile_ceu_formats[k];
+			xlate->code	= code;
 			xlate++;
-			dev_dbg(dev, "Providing format %s using %s\n",
-				sh_mobile_ceu_formats[k].name,
-				icd->formats[idx].name);
+			dev_dbg(dev, "Providing format %s using code %d\n",
+				sh_mobile_ceu_formats[k].name, code);
 		}
+		break;
 	default:
-add_single_format:
-		/* Generic pass-through */
-		formats++;
-		if (xlate) {
-			xlate->host_fmt = icd->formats + idx;
-			xlate->cam_fmt = icd->formats + idx;
-			xlate->buswidth = icd->formats[idx].depth;
-			xlate++;
-			dev_dbg(dev,
-				"Providing format %s in pass-through mode\n",
-				icd->formats[idx].name);
-		}
+		if (!sh_mobile_ceu_packing_supported(fmt))
+			return 0;
+	}
+
+	/* Generic pass-through */
+	formats++;
+	if (xlate) {
+		xlate->host_fmt	= fmt;
+		xlate->code	= code;
+		xlate++;
+		dev_dbg(dev, "Providing format %s in pass-through mode\n",
+			xlate->host_fmt->name);
 	}
 
 	return formats;
@@ -1029,17 +1127,15 @@
 static int get_camera_scales(struct v4l2_subdev *sd, struct v4l2_rect *rect,
 			     unsigned int *scale_h, unsigned int *scale_v)
 {
-	struct v4l2_format f;
+	struct v4l2_mbus_framefmt mf;
 	int ret;
 
-	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	ret = v4l2_subdev_call(sd, video, g_fmt, &f);
+	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
-	*scale_h = calc_generic_scale(rect->width, f.fmt.pix.width);
-	*scale_v = calc_generic_scale(rect->height, f.fmt.pix.height);
+	*scale_h = calc_generic_scale(rect->width, mf.width);
+	*scale_v = calc_generic_scale(rect->height, mf.height);
 
 	return 0;
 }
@@ -1054,32 +1150,29 @@
 	if (!ceu_rect->width) {
 		struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 		struct device *dev = icd->dev.parent;
-		struct v4l2_format f;
-		struct v4l2_pix_format *pix = &f.fmt.pix;
+		struct v4l2_mbus_framefmt mf;
 		int ret;
 		/* First time */
 
-		f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-		ret = v4l2_subdev_call(sd, video, g_fmt, &f);
+		ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
 		if (ret < 0)
 			return ret;
 
-		dev_geo(dev, "camera fmt %ux%u\n", pix->width, pix->height);
+		dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height);
 
-		if (pix->width > 2560) {
+		if (mf.width > 2560) {
 			ceu_rect->width	 = 2560;
-			ceu_rect->left	 = (pix->width - 2560) / 2;
+			ceu_rect->left	 = (mf.width - 2560) / 2;
 		} else {
-			ceu_rect->width	 = pix->width;
+			ceu_rect->width	 = mf.width;
 			ceu_rect->left	 = 0;
 		}
 
-		if (pix->height > 1920) {
+		if (mf.height > 1920) {
 			ceu_rect->height = 1920;
-			ceu_rect->top	 = (pix->height - 1920) / 2;
+			ceu_rect->top	 = (mf.height - 1920) / 2;
 		} else {
-			ceu_rect->height = pix->height;
+			ceu_rect->height = mf.height;
 			ceu_rect->top	 = 0;
 		}
 
@@ -1096,13 +1189,12 @@
 	return 0;
 }
 
-static int client_s_fmt(struct soc_camera_device *icd, struct v4l2_format *f,
-			bool ceu_can_scale)
+static int client_s_fmt(struct soc_camera_device *icd,
+			struct v4l2_mbus_framefmt *mf, bool ceu_can_scale)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->dev.parent;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-	unsigned int width = pix->width, height = pix->height, tmp_w, tmp_h;
+	unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
 	unsigned int max_width, max_height;
 	struct v4l2_cropcap cap;
 	int ret;
@@ -1116,29 +1208,29 @@
 	max_width = min(cap.bounds.width, 2560);
 	max_height = min(cap.bounds.height, 1920);
 
-	ret = v4l2_subdev_call(sd, video, s_fmt, f);
+	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf);
 	if (ret < 0)
 		return ret;
 
-	dev_geo(dev, "camera scaled to %ux%u\n", pix->width, pix->height);
+	dev_geo(dev, "camera scaled to %ux%u\n", mf->width, mf->height);
 
-	if ((width == pix->width && height == pix->height) || !ceu_can_scale)
+	if ((width == mf->width && height == mf->height) || !ceu_can_scale)
 		return 0;
 
 	/* Camera set a format, but geometry is not precise, try to improve */
-	tmp_w = pix->width;
-	tmp_h = pix->height;
+	tmp_w = mf->width;
+	tmp_h = mf->height;
 
 	/* width <= max_width && height <= max_height - guaranteed by try_fmt */
 	while ((width > tmp_w || height > tmp_h) &&
 	       tmp_w < max_width && tmp_h < max_height) {
 		tmp_w = min(2 * tmp_w, max_width);
 		tmp_h = min(2 * tmp_h, max_height);
-		pix->width = tmp_w;
-		pix->height = tmp_h;
-		ret = v4l2_subdev_call(sd, video, s_fmt, f);
+		mf->width = tmp_w;
+		mf->height = tmp_h;
+		ret = v4l2_subdev_call(sd, video, s_mbus_fmt, mf);
 		dev_geo(dev, "Camera scaled to %ux%u\n",
-			pix->width, pix->height);
+			mf->width, mf->height);
 		if (ret < 0) {
 			/* This shouldn't happen */
 			dev_err(dev, "Client failed to set format: %d\n", ret);
@@ -1156,27 +1248,26 @@
  */
 static int client_scale(struct soc_camera_device *icd, struct v4l2_rect *rect,
 			struct v4l2_rect *sub_rect, struct v4l2_rect *ceu_rect,
-			struct v4l2_format *f, bool ceu_can_scale)
+			struct v4l2_mbus_framefmt *mf, bool ceu_can_scale)
 {
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct sh_mobile_ceu_cam *cam = icd->host_priv;
 	struct device *dev = icd->dev.parent;
-	struct v4l2_format f_tmp = *f;
-	struct v4l2_pix_format *pix_tmp = &f_tmp.fmt.pix;
+	struct v4l2_mbus_framefmt mf_tmp = *mf;
 	unsigned int scale_h, scale_v;
 	int ret;
 
 	/* 5. Apply iterative camera S_FMT for camera user window. */
-	ret = client_s_fmt(icd, &f_tmp, ceu_can_scale);
+	ret = client_s_fmt(icd, &mf_tmp, ceu_can_scale);
 	if (ret < 0)
 		return ret;
 
 	dev_geo(dev, "5: camera scaled to %ux%u\n",
-		pix_tmp->width, pix_tmp->height);
+		mf_tmp.width, mf_tmp.height);
 
 	/* 6. Retrieve camera output window (g_fmt) */
 
-	/* unneeded - it is already in "f_tmp" */
+	/* unneeded - it is already in "mf_tmp" */
 
 	/* 7. Calculate new camera scales. */
 	ret = get_camera_scales(sd, rect, &scale_h, &scale_v);
@@ -1185,10 +1276,11 @@
 
 	dev_geo(dev, "7: camera scales %u:%u\n", scale_h, scale_v);
 
-	cam->cam_width		= pix_tmp->width;
-	cam->cam_height		= pix_tmp->height;
-	f->fmt.pix.width	= pix_tmp->width;
-	f->fmt.pix.height	= pix_tmp->height;
+	cam->cam_width	= mf_tmp.width;
+	cam->cam_height	= mf_tmp.height;
+	mf->width	= mf_tmp.width;
+	mf->height	= mf_tmp.height;
+	mf->colorspace	= mf_tmp.colorspace;
 
 	/*
 	 * 8. Calculate new CEU crop - apply camera scales to previously
@@ -1252,8 +1344,7 @@
 	struct v4l2_rect *cam_rect = &cam_crop.c, *ceu_rect = &cam->ceu_rect;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->dev.parent;
-	struct v4l2_format f;
-	struct v4l2_pix_format *pix = &f.fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	unsigned int scale_comb_h, scale_comb_v, scale_ceu_h, scale_ceu_v,
 		out_width, out_height;
 	u32 capsr, cflcr;
@@ -1302,26 +1393,25 @@
 	 * 5. Using actual input window and calculated combined scales calculate
 	 *    camera target output window.
 	 */
-	pix->width		= scale_down(cam_rect->width, scale_comb_h);
-	pix->height		= scale_down(cam_rect->height, scale_comb_v);
+	mf.width	= scale_down(cam_rect->width, scale_comb_h);
+	mf.height	= scale_down(cam_rect->height, scale_comb_v);
 
-	dev_geo(dev, "5: camera target %ux%u\n", pix->width, pix->height);
+	dev_geo(dev, "5: camera target %ux%u\n", mf.width, mf.height);
 
 	/* 6. - 9. */
-	pix->pixelformat	= cam->camera_fmt->fourcc;
-	pix->colorspace		= cam->camera_fmt->colorspace;
+	mf.code		= cam->code;
+	mf.field	= pcdev->field;
 
 	capsr = capture_save_reset(pcdev);
 	dev_dbg(dev, "CAPSR 0x%x, CFLCR 0x%x\n", capsr, pcdev->cflcr);
 
 	/* Make relative to camera rectangle */
-	rect->left		-= cam_rect->left;
-	rect->top		-= cam_rect->top;
+	rect->left	-= cam_rect->left;
+	rect->top	-= cam_rect->top;
 
-	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	ret = client_scale(icd, cam_rect, rect, ceu_rect, &f,
-			   pcdev->image_mode && !pcdev->is_interlaced);
+	ret = client_scale(icd, cam_rect, rect, ceu_rect, &mf,
+			   pcdev->image_mode &&
+			   V4L2_FIELD_NONE == pcdev->field);
 
 	dev_geo(dev, "6-9: %d\n", ret);
 
@@ -1368,8 +1458,7 @@
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 	struct sh_mobile_ceu_cam *cam = icd->host_priv;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
-	struct v4l2_format cam_f = *f;
-	struct v4l2_pix_format *cam_pix = &cam_f.fmt.pix;
+	struct v4l2_mbus_framefmt mf;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct device *dev = icd->dev.parent;
 	__u32 pixfmt = pix->pixelformat;
@@ -1379,18 +1468,20 @@
 	unsigned int scale_cam_h, scale_cam_v;
 	u16 scale_v, scale_h;
 	int ret;
-	bool is_interlaced, image_mode;
+	bool image_mode;
+	enum v4l2_field field;
 
 	switch (pix->field) {
-	case V4L2_FIELD_INTERLACED:
-		is_interlaced = true;
-		break;
-	case V4L2_FIELD_ANY:
 	default:
 		pix->field = V4L2_FIELD_NONE;
 		/* fall-through */
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
 	case V4L2_FIELD_NONE:
-		is_interlaced = false;
+		field = pix->field;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		field = V4L2_FIELD_INTERLACED_TB;
 		break;
 	}
 
@@ -1438,9 +1529,11 @@
 	 * 4. Calculate camera output window by applying combined scales to real
 	 *    input window.
 	 */
-	cam_pix->width = scale_down(cam_rect->width, scale_h);
-	cam_pix->height = scale_down(cam_rect->height, scale_v);
-	cam_pix->pixelformat = xlate->cam_fmt->fourcc;
+	mf.width	= scale_down(cam_rect->width, scale_h);
+	mf.height	= scale_down(cam_rect->height, scale_v);
+	mf.field	= pix->field;
+	mf.colorspace	= pix->colorspace;
+	mf.code		= xlate->code;
 
 	switch (pixfmt) {
 	case V4L2_PIX_FMT_NV12:
@@ -1453,51 +1546,61 @@
 		image_mode = false;
 	}
 
-	dev_geo(dev, "4: camera output %ux%u\n",
-		cam_pix->width, cam_pix->height);
+	dev_geo(dev, "4: camera output %ux%u\n", mf.width, mf.height);
 
 	/* 5. - 9. */
-	ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &cam_f,
-			   image_mode && !is_interlaced);
+	ret = client_scale(icd, cam_rect, &cam_subrect, &ceu_rect, &mf,
+			   image_mode && V4L2_FIELD_NONE == field);
 
 	dev_geo(dev, "5-9: client scale %d\n", ret);
 
 	/* Done with the camera. Now see if we can improve the result */
 
 	dev_dbg(dev, "Camera %d fmt %ux%u, requested %ux%u\n",
-		ret, cam_pix->width, cam_pix->height, pix->width, pix->height);
+		ret, mf.width, mf.height, pix->width, pix->height);
 	if (ret < 0)
 		return ret;
 
+	if (mf.code != xlate->code)
+		return -EINVAL;
+
 	/* 10. Use CEU scaling to scale to the requested user window. */
 
 	/* We cannot scale up */
-	if (pix->width > cam_pix->width)
-		pix->width = cam_pix->width;
+	if (pix->width > mf.width)
+		pix->width = mf.width;
 	if (pix->width > ceu_rect.width)
 		pix->width = ceu_rect.width;
 
-	if (pix->height > cam_pix->height)
-		pix->height = cam_pix->height;
+	if (pix->height > mf.height)
+		pix->height = mf.height;
 	if (pix->height > ceu_rect.height)
 		pix->height = ceu_rect.height;
 
-	/* Let's rock: scale pix->{width x height} down to width x height */
-	scale_h = calc_scale(ceu_rect.width, &pix->width);
-	scale_v = calc_scale(ceu_rect.height, &pix->height);
+	pix->colorspace = mf.colorspace;
+
+	if (image_mode) {
+		/* Scale pix->{width x height} down to width x height */
+		scale_h = calc_scale(ceu_rect.width, &pix->width);
+		scale_v = calc_scale(ceu_rect.height, &pix->height);
+
+		pcdev->cflcr = scale_h | (scale_v << 16);
+	} else {
+		pix->width = ceu_rect.width;
+		pix->height = ceu_rect.height;
+		scale_h = scale_v = 0;
+		pcdev->cflcr = 0;
+	}
 
 	dev_geo(dev, "10: W: %u : 0x%x = %u, H: %u : 0x%x = %u\n",
 		ceu_rect.width, scale_h, pix->width,
 		ceu_rect.height, scale_v, pix->height);
 
-	pcdev->cflcr = scale_h | (scale_v << 16);
+	cam->code		= xlate->code;
+	cam->ceu_rect		= ceu_rect;
+	icd->current_fmt	= xlate;
 
-	icd->buswidth = xlate->buswidth;
-	icd->current_fmt = xlate->host_fmt;
-	cam->camera_fmt = xlate->cam_fmt;
-	cam->ceu_rect = ceu_rect;
-
-	pcdev->is_interlaced = is_interlaced;
+	pcdev->field = field;
 	pcdev->image_mode = image_mode;
 
 	return 0;
@@ -1509,6 +1612,7 @@
 	const struct soc_camera_format_xlate *xlate;
 	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct v4l2_mbus_framefmt mf;
 	__u32 pixfmt = pix->pixelformat;
 	int width, height;
 	int ret;
@@ -1527,18 +1631,27 @@
 	width = pix->width;
 	height = pix->height;
 
-	pix->bytesperline = pix->width *
-		DIV_ROUND_UP(xlate->host_fmt->depth, 8);
-	pix->sizeimage = pix->height * pix->bytesperline;
-
-	pix->pixelformat = xlate->cam_fmt->fourcc;
+	pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt);
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
+	pix->sizeimage = height * pix->bytesperline;
 
 	/* limit to sensor capabilities */
-	ret = v4l2_subdev_call(sd, video, try_fmt, f);
-	pix->pixelformat = pixfmt;
+	mf.width	= pix->width;
+	mf.height	= pix->height;
+	mf.field	= pix->field;
+	mf.code		= xlate->code;
+	mf.colorspace	= pix->colorspace;
+
+	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
+	pix->width	= mf.width;
+	pix->height	= mf.height;
+	pix->field	= mf.field;
+	pix->colorspace	= mf.colorspace;
+
 	switch (pixfmt) {
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV21:
@@ -1547,21 +1660,25 @@
 		/* FIXME: check against rect_max after converting soc-camera */
 		/* We can scale precisely, need a bigger image from camera */
 		if (pix->width < width || pix->height < height) {
-			int tmp_w = pix->width, tmp_h = pix->height;
-			pix->width = 2560;
-			pix->height = 1920;
-			ret = v4l2_subdev_call(sd, video, try_fmt, f);
+			/*
+			 * We presume, the sensor behaves sanely, i.e., if
+			 * requested a bigger rectangle, it will not return a
+			 * smaller one.
+			 */
+			mf.width = 2560;
+			mf.height = 1920;
+			ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
 			if (ret < 0) {
 				/* Shouldn't actually happen... */
 				dev_err(icd->dev.parent,
-					"FIXME: try_fmt() returned %d\n", ret);
-				pix->width = tmp_w;
-				pix->height = tmp_h;
+					"FIXME: client try_fmt() = %d\n", ret);
+				return ret;
 			}
 		}
-		if (pix->width > width)
+		/* We will scale exactly */
+		if (mf.width > width)
 			pix->width = width;
-		if (pix->height > height)
+		if (mf.height > height)
 			pix->height = height;
 	}
 
@@ -1573,10 +1690,12 @@
 {
 	int i;
 
-	/* This is for locking debugging only. I removed spinlocks and now I
+	/*
+	 * This is for locking debugging only. I removed spinlocks and now I
 	 * check whether .prepare is ever called on a linked buffer, or whether
 	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-	 * it hadn't triggered */
+	 * it hadn't triggered
+	 */
 	for (i = 0; i < p->count; i++) {
 		struct sh_mobile_ceu_buffer *buf;
 
@@ -1624,8 +1743,7 @@
 				       &sh_mobile_ceu_videobuf_ops,
 				       icd->dev.parent, &pcdev->lock,
 				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				       pcdev->is_interlaced ?
-				       V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
+				       pcdev->field,
 				       sizeof(struct sh_mobile_ceu_buffer),
 				       icd);
 }
@@ -1654,7 +1772,7 @@
 
 	switch (ctrl->id) {
 	case V4L2_CID_SHARPNESS:
-		switch (icd->current_fmt->fourcc) {
+		switch (icd->current_fmt->host_fmt->fourcc) {
 		case V4L2_PIX_FMT_NV12:
 		case V4L2_PIX_FMT_NV21:
 		case V4L2_PIX_FMT_NV16:
@@ -1836,7 +1954,7 @@
 		.pm	= &sh_mobile_ceu_dev_pm_ops,
 	},
 	.probe		= sh_mobile_ceu_probe,
-	.remove		= __exit_p(sh_mobile_ceu_remove),
+	.remove		= __devexit_p(sh_mobile_ceu_remove),
 };
 
 static int __init sh_mobile_ceu_init(void)
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 4a7711c..cbf8087 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1007,8 +1007,8 @@
 	else if (cam->stream != STREAM_OFF) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "URB timeout reached. The camera is misconfigured. "
-		       "To use it, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "To use it, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1734,7 +1734,8 @@
 
 	cam = container_of(kref, struct sn9c102_device, kref);
 
-	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
+	DBG(2, "V4L2 device %s deregistered",
+	    video_device_node_name(cam->v4ldev));
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_unregister_device(cam->v4ldev);
 	usb_put_dev(cam->usbdev);
@@ -1791,8 +1792,8 @@
 	}
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is already in use",
-		       cam->v4ldev->num);
+		DBG(2, "Device %s is already in use",
+		    video_device_node_name(cam->v4ldev));
 		DBG(3, "Simultaneous opens are not supported");
 		/*
 		   open() must follow the open flags and should block
@@ -1845,7 +1846,7 @@
 	cam->frame_count = 0;
 	sn9c102_empty_framequeues(cam);
 
-	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
+	DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
 
 out:
 	mutex_unlock(&cam->open_mutex);
@@ -1870,7 +1871,7 @@
 	cam->users--;
 	wake_up_interruptible_nr(&cam->wait_open, 1);
 
-	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
+	DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
 
 	kref_put(&cam->kref, sn9c102_release_resources);
 
@@ -2433,8 +2434,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -2446,8 +2447,8 @@
 	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -2690,8 +2691,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -2702,8 +2703,8 @@
 	    nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -2748,9 +2749,9 @@
 	err += sn9c102_set_compression(cam, &jc);
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
-		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
-		       "problems. To use the camera, close and open "
-		       "/dev/video%d again.", cam->v4ldev->num);
+		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
+		       "To use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -3328,7 +3329,6 @@
 
 	strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
 	cam->v4ldev->fops = &sn9c102_fops;
-	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
 	cam->v4ldev->parent = &udev->dev;
 
@@ -3346,7 +3346,8 @@
 		goto fail;
 	}
 
-	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
+	DBG(2, "V4L2 device registered as %s",
+	    video_device_node_name(cam->v4ldev));
 
 	video_set_drvdata(cam->v4ldev, cam);
 	cam->module_param.force_munmap = force_munmap[dev_nr];
@@ -3398,9 +3399,9 @@
 	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is open! Deregistration and "
-		       "memory deallocation are deferred.",
-		    cam->v4ldev->num);
+		DBG(2, "Device %s is open! Deregistration and memory "
+		       "deallocation are deferred.",
+		    video_device_node_name(cam->v4ldev));
 		cam->state |= DEV_MISCONFIGURED;
 		sn9c102_stop_transfer(cam);
 		cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 95fdeb2..6b3fbcc 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -31,6 +31,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-core.h>
+#include <media/soc_mediabus.h>
 
 /* Default to VGA resolution */
 #define DEFAULT_WIDTH	640
@@ -40,18 +41,6 @@
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);		/* Protects the list of hosts */
 
-const struct soc_camera_data_format *soc_camera_format_by_fourcc(
-	struct soc_camera_device *icd, unsigned int fourcc)
-{
-	unsigned int i;
-
-	for (i = 0; i < icd->num_formats; i++)
-		if (icd->formats[i].fourcc == fourcc)
-			return icd->formats + i;
-	return NULL;
-}
-EXPORT_SYMBOL(soc_camera_format_by_fourcc);
-
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
 	struct soc_camera_device *icd, unsigned int fourcc)
 {
@@ -207,21 +196,26 @@
 /* Always entered with .video_lock held */
 static int soc_camera_init_user_formats(struct soc_camera_device *icd)
 {
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	int i, fmts = 0, ret;
+	int i, fmts = 0, raw_fmts = 0, ret;
+	enum v4l2_mbus_pixelcode code;
+
+	while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
+		raw_fmts++;
 
 	if (!ici->ops->get_formats)
 		/*
 		 * Fallback mode - the host will have to serve all
 		 * sensor-provided formats one-to-one to the user
 		 */
-		fmts = icd->num_formats;
+		fmts = raw_fmts;
 	else
 		/*
 		 * First pass - only count formats this host-sensor
 		 * configuration can provide
 		 */
-		for (i = 0; i < icd->num_formats; i++) {
+		for (i = 0; i < raw_fmts; i++) {
 			ret = ici->ops->get_formats(icd, i, NULL);
 			if (ret < 0)
 				return ret;
@@ -242,11 +236,12 @@
 
 	/* Second pass - actually fill data formats */
 	fmts = 0;
-	for (i = 0; i < icd->num_formats; i++)
+	for (i = 0; i < raw_fmts; i++)
 		if (!ici->ops->get_formats) {
-			icd->user_formats[i].host_fmt = icd->formats + i;
-			icd->user_formats[i].cam_fmt = icd->formats + i;
-			icd->user_formats[i].buswidth = icd->formats[i].depth;
+			v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code);
+			icd->user_formats[i].host_fmt =
+				soc_mbus_get_fmtdesc(code);
+			icd->user_formats[i].code = code;
 		} else {
 			ret = ici->ops->get_formats(icd, i,
 						    &icd->user_formats[fmts]);
@@ -255,7 +250,7 @@
 			fmts += ret;
 		}
 
-	icd->current_fmt = icd->user_formats[0].host_fmt;
+	icd->current_fmt = &icd->user_formats[0];
 
 	return 0;
 
@@ -281,7 +276,7 @@
 #define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
 	((x) >> 24) & 0xff
 
-/* Called with .vb_lock held */
+/* Called with .vb_lock held, or from the first open(2), see comment there */
 static int soc_camera_set_fmt(struct soc_camera_file *icf,
 			      struct v4l2_format *f)
 {
@@ -302,7 +297,7 @@
 	if (ret < 0) {
 		return ret;
 	} else if (!icd->current_fmt ||
-		   icd->current_fmt->fourcc != pix->pixelformat) {
+		   icd->current_fmt->host_fmt->fourcc != pix->pixelformat) {
 		dev_err(&icd->dev,
 			"Host driver hasn't set up current format correctly!\n");
 		return -EINVAL;
@@ -310,6 +305,7 @@
 
 	icd->user_width		= pix->width;
 	icd->user_height	= pix->height;
+	icd->colorspace		= pix->colorspace;
 	icf->vb_vidq.field	=
 		icd->field	= pix->field;
 
@@ -369,8 +365,9 @@
 				.width		= icd->user_width,
 				.height		= icd->user_height,
 				.field		= icd->field,
-				.pixelformat	= icd->current_fmt->fourcc,
-				.colorspace	= icd->current_fmt->colorspace,
+				.colorspace	= icd->colorspace,
+				.pixelformat	=
+					icd->current_fmt->host_fmt->fourcc,
 			},
 		};
 
@@ -390,7 +387,12 @@
 			goto eiciadd;
 		}
 
-		/* Try to configure with default parameters */
+		/*
+		 * Try to configure with default parameters. Notice: this is the
+		 * very first open, so, we cannot race against other calls,
+		 * apart from someone else calling open() simultaneously, but
+		 * .video_lock is protecting us against it.
+		 */
 		ret = soc_camera_set_fmt(icf, &f);
 		if (ret < 0)
 			goto esfmt;
@@ -534,7 +536,7 @@
 {
 	struct soc_camera_file *icf = file->private_data;
 	struct soc_camera_device *icd = icf->icd;
-	const struct soc_camera_data_format *format;
+	const struct soc_mbus_pixelfmt *format;
 
 	WARN_ON(priv != file->private_data);
 
@@ -543,7 +545,8 @@
 
 	format = icd->user_formats[f->index].host_fmt;
 
-	strlcpy(f->description, format->name, sizeof(f->description));
+	if (format->name)
+		strlcpy(f->description, format->name, sizeof(f->description));
 	f->pixelformat = format->fourcc;
 	return 0;
 }
@@ -560,12 +563,15 @@
 	pix->width		= icd->user_width;
 	pix->height		= icd->user_height;
 	pix->field		= icf->vb_vidq.field;
-	pix->pixelformat	= icd->current_fmt->fourcc;
-	pix->bytesperline	= pix->width *
-		DIV_ROUND_UP(icd->current_fmt->depth, 8);
+	pix->pixelformat	= icd->current_fmt->host_fmt->fourcc;
+	pix->bytesperline	= soc_mbus_bytes_per_line(pix->width,
+						icd->current_fmt->host_fmt);
+	pix->colorspace		= icd->colorspace;
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
 	pix->sizeimage		= pix->height * pix->bytesperline;
 	dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
-		icd->current_fmt->fourcc);
+		icd->current_fmt->host_fmt->fourcc);
 	return 0;
 }
 
@@ -621,8 +627,10 @@
 
 	mutex_lock(&icd->video_lock);
 
-	/* This calls buf_release from host driver's videobuf_queue_ops for all
-	 * remaining buffers. When the last buffer is freed, stop capture */
+	/*
+	 * This calls buf_release from host driver's videobuf_queue_ops for all
+	 * remaining buffers. When the last buffer is freed, stop capture
+	 */
 	videobuf_streamoff(&icf->vb_vidq);
 
 	v4l2_subdev_call(sd, video, s_stream, 0);
@@ -892,7 +900,7 @@
 	struct soc_camera_link *icl = to_soc_camera_link(icd);
 	struct device *control = NULL;
 	struct v4l2_subdev *sd;
-	struct v4l2_format f = {.type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
+	struct v4l2_mbus_framefmt mf;
 	int ret;
 
 	dev_info(dev, "Probing %s\n", dev_name(dev));
@@ -963,9 +971,11 @@
 
 	/* Try to improve our guess of a reasonable window format */
 	sd = soc_camera_to_subdev(icd);
-	if (!v4l2_subdev_call(sd, video, g_fmt, &f)) {
-		icd->user_width		= f.fmt.pix.width;
-		icd->user_height	= f.fmt.pix.height;
+	if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
+		icd->user_width		= mf.width;
+		icd->user_height	= mf.height;
+		icd->colorspace		= mf.colorspace;
+		icd->field		= mf.field;
 	}
 
 	/* Do we have to sysfs_remove_link() before device_unregister()? */
@@ -1004,8 +1014,10 @@
 	return ret;
 }
 
-/* This is called on device_unregister, which only means we have to disconnect
- * from the host, but not remove ourselves from the device list */
+/*
+ * This is called on device_unregister, which only means we have to disconnect
+ * from the host, but not remove ourselves from the device list
+ */
 static int soc_camera_remove(struct device *dev)
 {
 	struct soc_camera_device *icd = to_soc_camera_dev(dev);
@@ -1205,8 +1217,10 @@
 	}
 
 	if (num < 0)
-		/* ok, we have 256 cameras on this host...
-		 * man, stay reasonable... */
+		/*
+		 * ok, we have 256 cameras on this host...
+		 * man, stay reasonable...
+		 */
 		return -ENOMEM;
 
 	icd->devnum		= num;
@@ -1268,7 +1282,6 @@
 	vdev->fops		= &soc_camera_fops;
 	vdev->ioctl_ops		= &soc_camera_ioctl_ops;
 	vdev->release		= video_device_release;
-	vdev->minor		= -1;
 	vdev->tvnorms		= V4L2_STD_UNKNOWN;
 
 	icd->vdev = vdev;
@@ -1291,8 +1304,7 @@
 	    !icd->ops->set_bus_param)
 		return -EINVAL;
 
-	ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER,
-				    icd->vdev->minor);
+	ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret < 0) {
 		dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
 		return ret;
@@ -1335,9 +1347,11 @@
 	return ret;
 }
 
-/* Only called on rmmod for each platform device, since they are not
+/*
+ * Only called on rmmod for each platform device, since they are not
  * hot-pluggable. Now we know, that all our users - hosts and devices have
- * been unloaded already */
+ * been unloaded already
+ */
 static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
 {
 	struct soc_camera_device *icd = platform_get_drvdata(pdev);
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index b6a575c..10b003a 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -22,7 +22,6 @@
 
 struct soc_camera_platform_priv {
 	struct v4l2_subdev subdev;
-	struct soc_camera_data_format format;
 };
 
 static struct soc_camera_platform_priv *get_priv(struct platform_device *pdev)
@@ -58,36 +57,36 @@
 }
 
 static int soc_camera_platform_try_fmt(struct v4l2_subdev *sd,
-				       struct v4l2_format *f)
+				       struct v4l2_mbus_framefmt *mf)
 {
 	struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	pix->width = p->format.width;
-	pix->height = p->format.height;
+	mf->width	= p->format.width;
+	mf->height	= p->format.height;
+	mf->code	= p->format.code;
+	mf->colorspace	= p->format.colorspace;
+
 	return 0;
 }
 
-static void soc_camera_platform_video_probe(struct soc_camera_device *icd,
-					    struct platform_device *pdev)
-{
-	struct soc_camera_platform_priv *priv = get_priv(pdev);
-	struct soc_camera_platform_info *p = pdev->dev.platform_data;
-
-	priv->format.name = p->format_name;
-	priv->format.depth = p->format_depth;
-	priv->format.fourcc = p->format.pixelformat;
-	priv->format.colorspace = p->format.colorspace;
-
-	icd->formats = &priv->format;
-	icd->num_formats = 1;
-}
-
 static struct v4l2_subdev_core_ops platform_subdev_core_ops;
 
+static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, int index,
+					enum v4l2_mbus_pixelcode *code)
+{
+	struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
+
+	if (index)
+		return -EINVAL;
+
+	*code = p->format.code;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
 	.s_stream	= soc_camera_platform_s_stream,
-	.try_fmt	= soc_camera_platform_try_fmt,
+	.try_mbus_fmt	= soc_camera_platform_try_fmt,
+	.enum_mbus_fmt	= soc_camera_platform_enum_fmt,
 };
 
 static struct v4l2_subdev_ops platform_subdev_ops = {
@@ -128,13 +127,10 @@
 	/* Set the control device reference */
 	dev_set_drvdata(&icd->dev, &pdev->dev);
 
-	icd->y_skip_top		= 0;
-	icd->ops		= &soc_camera_platform_ops;
+	icd->ops = &soc_camera_platform_ops;
 
 	ici = to_soc_camera_host(icd->dev.parent);
 
-	soc_camera_platform_video_probe(icd, pdev);
-
 	v4l2_subdev_init(&priv->subdev, &platform_subdev_ops);
 	v4l2_set_subdevdata(&priv->subdev, p);
 	strncpy(priv->subdev.name, dev_name(&pdev->dev), V4L2_SUBDEV_NAME_SIZE);
diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c
new file mode 100644
index 0000000..f8d5c87
--- /dev/null
+++ b/drivers/media/video/soc_mediabus.c
@@ -0,0 +1,157 @@
+/*
+ * soc-camera media bus helper routines
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/soc_mediabus.h>
+
+#define MBUS_IDX(f) (V4L2_MBUS_FMT_ ## f - V4L2_MBUS_FMT_FIXED - 1)
+
+static const struct soc_mbus_pixelfmt mbus_fmt[] = {
+	[MBUS_IDX(YUYV8_2X8_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_YUYV,
+		.name			= "YUYV",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(YVYU8_2X8_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_YVYU,
+		.name			= "YVYU",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(YUYV8_2X8_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_UYVY,
+		.name			= "UYVY",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(YVYU8_2X8_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_VYUY,
+		.name			= "VYUY",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(RGB555_2X8_PADHI_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_RGB555,
+		.name			= "RGB555",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(RGB555_2X8_PADHI_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_RGB555X,
+		.name			= "RGB555X",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(RGB565_2X8_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_RGB565,
+		.name			= "RGB565",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(RGB565_2X8_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_RGB565X,
+		.name			= "RGB565X",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(SBGGR8_1X8)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR8,
+		.name			= "Bayer 8 BGGR",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(SBGGR10_1X10)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.name			= "Bayer 10 BGGR",
+		.bits_per_sample	= 10,
+		.packing		= SOC_MBUS_PACKING_EXTEND16,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(GREY8_1X8)] = {
+		.fourcc			= V4L2_PIX_FMT_GREY,
+		.name			= "Grey",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_NONE,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(Y10_1X10)] = {
+		.fourcc			= V4L2_PIX_FMT_Y10,
+		.name			= "Grey 10bit",
+		.bits_per_sample	= 10,
+		.packing		= SOC_MBUS_PACKING_EXTEND16,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(SBGGR10_2X8_PADHI_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.name			= "Bayer 10 BGGR",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(SBGGR10_2X8_PADLO_LE)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.name			= "Bayer 10 BGGR",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADLO,
+		.order			= SOC_MBUS_ORDER_LE,
+	}, [MBUS_IDX(SBGGR10_2X8_PADHI_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.name			= "Bayer 10 BGGR",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADHI,
+		.order			= SOC_MBUS_ORDER_BE,
+	}, [MBUS_IDX(SBGGR10_2X8_PADLO_BE)] = {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.name			= "Bayer 10 BGGR",
+		.bits_per_sample	= 8,
+		.packing		= SOC_MBUS_PACKING_2X8_PADLO,
+		.order			= SOC_MBUS_ORDER_BE,
+	},
+};
+
+s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
+{
+	switch (mf->packing) {
+	case SOC_MBUS_PACKING_NONE:
+		return width * mf->bits_per_sample / 8;
+	case SOC_MBUS_PACKING_2X8_PADHI:
+	case SOC_MBUS_PACKING_2X8_PADLO:
+	case SOC_MBUS_PACKING_EXTEND16:
+		return width * 2;
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(soc_mbus_bytes_per_line);
+
+const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
+	enum v4l2_mbus_pixelcode code)
+{
+	if ((unsigned int)(code - V4L2_MBUS_FMT_FIXED) > ARRAY_SIZE(mbus_fmt))
+		return NULL;
+	return mbus_fmt + code - V4L2_MBUS_FMT_FIXED - 1;
+}
+EXPORT_SYMBOL(soc_mbus_get_fmtdesc);
+
+static int __init soc_mbus_init(void)
+{
+	return 0;
+}
+
+static void __exit soc_mbus_exit(void)
+{
+}
+
+module_init(soc_mbus_init);
+module_exit(soc_mbus_exit);
+
+MODULE_DESCRIPTION("soc-camera media bus interface");
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index 6b41865..f07a0f6 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -1307,7 +1307,6 @@
 
 static struct video_device stk_v4l_data = {
 	.name = "stkwebcam",
-	.minor = -1,
 	.tvnorms = V4L2_STD_UNKNOWN,
 	.current_norm = V4L2_STD_UNKNOWN,
 	.fops = &v4l_stk_fops,
@@ -1327,8 +1326,8 @@
 	if (err)
 		STK_ERROR("v4l registration failed\n");
 	else
-		STK_INFO("Syntek USB2.0 Camera is now controlling video device"
-			" /dev/video%d\n", dev->vdev.num);
+		STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n",
+			 video_device_node_name(&dev->vdev));
 	return err;
 }
 
@@ -1418,8 +1417,8 @@
 	wake_up_interruptible(&dev->wait_frame);
 	stk_remove_sysfs_files(&dev->vdev);
 
-	STK_INFO("Syntek USB2.0 Camera release resources "
-		"video device /dev/video%d\n", dev->vdev.num);
+	STK_INFO("Syntek USB2.0 Camera release resources device %s\n",
+		 video_device_node_name(&dev->vdev));
 
 	video_unregister_device(&dev->vdev);
 }
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index eaada39..a057824 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1921,7 +1921,6 @@
 static struct video_device saa_template = {
 	.name = "SAA7146A",
 	.fops = &saa_fops,
-	.minor = -1,
 	.release = video_device_release_empty,
 };
 
@@ -1972,7 +1971,6 @@
 
 	saa->id = pdev->device;
 	saa->irq = pdev->irq;
-	saa->video_dev.minor = -1;
 	saa->saa7146_adr = pci_resource_start(pdev, 0);
 	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
 
@@ -2134,7 +2132,7 @@
 	free_irq(saa->irq, saa);
 	if (saa->saa7146_mem)
 		iounmap(saa->saa7146_mem);
-	if (saa->video_dev.minor != -1)
+	if (video_is_registered(&saa->video_dev))
 		video_unregister_device(&saa->video_dev);
 }
 
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 6a91714..5938ad8 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1405,7 +1405,6 @@
 	.name =		"STV0680 USB camera",
 	.fops =         &stv680_fops,
 	.release =	video_device_release,
-	.minor = 	-1,
 };
 
 static int stv680_probe (struct usb_interface *intf, const struct usb_device_id *id)
@@ -1467,8 +1466,8 @@
 		retval = -EIO;
 		goto error_vdev;
 	}
-	PDEBUG(0, "STV(i): registered new video device: video%d",
-		stv680->vdev->num);
+	PDEBUG(0, "STV(i): registered new video device: %s",
+		video_device_node_name(stv680->vdev));
 
 	usb_set_intfdata (intf, stv680);
 	retval = stv680_create_sysfs_files(stv680->vdev);
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index 269ab04..5b801a6 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -29,7 +29,7 @@
 #include <media/tw9910.h>
 
 #define GET_ID(val)  ((val & 0xF8) >> 3)
-#define GET_ReV(val) (val & 0x07)
+#define GET_REV(val) (val & 0x07)
 
 /*
  * register offset
@@ -117,7 +117,7 @@
 #define LCTL24		0x68
 #define LCTL25		0x69
 #define LCTL26		0x6A
-#define HSGEGIN		0x6B
+#define HSBEGIN		0x6B
 #define HSEND		0x6C
 #define OVSDLY		0x6D
 #define OVSEND		0x6E
@@ -152,7 +152,10 @@
 			 /* 1 : non-auto */
 #define VSCTL       0x08 /* 1 : Vertical out ctrl by DVALID */
 			 /* 0 : Vertical out ctrl by HACTIVE and DVALID */
-#define OEN         0x04 /* Output Enable together with TRI_SEL. */
+#define OEN_TRI_SEL_MASK	0x07
+#define OEN_TRI_SEL_ALL_ON	0x00 /* Enable output for Rev0/Rev1 */
+#define OEN_TRI_SEL_ALL_OFF_r0	0x06 /* All tri-stated for Rev0 */
+#define OEN_TRI_SEL_ALL_OFF_r1	0x07 /* All tri-stated for Rev1 */
 
 /* OUTCTR1 */
 #define VSP_LO      0x00 /* 0 : VS pin output polarity is active low */
@@ -178,11 +181,18 @@
 			  * but all register content remain unchanged.
 			  * This bit is self-resetting.
 			  */
+#define ACNTL1_PDN_MASK	0x0e
+#define CLK_PDN		0x08 /* system clock power down */
+#define Y_PDN		0x04 /* Luma ADC power down */
+#define C_PDN		0x02 /* Chroma ADC power down */
+
+/* ACNTL2 */
+#define ACNTL2_PDN_MASK	0x40
+#define PLL_PDN		0x40 /* PLL power down */
 
 /* VBICNTL */
-/* RTSEL : control the real time signal
-*          output from the MPOUT pin
-*/
+
+/* RTSEL : control the real time signal output from the MPOUT pin */
 #define RTSEL_MASK  0x07
 #define RTSEL_VLOSS 0x00 /* 0000 = Video loss */
 #define RTSEL_HLOCK 0x01 /* 0001 = H-lock */
@@ -226,28 +236,7 @@
 	struct v4l2_subdev                subdev;
 	struct tw9910_video_info       *info;
 	const struct tw9910_scale_ctrl *scale;
-};
-
-/*
- * register settings
- */
-
-#define ENDMARKER { 0xff, 0xff }
-
-static const struct regval_list tw9910_default_regs[] =
-{
-	{ OPFORM,  0x00 },
-	{ OUTCTR1, VSP_LO | VSSL_VVALID | HSP_HI | HSSL_HSYNC },
-	ENDMARKER,
-};
-
-static const struct soc_camera_data_format tw9910_color_fmt[] = {
-	{
-		.name       = "VYUY",
-		.fourcc     = V4L2_PIX_FMT_VYUY,
-		.depth      = 16,
-		.colorspace = V4L2_COLORSPACE_SMPTE170M,
-	}
+	u32                             revision;
 };
 
 static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = {
@@ -340,13 +329,6 @@
 	},
 };
 
-static const struct tw9910_cropping_ctrl tw9910_cropping_ctrl = {
-	.vdelay  = 0x0012,
-	.vactive = 0x00F0,
-	.hdelay  = 0x0010,
-	.hactive = 0x02D0,
-};
-
 static const struct tw9910_hsync_ctrl tw9910_hsync_ctrl = {
 	.start = 0x0260,
 	.end   = 0x0300,
@@ -361,6 +343,19 @@
 			    subdev);
 }
 
+static int tw9910_mask_set(struct i2c_client *client, u8 command,
+			   u8 mask, u8 set)
+{
+	s32 val = i2c_smbus_read_byte_data(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return i2c_smbus_write_byte_data(client, command, val);
+}
+
 static int tw9910_set_scale(struct i2c_client *client,
 			    const struct tw9910_scale_ctrl *scale)
 {
@@ -383,47 +378,14 @@
 	return ret;
 }
 
-static int tw9910_set_cropping(struct i2c_client *client,
-			       const struct tw9910_cropping_ctrl *cropping)
-{
-	int ret;
-
-	ret = i2c_smbus_write_byte_data(client, CROP_HI,
-					(cropping->vdelay  & 0x0300) >> 2 |
-					(cropping->vactive & 0x0300) >> 4 |
-					(cropping->hdelay  & 0x0300) >> 6 |
-					(cropping->hactive & 0x0300) >> 8);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_smbus_write_byte_data(client, VDELAY_LO,
-					cropping->vdelay & 0x00FF);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_smbus_write_byte_data(client, VACTIVE_LO,
-					cropping->vactive & 0x00FF);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_smbus_write_byte_data(client, HDELAY_LO,
-					cropping->hdelay & 0x00FF);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_smbus_write_byte_data(client, HACTIVE_LO,
-					cropping->hactive & 0x00FF);
-
-	return ret;
-}
-
 static int tw9910_set_hsync(struct i2c_client *client,
 			    const struct tw9910_hsync_ctrl *hsync)
 {
+	struct tw9910_priv *priv = to_tw9910(client);
 	int ret;
 
 	/* bit 10 - 3 */
-	ret = i2c_smbus_write_byte_data(client, HSGEGIN,
+	ret = i2c_smbus_write_byte_data(client, HSBEGIN,
 					(hsync->start & 0x07F8) >> 3);
 	if (ret < 0)
 		return ret;
@@ -434,52 +396,43 @@
 	if (ret < 0)
 		return ret;
 
+	/* So far only revisions 0 and 1 have been seen */
 	/* bit 2 - 0 */
-	ret = i2c_smbus_read_byte_data(client, HSLOWCTL);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_smbus_write_byte_data(client, HSLOWCTL,
-					(ret & 0x88)                 |
-					(hsync->start & 0x0007) << 4 |
-					(hsync->end   & 0x0007));
+	if (1 == priv->revision)
+		ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
+				      (hsync->start & 0x0007) << 4 |
+				      (hsync->end   & 0x0007));
 
 	return ret;
 }
 
-static int tw9910_write_array(struct i2c_client *client,
-			      const struct regval_list *vals)
-{
-	while (vals->reg_num != 0xff) {
-		int ret = i2c_smbus_write_byte_data(client,
-						    vals->reg_num,
-						    vals->value);
-		if (ret < 0)
-			return ret;
-		vals++;
-	}
-	return 0;
-}
-
-static int tw9910_mask_set(struct i2c_client *client, u8 command,
-			   u8 mask, u8 set)
-{
-	s32 val = i2c_smbus_read_byte_data(client, command);
-	if (val < 0)
-		return val;
-
-	val &= ~mask;
-	val |= set & mask;
-
-	return i2c_smbus_write_byte_data(client, command, val);
-}
-
 static void tw9910_reset(struct i2c_client *client)
 {
-	i2c_smbus_write_byte_data(client, ACNTL1, SRESET);
+	tw9910_mask_set(client, ACNTL1, SRESET, SRESET);
 	msleep(1);
 }
 
+static int tw9910_power(struct i2c_client *client, int enable)
+{
+	int ret;
+	u8 acntl1;
+	u8 acntl2;
+
+	if (enable) {
+		acntl1 = 0;
+		acntl2 = 0;
+	} else {
+		acntl1 = CLK_PDN | Y_PDN | C_PDN;
+		acntl2 = PLL_PDN;
+	}
+
+	ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1);
+	if (ret < 0)
+		return ret;
+
+	return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
+}
+
 static const struct tw9910_scale_ctrl*
 tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
 {
@@ -518,27 +471,62 @@
 {
 	struct i2c_client *client = sd->priv;
 	struct tw9910_priv *priv = to_tw9910(client);
+	u8 val;
+	int ret;
 
-	if (!enable)
-		return 0;
+	if (!enable) {
+		switch (priv->revision) {
+		case 0:
+			val = OEN_TRI_SEL_ALL_OFF_r0;
+			break;
+		case 1:
+			val = OEN_TRI_SEL_ALL_OFF_r1;
+			break;
+		default:
+			dev_err(&client->dev, "un-supported revision\n");
+			return -EINVAL;
+		}
+	} else {
+		val = OEN_TRI_SEL_ALL_ON;
 
-	if (!priv->scale) {
-		dev_err(&client->dev, "norm select error\n");
-		return -EPERM;
+		if (!priv->scale) {
+			dev_err(&client->dev, "norm select error\n");
+			return -EPERM;
+		}
+
+		dev_dbg(&client->dev, "%s %dx%d\n",
+			priv->scale->name,
+			priv->scale->width,
+			priv->scale->height);
 	}
 
-	dev_dbg(&client->dev, "%s %dx%d\n",
-		 priv->scale->name,
-		 priv->scale->width,
-		 priv->scale->height);
+	ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val);
+	if (ret < 0)
+		return ret;
 
-	return 0;
+	return tw9910_power(client, enable);
 }
 
 static int tw9910_set_bus_param(struct soc_camera_device *icd,
 				unsigned long flags)
 {
-	return 0;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct i2c_client *client = sd->priv;
+	u8 val = VSSL_VVALID | HSSL_DVALID;
+
+	/*
+	 * set OUTCTR1
+	 *
+	 * We use VVALID and DVALID signals to control VSYNC and HSYNC
+	 * outputs, in this mode their polarity is inverted.
+	 */
+	if (flags & SOCAM_HSYNC_ACTIVE_LOW)
+		val |= HSP_HI;
+
+	if (flags & SOCAM_VSYNC_ACTIVE_LOW)
+		val |= VSP_HI;
+
+	return i2c_smbus_write_byte_data(client, OUTCTR1, val);
 }
 
 static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
@@ -548,6 +536,7 @@
 	struct soc_camera_link *icl = to_soc_camera_link(icd);
 	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
 		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
+		SOCAM_VSYNC_ACTIVE_LOW  | SOCAM_HSYNC_ACTIVE_LOW  |
 		SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
 
 	return soc_camera_apply_sensor_flags(icl, flags);
@@ -576,8 +565,11 @@
 static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
 			       struct v4l2_dbg_chip_ident *id)
 {
+	struct i2c_client *client = sd->priv;
+	struct tw9910_priv *priv = to_tw9910(client);
+
 	id->ident = V4L2_IDENT_TW9910;
-	id->revision = 0;
+	id->revision = priv->revision;
 
 	return 0;
 }
@@ -596,7 +588,8 @@
 	if (ret < 0)
 		return ret;
 
-	/* ret      = int
+	/*
+	 * ret      = int
 	 * reg->val = __u64
 	 */
 	reg->val = (__u64)ret;
@@ -637,9 +630,6 @@
 	 * reset hardware
 	 */
 	tw9910_reset(client);
-	ret = tw9910_write_array(client, tw9910_default_regs);
-	if (ret < 0)
-		goto tw9910_set_fmt_error;
 
 	/*
 	 * set bus width
@@ -688,13 +678,6 @@
 		goto tw9910_set_fmt_error;
 
 	/*
-	 * set cropping
-	 */
-	ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
-	if (ret < 0)
-		goto tw9910_set_fmt_error;
-
-	/*
 	 * set hsync
 	 */
 	ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
@@ -762,11 +745,11 @@
 	return 0;
 }
 
-static int tw9910_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int tw9910_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct tw9910_priv *priv = to_tw9910(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 
 	if (!priv->scale) {
 		int ret;
@@ -783,74 +766,76 @@
 			return ret;
 	}
 
-	f->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	pix->width		= priv->scale->width;
-	pix->height		= priv->scale->height;
-	pix->pixelformat	= V4L2_PIX_FMT_VYUY;
-	pix->colorspace		= V4L2_COLORSPACE_SMPTE170M;
-	pix->field		= V4L2_FIELD_INTERLACED;
+	mf->width	= priv->scale->width;
+	mf->height	= priv->scale->height;
+	mf->code	= V4L2_MBUS_FMT_YUYV8_2X8_BE;
+	mf->colorspace	= V4L2_COLORSPACE_JPEG;
+	mf->field	= V4L2_FIELD_INTERLACED_BT;
 
 	return 0;
 }
 
-static int tw9910_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int tw9910_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct tw9910_priv *priv = to_tw9910(client);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	/* See tw9910_s_crop() - no proper cropping support */
 	struct v4l2_crop a = {
 		.c = {
 			.left	= 0,
 			.top	= 0,
-			.width	= pix->width,
-			.height	= pix->height,
+			.width	= mf->width,
+			.height	= mf->height,
 		},
 	};
-	int i, ret;
+	int ret;
+
+	WARN_ON(mf->field != V4L2_FIELD_ANY &&
+		mf->field != V4L2_FIELD_INTERLACED_BT);
 
 	/*
 	 * check color format
 	 */
-	for (i = 0; i < ARRAY_SIZE(tw9910_color_fmt); i++)
-		if (pix->pixelformat == tw9910_color_fmt[i].fourcc)
-			break;
-
-	if (i == ARRAY_SIZE(tw9910_color_fmt))
+	if (mf->code != V4L2_MBUS_FMT_YUYV8_2X8_BE)
 		return -EINVAL;
 
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+
 	ret = tw9910_s_crop(sd, &a);
 	if (!ret) {
-		pix->width = priv->scale->width;
-		pix->height = priv->scale->height;
+		mf->width	= priv->scale->width;
+		mf->height	= priv->scale->height;
 	}
 	return ret;
 }
 
-static int tw9910_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
+static int tw9910_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
 {
 	struct i2c_client *client = sd->priv;
 	struct soc_camera_device *icd = client->dev.platform_data;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
 	const struct tw9910_scale_ctrl *scale;
 
-	if (V4L2_FIELD_ANY == pix->field) {
-		pix->field = V4L2_FIELD_INTERLACED;
-	} else if (V4L2_FIELD_INTERLACED != pix->field) {
-		dev_err(&client->dev, "Field type invalid.\n");
+	if (V4L2_FIELD_ANY == mf->field) {
+		mf->field = V4L2_FIELD_INTERLACED_BT;
+	} else if (V4L2_FIELD_INTERLACED_BT != mf->field) {
+		dev_err(&client->dev, "Field type %d invalid.\n", mf->field);
 		return -EINVAL;
 	}
 
+	mf->code = V4L2_MBUS_FMT_YUYV8_2X8_BE;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+
 	/*
 	 * select suitable norm
 	 */
-	scale = tw9910_select_norm(icd, pix->width, pix->height);
+	scale = tw9910_select_norm(icd, mf->width, mf->height);
 	if (!scale)
 		return -EINVAL;
 
-	pix->width  = scale->width;
-	pix->height = scale->height;
+	mf->width	= scale->width;
+	mf->height	= scale->height;
 
 	return 0;
 }
@@ -859,7 +844,7 @@
 			      struct i2c_client *client)
 {
 	struct tw9910_priv *priv = to_tw9910(client);
-	s32 val;
+	s32 id;
 
 	/*
 	 * We must have a parent by now. And it cannot be a wrong one.
@@ -878,23 +863,24 @@
 		return -ENODEV;
 	}
 
-	icd->formats     = tw9910_color_fmt;
-	icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
-
 	/*
 	 * check and show Product ID
+	 * So far only revisions 0 and 1 have been seen
 	 */
-	val = i2c_smbus_read_byte_data(client, ID);
+	id = i2c_smbus_read_byte_data(client, ID);
+	priv->revision = GET_REV(id);
+	id = GET_ID(id);
 
-	if (0x0B != GET_ID(val) ||
-	    0x00 != GET_ReV(val)) {
+	if (0x0B != id ||
+	    0x01 < priv->revision) {
 		dev_err(&client->dev,
-			"Product ID error %x:%x\n", GET_ID(val), GET_ReV(val));
+			"Product ID error %x:%x\n",
+			id, priv->revision);
 		return -ENODEV;
 	}
 
 	dev_info(&client->dev,
-		 "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
+		 "tw9910 Product ID %0x:%0x\n", id, priv->revision);
 
 	icd->vdev->tvnorms      = V4L2_STD_NTSC | V4L2_STD_PAL;
 	icd->vdev->current_norm = V4L2_STD_NTSC;
@@ -917,14 +903,25 @@
 #endif
 };
 
+static int tw9910_enum_fmt(struct v4l2_subdev *sd, int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_YUYV8_2X8_BE;
+	return 0;
+}
+
 static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
 	.s_stream	= tw9910_s_stream,
-	.g_fmt		= tw9910_g_fmt,
-	.s_fmt		= tw9910_s_fmt,
-	.try_fmt	= tw9910_try_fmt,
+	.g_mbus_fmt	= tw9910_g_fmt,
+	.s_mbus_fmt	= tw9910_s_fmt,
+	.try_mbus_fmt	= tw9910_try_fmt,
 	.cropcap	= tw9910_cropcap,
 	.g_crop		= tw9910_g_crop,
 	.s_crop		= tw9910_s_crop,
+	.enum_mbus_fmt	= tw9910_enum_fmt,
 };
 
 static struct v4l2_subdev_ops tw9910_subdev_ops = {
@@ -954,10 +951,10 @@
 	}
 
 	icl = to_soc_camera_link(icd);
-	if (!icl)
+	if (!icl || !icl->priv)
 		return -EINVAL;
 
-	info = container_of(icl, struct tw9910_video_info, link);
+	info = icl->priv;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&client->dev,
@@ -975,7 +972,7 @@
 	v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
 
 	icd->ops     = &tw9910_ops;
-	icd->iface   = info->link.bus_id;
+	icd->iface   = icl->bus_id;
 
 	ret = tw9910_video_probe(icd, client);
 	if (ret) {
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index dea8b32..5ac37c6 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -1053,9 +1053,9 @@
 			 "%s: video_register_device() successful\n", __func__);
 	}
 
-	dev_info(&uvd->dev->dev, "%s on /dev/video%d: canvas=%s videosize=%s\n",
+	dev_info(&uvd->dev->dev, "%s on %s: canvas=%s videosize=%s\n",
 		 (uvd->handle != NULL) ? uvd->handle->drvName : "???",
-		 uvd->vdev.num, tmp2, tmp1);
+		 video_device_node_name(&uvd->vdev), tmp2, tmp1);
 
 	usb_get_dev(uvd->dev);
 	return 0;
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 45fce39..6030410 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -796,7 +796,6 @@
 static struct video_device vicam_template = {
 	.name 		= "ViCam-based USB Camera",
 	.fops 		= &vicam_fops,
-	.minor 		= -1,
 	.release 	= video_device_release_empty,
 };
 
@@ -873,8 +872,8 @@
 		return -EIO;
 	}
 
-	printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",
-			cam->vdev.num);
+	printk(KERN_INFO "ViCam webcam driver now controlling device %s\n",
+		video_device_node_name(&cam->vdev));
 
 	usb_set_intfdata (intf, cam);
 
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index c19f51d..0613922 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -215,8 +215,8 @@
 	memcpy(&usbvision->i2c_adap, &i2c_adap_template,
 	       sizeof(struct i2c_adapter));
 
-	sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
-		" #%d", usbvision->vdev->num);
+	sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name,
+		usbvision->dev->bus->busnum, usbvision->dev->devpath);
 	PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
 	usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
 
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index c07b0ac..1054546 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1328,7 +1328,6 @@
 	.ioctl_ops 	= &usbvision_ioctl_ops,
 	.name           = "usbvision-video",
 	.release	= video_device_release,
-	.minor		= -1,
 	.tvnorms              = USBVISION_NORMS,
 	.current_norm         = V4L2_STD_PAL
 };
@@ -1362,7 +1361,6 @@
 	.fops		= &usbvision_radio_fops,
 	.name           = "usbvision-radio",
 	.release	= video_device_release,
-	.minor		= -1,
 	.ioctl_ops 	= &usbvision_radio_ioctl_ops,
 
 	.tvnorms              = USBVISION_NORMS,
@@ -1382,7 +1380,6 @@
 	.fops		= &usbvision_vbi_fops,
 	.release	= video_device_release,
 	.name           = "usbvision-vbi",
-	.minor		= -1,
 };
 
 
@@ -1404,7 +1401,6 @@
 		return NULL;
 	}
 	*vdev = *vdev_template;
-//	vdev->minor   = -1;
 	vdev->v4l2_dev = &usbvision->v4l2_dev;
 	snprintf(vdev->name, sizeof(vdev->name), "%s", name);
 	video_set_drvdata(vdev, usbvision);
@@ -1416,9 +1412,9 @@
 {
 	// vbi Device:
 	if (usbvision->vbi) {
-		PDEBUG(DBG_PROBE, "unregister /dev/vbi%d [v4l2]",
-		       usbvision->vbi->num);
-		if (usbvision->vbi->minor != -1) {
+		PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
+		       video_device_node_name(usbvision->vbi));
+		if (video_is_registered(usbvision->vbi)) {
 			video_unregister_device(usbvision->vbi);
 		} else {
 			video_device_release(usbvision->vbi);
@@ -1428,9 +1424,9 @@
 
 	// Radio Device:
 	if (usbvision->rdev) {
-		PDEBUG(DBG_PROBE, "unregister /dev/radio%d [v4l2]",
-		       usbvision->rdev->num);
-		if (usbvision->rdev->minor != -1) {
+		PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
+		       video_device_node_name(usbvision->rdev));
+		if (video_is_registered(usbvision->rdev)) {
 			video_unregister_device(usbvision->rdev);
 		} else {
 			video_device_release(usbvision->rdev);
@@ -1440,9 +1436,9 @@
 
 	// Video Device:
 	if (usbvision->vdev) {
-		PDEBUG(DBG_PROBE, "unregister /dev/video%d [v4l2]",
-		       usbvision->vdev->num);
-		if (usbvision->vdev->minor != -1) {
+		PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
+		       video_device_node_name(usbvision->vdev));
+		if (video_is_registered(usbvision->vdev)) {
 			video_unregister_device(usbvision->vdev);
 		} else {
 			video_device_release(usbvision->vdev);
@@ -1466,8 +1462,8 @@
 				  video_nr)<0) {
 		goto err_exit;
 	}
-	printk(KERN_INFO "USBVision[%d]: registered USBVision Video device /dev/video%d [v4l2]\n",
-	       usbvision->nr, usbvision->vdev->num);
+	printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
+	       usbvision->nr, video_device_node_name(usbvision->vdev));
 
 	// Radio Device:
 	if (usbvision_device_data[usbvision->DevModel].Radio) {
@@ -1483,8 +1479,8 @@
 					  radio_nr)<0) {
 			goto err_exit;
 		}
-		printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device /dev/radio%d [v4l2]\n",
-		       usbvision->nr, usbvision->rdev->num);
+		printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n",
+		       usbvision->nr, video_device_node_name(usbvision->rdev));
 	}
 	// vbi Device:
 	if (usbvision_device_data[usbvision->DevModel].vbi) {
@@ -1499,8 +1495,8 @@
 					  vbi_nr)<0) {
 			goto err_exit;
 		}
-		printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device /dev/vbi%d [v4l2] (Not Working Yet!)\n",
-		       usbvision->nr, usbvision->vbi->num);
+		printk(KERN_INFO "USBVision[%d]: registered USBVision VBI device %s [v4l2] (Not Working Yet!)\n",
+		       usbvision->nr, video_device_node_name(usbvision->vbi));
 	}
 	// all done
 	return 0;
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index c31bc50..391cccc 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1651,7 +1651,6 @@
 	 * get another one.
 	 */
 	vdev->parent = &dev->intf->dev;
-	vdev->minor = -1;
 	vdev->fops = &uvc_fops;
 	vdev->release = uvc_release;
 	strlcpy(vdev->name, dev->name, sizeof vdev->name);
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 05139a4..9a98028 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -145,7 +145,7 @@
 		uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non "
 			"compliance - GET_MIN/MAX(PROBE) incorrectly "
 			"supported. Enabling workaround.\n");
-		memset(ctrl, 0, sizeof ctrl);
+		memset(ctrl, 0, sizeof *ctrl);
 		ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
 		ret = 0;
 		goto out;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index e8e5aff..36b5cb8 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -1024,3 +1024,50 @@
 	}
 }
 EXPORT_SYMBOL_GPL(v4l_bound_align_image);
+
+/**
+ * v4l_fill_dv_preset_info - fill description of a digital video preset
+ * @preset - preset value
+ * @info - pointer to struct v4l2_dv_enum_preset
+ *
+ * drivers can use this helper function to fill description of dv preset
+ * in info.
+ */
+int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
+{
+	static const struct v4l2_dv_preset_info {
+		u16 width;
+		u16 height;
+		const char *name;
+	} dv_presets[] = {
+		{ 0, 0, "Invalid" },		/* V4L2_DV_INVALID */
+		{ 720,  480, "480p@59.94" },	/* V4L2_DV_480P59_94 */
+		{ 720,  576, "576p@50" },	/* V4L2_DV_576P50 */
+		{ 1280, 720, "720p@24" },	/* V4L2_DV_720P24 */
+		{ 1280, 720, "720p@25" },	/* V4L2_DV_720P25 */
+		{ 1280, 720, "720p@30" },	/* V4L2_DV_720P30 */
+		{ 1280, 720, "720p@50" },	/* V4L2_DV_720P50 */
+		{ 1280, 720, "720p@59.94" },	/* V4L2_DV_720P59_94 */
+		{ 1280, 720, "720p@60" },	/* V4L2_DV_720P60 */
+		{ 1920, 1080, "1080i@29.97" },	/* V4L2_DV_1080I29_97 */
+		{ 1920, 1080, "1080i@30" },	/* V4L2_DV_1080I30 */
+		{ 1920, 1080, "1080i@25" },	/* V4L2_DV_1080I25 */
+		{ 1920, 1080, "1080i@50" },	/* V4L2_DV_1080I50 */
+		{ 1920, 1080, "1080i@60" },	/* V4L2_DV_1080I60 */
+		{ 1920, 1080, "1080p@24" },	/* V4L2_DV_1080P24 */
+		{ 1920, 1080, "1080p@25" },	/* V4L2_DV_1080P25 */
+		{ 1920, 1080, "1080p@30" },	/* V4L2_DV_1080P30 */
+		{ 1920, 1080, "1080p@50" },	/* V4L2_DV_1080P50 */
+		{ 1920, 1080, "1080p@60" },	/* V4L2_DV_1080P60 */
+	};
+
+	if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
+		return -EINVAL;
+
+	info->preset = preset;
+	info->width = dv_presets[preset].width;
+	info->height = dv_presets[preset].height;
+	strlcpy(info->name, dv_presets[preset].name, sizeof(info->name));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info);
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 997975d..c4150bd 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -1077,6 +1077,12 @@
 	case VIDIOC_DBG_G_REGISTER:
 	case VIDIOC_DBG_G_CHIP_IDENT:
 	case VIDIOC_S_HW_FREQ_SEEK:
+	case VIDIOC_ENUM_DV_PRESETS:
+	case VIDIOC_S_DV_PRESET:
+	case VIDIOC_G_DV_PRESET:
+	case VIDIOC_QUERY_DV_PRESET:
+	case VIDIOC_S_DV_TIMINGS:
+	case VIDIOC_G_DV_TIMINGS:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 500cbe9..7090699 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -189,7 +189,7 @@
 
 	if (!vdev->fops->read)
 		return -EINVAL;
-	if (video_is_unregistered(vdev))
+	if (!video_is_registered(vdev))
 		return -EIO;
 	return vdev->fops->read(filp, buf, sz, off);
 }
@@ -201,7 +201,7 @@
 
 	if (!vdev->fops->write)
 		return -EINVAL;
-	if (video_is_unregistered(vdev))
+	if (!video_is_registered(vdev))
 		return -EIO;
 	return vdev->fops->write(filp, buf, sz, off);
 }
@@ -210,7 +210,7 @@
 {
 	struct video_device *vdev = video_devdata(filp);
 
-	if (!vdev->fops->poll || video_is_unregistered(vdev))
+	if (!vdev->fops->poll || !video_is_registered(vdev))
 		return DEFAULT_POLLMASK;
 	return vdev->fops->poll(filp, poll);
 }
@@ -250,7 +250,7 @@
 
 	if (!vdev->fops->get_unmapped_area)
 		return -ENOSYS;
-	if (video_is_unregistered(vdev))
+	if (!video_is_registered(vdev))
 		return -ENODEV;
 	return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags);
 }
@@ -260,8 +260,7 @@
 {
 	struct video_device *vdev = video_devdata(filp);
 
-	if (!vdev->fops->mmap ||
-	    video_is_unregistered(vdev))
+	if (!vdev->fops->mmap || !video_is_registered(vdev))
 		return -ENODEV;
 	return vdev->fops->mmap(filp, vm);
 }
@@ -277,7 +276,7 @@
 	vdev = video_devdata(filp);
 	/* return ENODEV if the video device has been removed
 	   already or if it is not registered anymore. */
-	if (vdev == NULL || video_is_unregistered(vdev)) {
+	if (vdev == NULL || !video_is_registered(vdev)) {
 		mutex_unlock(&videodev_lock);
 		return -ENODEV;
 	}
@@ -551,10 +550,11 @@
 	vdev->dev.release = v4l2_device_release;
 
 	if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
-		printk(KERN_WARNING "%s: requested %s%d, got %s%d\n",
-				__func__, name_base, nr, name_base, vdev->num);
+		printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
+			name_base, nr, video_device_node_name(vdev));
 
 	/* Part 5: Activate this minor. The char device can now be used. */
+	set_bit(V4L2_FL_REGISTERED, &vdev->flags);
 	mutex_lock(&videodev_lock);
 	video_device[vdev->minor] = vdev;
 	mutex_unlock(&videodev_lock);
@@ -593,11 +593,11 @@
 void video_unregister_device(struct video_device *vdev)
 {
 	/* Check if vdev was ever registered at all */
-	if (!vdev || vdev->minor < 0)
+	if (!vdev || !video_is_registered(vdev))
 		return;
 
 	mutex_lock(&videodev_lock);
-	set_bit(V4L2_FL_UNREGISTERED, &vdev->flags);
+	clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
 	mutex_unlock(&videodev_lock);
 	device_unregister(&vdev->dev);
 }
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 30cc3347..4b11257 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -284,6 +284,12 @@
 	[_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
 	[_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)]   = "VIDIOC_S_HW_FREQ_SEEK",
 #endif
+	[_IOC_NR(VIDIOC_ENUM_DV_PRESETS)]  = "VIDIOC_ENUM_DV_PRESETS",
+	[_IOC_NR(VIDIOC_S_DV_PRESET)]	   = "VIDIOC_S_DV_PRESET",
+	[_IOC_NR(VIDIOC_G_DV_PRESET)]	   = "VIDIOC_G_DV_PRESET",
+	[_IOC_NR(VIDIOC_QUERY_DV_PRESET)]  = "VIDIOC_QUERY_DV_PRESET",
+	[_IOC_NR(VIDIOC_S_DV_TIMINGS)]     = "VIDIOC_S_DV_TIMINGS",
+	[_IOC_NR(VIDIOC_G_DV_TIMINGS)]     = "VIDIOC_G_DV_TIMINGS",
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -1135,6 +1141,19 @@
 	{
 		struct v4l2_input *p = arg;
 
+		/*
+		 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+		 * CAP_STD here based on ioctl handler provided by the
+		 * driver. If the driver doesn't support these
+		 * for a specific input, it must override these flags.
+		 */
+		if (ops->vidioc_s_std)
+			p->capabilities |= V4L2_IN_CAP_STD;
+		if (ops->vidioc_s_dv_preset)
+			p->capabilities |= V4L2_IN_CAP_PRESETS;
+		if (ops->vidioc_s_dv_timings)
+			p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
+
 		if (!ops->vidioc_enum_input)
 			break;
 
@@ -1179,6 +1198,19 @@
 		if (!ops->vidioc_enum_output)
 			break;
 
+		/*
+		 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+		 * CAP_STD here based on ioctl handler provided by the
+		 * driver. If the driver doesn't support these
+		 * for a specific output, it must override these flags.
+		 */
+		if (ops->vidioc_s_std)
+			p->capabilities |= V4L2_OUT_CAP_STD;
+		if (ops->vidioc_s_dv_preset)
+			p->capabilities |= V4L2_OUT_CAP_PRESETS;
+		if (ops->vidioc_s_dv_timings)
+			p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
+
 		ret = ops->vidioc_enum_output(file, fh, p);
 		if (!ret)
 			dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1794,6 +1826,121 @@
 		}
 		break;
 	}
+	case VIDIOC_ENUM_DV_PRESETS:
+	{
+		struct v4l2_dv_enum_preset *p = arg;
+
+		if (!ops->vidioc_enum_dv_presets)
+			break;
+
+		ret = ops->vidioc_enum_dv_presets(file, fh, p);
+		if (!ret)
+			dbgarg(cmd,
+				"index=%d, preset=%d, name=%s, width=%d,"
+				" height=%d ",
+				p->index, p->preset, p->name, p->width,
+				p->height);
+		break;
+	}
+	case VIDIOC_S_DV_PRESET:
+	{
+		struct v4l2_dv_preset *p = arg;
+
+		if (!ops->vidioc_s_dv_preset)
+			break;
+
+		dbgarg(cmd, "preset=%d\n", p->preset);
+		ret = ops->vidioc_s_dv_preset(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_DV_PRESET:
+	{
+		struct v4l2_dv_preset *p = arg;
+
+		if (!ops->vidioc_g_dv_preset)
+			break;
+
+		ret = ops->vidioc_g_dv_preset(file, fh, p);
+		if (!ret)
+			dbgarg(cmd, "preset=%d\n", p->preset);
+		break;
+	}
+	case VIDIOC_QUERY_DV_PRESET:
+	{
+		struct v4l2_dv_preset *p = arg;
+
+		if (!ops->vidioc_query_dv_preset)
+			break;
+
+		ret = ops->vidioc_query_dv_preset(file, fh, p);
+		if (!ret)
+			dbgarg(cmd, "preset=%d\n", p->preset);
+		break;
+	}
+	case VIDIOC_S_DV_TIMINGS:
+	{
+		struct v4l2_dv_timings *p = arg;
+
+		if (!ops->vidioc_s_dv_timings)
+			break;
+
+		switch (p->type) {
+		case V4L2_DV_BT_656_1120:
+			dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
+				" width=%d, height=%d, polarities=%x,"
+				" hfrontporch=%d, hsync=%d, hbackporch=%d,"
+				" vfrontporch=%d, vsync=%d, vbackporch=%d,"
+				" il_vfrontporch=%d, il_vsync=%d,"
+				" il_vbackporch=%d\n",
+				p->bt.interlaced, p->bt.pixelclock,
+				p->bt.width, p->bt.height, p->bt.polarities,
+				p->bt.hfrontporch, p->bt.hsync,
+				p->bt.hbackporch, p->bt.vfrontporch,
+				p->bt.vsync, p->bt.vbackporch,
+				p->bt.il_vfrontporch, p->bt.il_vsync,
+				p->bt.il_vbackporch);
+			ret = ops->vidioc_s_dv_timings(file, fh, p);
+			break;
+		default:
+			dbgarg2("Unknown type %d!\n", p->type);
+			break;
+		}
+		break;
+	}
+	case VIDIOC_G_DV_TIMINGS:
+	{
+		struct v4l2_dv_timings *p = arg;
+
+		if (!ops->vidioc_g_dv_timings)
+			break;
+
+		ret = ops->vidioc_g_dv_timings(file, fh, p);
+		if (!ret) {
+			switch (p->type) {
+			case V4L2_DV_BT_656_1120:
+				dbgarg2("bt-656/1120:interlaced=%d,"
+					" pixelclock=%lld,"
+					" width=%d, height=%d, polarities=%x,"
+					" hfrontporch=%d, hsync=%d,"
+					" hbackporch=%d, vfrontporch=%d,"
+					" vsync=%d, vbackporch=%d,"
+					" il_vfrontporch=%d, il_vsync=%d,"
+					" il_vbackporch=%d\n",
+					p->bt.interlaced, p->bt.pixelclock,
+					p->bt.width, p->bt.height,
+					p->bt.polarities, p->bt.hfrontporch,
+					p->bt.hsync, p->bt.hbackporch,
+					p->bt.vfrontporch, p->bt.vsync,
+					p->bt.vbackporch, p->bt.il_vfrontporch,
+					p->bt.il_vsync, p->bt.il_vbackporch);
+				break;
+			default:
+				dbgarg2("Unknown type %d!\n", p->type);
+				break;
+			}
+		}
+		break;
+	}
 
 	default:
 	{
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
index d25f284..22c0109 100644
--- a/drivers/media/video/videobuf-dma-contig.c
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -141,9 +141,11 @@
 	struct vm_area_struct *vma;
 	unsigned long prev_pfn, this_pfn;
 	unsigned long pages_done, user_address;
+	unsigned int offset;
 	int ret;
 
-	mem->size = PAGE_ALIGN(vb->size);
+	offset = vb->baddr & ~PAGE_MASK;
+	mem->size = PAGE_ALIGN(vb->size + offset);
 	mem->is_userptr = 0;
 	ret = -EINVAL;
 
@@ -166,7 +168,7 @@
 			break;
 
 		if (pages_done == 0)
-			mem->dma_handle = this_pfn << PAGE_SHIFT;
+			mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset;
 		else if (this_pfn != (prev_pfn + 1))
 			ret = -EFAULT;
 
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index b034a81..a15d1e7 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4068,7 +4068,6 @@
 	.fops		= &vino_fops,
 	.ioctl_ops 	= &vino_ioctl_ops,
 	.tvnorms 	= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
-	.minor		= -1,
 };
 
 static void vino_module_cleanup(int stage)
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 7705fc6..37632a0 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1148,7 +1148,8 @@
 		return -EBUSY;
 	}
 
-	dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
+	dprintk(dev, 1, "open %s type=%s users=%d\n",
+		video_device_node_name(dev->vfd),
 		v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
 	/* allocate + initialize per filehandle data */
@@ -1221,8 +1222,7 @@
 	struct vivi_fh         *fh = file->private_data;
 	struct vivi_dev *dev       = fh->dev;
 	struct vivi_dmaqueue *vidq = &dev->vidq;
-
-	int minor = video_devdata(file)->minor;
+	struct video_device  *vdev = video_devdata(file);
 
 	vivi_stop_thread(vidq);
 	videobuf_stop(&fh->vb_vidq);
@@ -1234,8 +1234,8 @@
 	dev->users--;
 	mutex_unlock(&dev->mutex);
 
-	dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
-		minor, dev->users);
+	dprintk(dev, 1, "close called (dev=%s, users=%d)\n",
+		video_device_node_name(vdev), dev->users);
 
 	return 0;
 }
@@ -1296,7 +1296,6 @@
 	.name		= "vivi",
 	.fops           = &vivi_fops,
 	.ioctl_ops 	= &vivi_ioctl_ops,
-	.minor		= -1,
 	.release	= video_device_release,
 
 	.tvnorms              = V4L2_STD_525_60,
@@ -1317,8 +1316,8 @@
 		list_del(list);
 		dev = list_entry(list, struct vivi_dev, vivi_devlist);
 
-		v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
-			dev->vfd->num);
+		v4l2_info(&dev->v4l2_dev, "unregistering %s\n",
+			video_device_node_name(dev->vfd));
 		video_unregister_device(dev->vfd);
 		v4l2_device_unregister(&dev->v4l2_dev);
 		kfree(dev);
@@ -1372,15 +1371,12 @@
 	/* Now that everything is fine, let's add it to device list */
 	list_add_tail(&dev->vivi_devlist, &vivi_devlist);
 
-	snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
-			vivi_template.name, vfd->num);
-
 	if (video_nr >= 0)
 		video_nr++;
 
 	dev->vfd = vfd;
-	v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
-			vfd->num);
+	v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
+		  video_device_node_name(vfd));
 	return 0;
 
 rel_vdev:
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 37fcdc4..d807eea 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -2323,9 +2323,9 @@
 error:
 	cam->sensor_initialized = 0;
 	cam->sensor = CC_UNKNOWN;
-	DBG(1, "Image sensor initialization failed for %s (/dev/video%d). "
+	DBG(1, "Image sensor initialization failed for %s (%s). "
 	       "Try to detach and attach this device again",
-	    symbolic(camlist, cam->id), cam->v4ldev->num)
+	    symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev))
 	return err;
 }
 
@@ -2571,7 +2571,8 @@
 {
 	mutex_lock(&w9968cf_devlist_mutex);
 
-	DBG(2, "V4L device deregistered: /dev/video%d", cam->v4ldev->num)
+	DBG(2, "V4L device deregistered: %s",
+	    video_device_node_name(cam->v4ldev))
 
 	video_unregister_device(cam->v4ldev);
 	list_del(&cam->v4llist);
@@ -2605,17 +2606,19 @@
 
 	if (cam->sensor == CC_UNKNOWN) {
 		DBG(2, "No supported image sensor has been detected by the "
-		       "'ovcamchip' module for the %s (/dev/video%d). Make "
-		       "sure it is loaded *before* (re)connecting the camera.",
-		    symbolic(camlist, cam->id), cam->v4ldev->num)
+		       "'ovcamchip' module for the %s (%s). Make sure "
+		       "it is loaded *before* (re)connecting the camera.",
+		    symbolic(camlist, cam->id),
+		    video_device_node_name(cam->v4ldev))
 		mutex_unlock(&cam->dev_mutex);
 		up_read(&w9968cf_disconnect);
 		return -ENODEV;
 	}
 
 	if (cam->users) {
-		DBG(2, "%s (/dev/video%d) has been already occupied by '%s'",
-		    symbolic(camlist, cam->id), cam->v4ldev->num, cam->command)
+		DBG(2, "%s (%s) has been already occupied by '%s'",
+		    symbolic(camlist, cam->id),
+		    video_device_node_name(cam->v4ldev), cam->command)
 		if ((filp->f_flags & O_NONBLOCK)||(filp->f_flags & O_NDELAY)) {
 			mutex_unlock(&cam->dev_mutex);
 			up_read(&w9968cf_disconnect);
@@ -2636,8 +2639,8 @@
 		mutex_lock(&cam->dev_mutex);
 	}
 
-	DBG(5, "Opening '%s', /dev/video%d ...",
-	    symbolic(camlist, cam->id), cam->v4ldev->num)
+	DBG(5, "Opening '%s', %s ...",
+	    symbolic(camlist, cam->id), video_device_node_name(cam->v4ldev))
 
 	cam->streaming = 0;
 	cam->misconfigured = 0;
@@ -2874,8 +2877,7 @@
 			.minwidth = cam->minwidth,
 			.minheight = cam->minheight,
 		};
-		sprintf(cap.name, "W996[87]CF USB Camera #%d",
-			cam->v4ldev->num);
+		sprintf(cap.name, "W996[87]CF USB Camera");
 		cap.maxwidth = (cam->upscaling && w9968cf_vpp)
 			       ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth)
 				 : cam->maxwidth;
@@ -3485,7 +3487,6 @@
 
 	strcpy(cam->v4ldev->name, symbolic(camlist, mod_id));
 	cam->v4ldev->fops = &w9968cf_fops;
-	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
 	video_set_drvdata(cam->v4ldev, cam);
 	cam->v4ldev->v4l2_dev = &cam->v4l2_dev;
@@ -3501,7 +3502,8 @@
 		goto fail;
 	}
 
-	DBG(2, "V4L device registered as /dev/video%d", cam->v4ldev->num)
+	DBG(2, "V4L device registered as %s",
+	    video_device_node_name(cam->v4ldev))
 
 	/* Set some basic constants */
 	w9968cf_configure_camera(cam, udev, mod_id, dev_nr);
@@ -3557,10 +3559,10 @@
 		wake_up_interruptible_all(&cam->open);
 
 		if (cam->users) {
-			DBG(2, "The device is open (/dev/video%d)! "
+			DBG(2, "The device is open (%s)! "
 			       "Process name: %s. Deregistration and memory "
 			       "deallocation are deferred on close.",
-			    cam->v4ldev->num, cam->command)
+			    video_device_node_name(cam->v4ldev), cam->command)
 			cam->misconfigured = 1;
 			w9968cf_stop_transfer(cam);
 			wake_up_interruptible(&cam->wait_queue);
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 312a713..e44e4b5 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -538,8 +538,8 @@
 	else if (cam->stream != STREAM_OFF) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "URB timeout reached. The camera is misconfigured. To "
-		       "use it, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use it, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -640,7 +640,8 @@
 {
 	struct zc0301_device *cam = container_of(kref, struct zc0301_device,
 						 kref);
-	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->num);
+	DBG(2, "V4L2 device %s deregistered",
+	    video_device_node_name(cam->v4ldev));
 	video_set_drvdata(cam->v4ldev, NULL);
 	video_unregister_device(cam->v4ldev);
 	usb_put_dev(cam->usbdev);
@@ -679,7 +680,8 @@
 	}
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->num);
+		DBG(2, "Device %s is busy...",
+		    video_device_node_name(cam->v4ldev));
 		DBG(3, "Simultaneous opens are not supported");
 		if ((filp->f_flags & O_NONBLOCK) ||
 		    (filp->f_flags & O_NDELAY)) {
@@ -722,7 +724,8 @@
 	cam->frame_count = 0;
 	zc0301_empty_framequeues(cam);
 
-	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->num);
+	DBG(3, "Video device %s is open",
+	    video_device_node_name(cam->v4ldev));
 
 out:
 	mutex_unlock(&cam->open_mutex);
@@ -746,7 +749,8 @@
 	cam->users--;
 	wake_up_interruptible_nr(&cam->wait_open, 1);
 
-	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->num);
+	DBG(3, "Video device %s closed",
+	    video_device_node_name(cam->v4ldev));
 
 	kref_put(&cam->kref, zc0301_release_resources);
 
@@ -1276,8 +1280,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1289,8 +1293,8 @@
 	    nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -1471,8 +1475,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1483,8 +1487,8 @@
 	    nbuffers != zc0301_request_buffers(cam, nbuffers, cam->io)) {
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
-		       "use the camera, close and open /dev/video%d again.",
-		    cam->v4ldev->num);
+		       "use the camera, close and open %s again.",
+		    video_device_node_name(cam->v4ldev));
 		return -ENOMEM;
 	}
 
@@ -1530,8 +1534,8 @@
 	if (err) { /* atomic, no rollback in ioctl() */
 		cam->state |= DEV_MISCONFIGURED;
 		DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware "
-		       "problems. To use the camera, close and open "
-		       "/dev/video%d again.", cam->v4ldev->num);
+		       "problems. To use the camera, close and open %s again.",
+		       video_device_node_name(cam->v4ldev));
 		return -EIO;
 	}
 
@@ -1984,7 +1988,6 @@
 
 	strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera");
 	cam->v4ldev->fops = &zc0301_fops;
-	cam->v4ldev->minor = video_nr[dev_nr];
 	cam->v4ldev->release = video_device_release;
 	cam->v4ldev->parent = &udev->dev;
 	video_set_drvdata(cam->v4ldev, cam);
@@ -2003,7 +2006,8 @@
 		goto fail;
 	}
 
-	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->num);
+	DBG(2, "V4L2 device registered as %s",
+	    video_device_node_name(cam->v4ldev));
 
 	cam->module_param.force_munmap = force_munmap[dev_nr];
 	cam->module_param.frame_timeout = frame_timeout[dev_nr];
@@ -2040,9 +2044,9 @@
 	DBG(2, "Disconnecting %s...", cam->v4ldev->name);
 
 	if (cam->users) {
-		DBG(2, "Device /dev/video%d is open! Deregistration and "
+		DBG(2, "Device %s is open! Deregistration and "
 		       "memory deallocation are deferred.",
-		    cam->v4ldev->num);
+		    video_device_node_name(cam->v4ldev));
 		cam->state |= DEV_MISCONFIGURED;
 		zc0301_stop_transfer(cam);
 		cam->state |= DEV_DISCONNECTED;
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index e9f72ca..2ddffed 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -3387,6 +3387,5 @@
 	.ioctl_ops = &zoran_ioctl_ops,
 	.release = &zoran_vdev_release,
 	.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
-	.minor = -1
 };
 
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index 2ef110b..f0eae83 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -1455,7 +1455,6 @@
 	.fops = &zr364xx_fops,
 	.ioctl_ops = &zr364xx_ioctl_ops,
 	.release = video_device_release,
-	.minor = -1,
 };
 
 
@@ -1635,8 +1634,8 @@
 
 	spin_lock_init(&cam->slock);
 
-	dev_info(&udev->dev, DRIVER_DESC " controlling video device %d\n",
-		 cam->vdev->num);
+	dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
+		 video_device_node_name(cam->vdev));
 	return 0;
 }
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 610e914..85bc6a6 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1587,7 +1587,7 @@
 {
 	u8		__iomem *mem;
 	int		 ii;
-	unsigned long	 mem_phys;
+	resource_size_t	 mem_phys;
 	unsigned long	 port;
 	u32		 msize;
 	u32		 psize;
@@ -1677,8 +1677,8 @@
 		return -EINVAL;
 	}
 	ioc->memmap = mem;
-	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n",
-	    ioc->name, mem, mem_phys));
+	dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n",
+	    ioc->name, mem, (unsigned long long)mem_phys));
 
 	ioc->mem_phys = mem_phys;
 	ioc->chip = (SYSIF_REGS __iomem *)mem;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 59f4ba1..e3551d2 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -203,6 +203,7 @@
 
 config CS5535_MFGPT_DEFAULT_IRQ
 	int
+	depends on CS5535_MFGPT
 	default 7
 	help
 	  MFGPTs on the CS5535 require an interrupt.  The selected IRQ
@@ -248,19 +249,6 @@
 	This option enables addition debugging code for the SGI GRU driver. If
 	you are unsure, say N.
 
-config DELL_LAPTOP
-	tristate "Dell Laptop Extras (EXPERIMENTAL)"
-	depends on X86
-	depends on DCDBAS
-	depends on EXPERIMENTAL
-	depends on BACKLIGHT_CLASS_DEVICE
-	depends on RFKILL
-	depends on POWER_SUPPLY
-	default n
-	---help---
-	This driver adds support for rfkill and backlight control to Dell
-	laptops.
-
 config ISL29003
 	tristate "Intersil ISL29003 ambient light sensor"
 	depends on I2C && SYSFS
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index e9eae4a..1eac626 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -391,6 +391,7 @@
 	[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
 	[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
 	[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
+	[ENCLOSURE_STATUS_MAX] = NULL,
 };
 
 static const char *const enclosure_type [] = {
diff --git a/drivers/misc/sgi-gru/gru.h b/drivers/misc/sgi-gru/gru.h
index f93f03a..3ad76cd 100644
--- a/drivers/misc/sgi-gru/gru.h
+++ b/drivers/misc/sgi-gru/gru.h
@@ -53,6 +53,17 @@
 	int	free_user_cbr;
 };
 
+/*
+ * Statictics kept for each context.
+ */
+struct gru_gseg_statistics {
+	unsigned long	fmm_tlbmiss;
+	unsigned long	upm_tlbmiss;
+	unsigned long	tlbdropin;
+	unsigned long	context_stolen;
+	unsigned long	reserved[10];
+};
+
 /* Flags for GRU options on the gru_create_context() call */
 /* Select one of the follow 4 options to specify how TLB misses are handled */
 #define GRU_OPT_MISS_DEFAULT	0x0000	/* Use default mode */
diff --git a/drivers/misc/sgi-gru/gru_instructions.h b/drivers/misc/sgi-gru/gru_instructions.h
index 3c9c066..d95587c 100644
--- a/drivers/misc/sgi-gru/gru_instructions.h
+++ b/drivers/misc/sgi-gru/gru_instructions.h
@@ -34,17 +34,17 @@
 #include <asm/intrinsics.h>
 #define __flush_cache(p)		ia64_fc((unsigned long)p)
 /* Use volatile on IA64 to ensure ordering via st4.rel */
-#define gru_ordered_store_int(p, v)					\
+#define gru_ordered_store_ulong(p, v)					\
 		do {							\
 			barrier();					\
-			*((volatile int *)(p)) = v; /* force st.rel */	\
+			*((volatile unsigned long *)(p)) = v; /* force st.rel */	\
 		} while (0)
 #elif defined(CONFIG_X86_64)
 #define __flush_cache(p)		clflush(p)
-#define gru_ordered_store_int(p, v)					\
+#define gru_ordered_store_ulong(p, v)					\
 		do {							\
 			barrier();					\
-			*(int *)p = v;					\
+			*(unsigned long *)p = v;			\
 		} while (0)
 #else
 #error "Unsupported architecture"
@@ -129,8 +129,13 @@
  */
 struct gru_instruction {
     /* DW 0 */
-    unsigned int		op32;    /* icmd,xtype,iaa0,ima,opc */
-    unsigned int		tri0;
+    union {
+    	unsigned long		op64;    /* icmd,xtype,iaa0,ima,opc,tri0 */
+	struct {
+		unsigned int	op32;
+		unsigned int	tri0;
+	};
+    };
     unsigned long		tri1_bufsize;		/* DW 1 */
     unsigned long		baddr0;			/* DW 2 */
     unsigned long		nelem;			/* DW 3 */
@@ -140,7 +145,7 @@
     unsigned long		avalue;			/* DW 7 */
 };
 
-/* Some shifts and masks for the low 32 bits of a GRU command */
+/* Some shifts and masks for the low 64 bits of a GRU command */
 #define GRU_CB_ICMD_SHFT	0
 #define GRU_CB_ICMD_MASK	0x1
 #define GRU_CB_XTYPE_SHFT	8
@@ -155,6 +160,10 @@
 #define GRU_CB_OPC_MASK		0xff
 #define GRU_CB_EXOPC_SHFT	24
 #define GRU_CB_EXOPC_MASK	0xff
+#define GRU_IDEF2_SHFT		32
+#define GRU_IDEF2_MASK		0x3ffff
+#define GRU_ISTATUS_SHFT	56
+#define GRU_ISTATUS_MASK	0x3
 
 /* GRU instruction opcodes (opc field) */
 #define OP_NOP		0x00
@@ -256,6 +265,7 @@
 #define CBE_CAUSE_PROTOCOL_STATE_DATA_ERROR	(1 << 16)
 #define CBE_CAUSE_RA_RESPONSE_DATA_ERROR	(1 << 17)
 #define CBE_CAUSE_HA_RESPONSE_DATA_ERROR	(1 << 18)
+#define CBE_CAUSE_FORCED_ERROR			(1 << 19)
 
 /* CBE cbrexecstatus bits */
 #define CBR_EXS_ABORT_OCC_BIT			0
@@ -264,13 +274,15 @@
 #define CBR_EXS_QUEUED_BIT			3
 #define CBR_EXS_TLB_INVAL_BIT			4
 #define CBR_EXS_EXCEPTION_BIT			5
+#define CBR_EXS_CB_INT_PENDING_BIT		6
 
 #define CBR_EXS_ABORT_OCC			(1 << CBR_EXS_ABORT_OCC_BIT)
 #define CBR_EXS_INT_OCC				(1 << CBR_EXS_INT_OCC_BIT)
 #define CBR_EXS_PENDING				(1 << CBR_EXS_PENDING_BIT)
 #define CBR_EXS_QUEUED				(1 << CBR_EXS_QUEUED_BIT)
-#define CBR_TLB_INVAL				(1 << CBR_EXS_TLB_INVAL_BIT)
+#define CBR_EXS_TLB_INVAL			(1 << CBR_EXS_TLB_INVAL_BIT)
 #define CBR_EXS_EXCEPTION			(1 << CBR_EXS_EXCEPTION_BIT)
+#define CBR_EXS_CB_INT_PENDING			(1 << CBR_EXS_CB_INT_PENDING_BIT)
 
 /*
  * Exceptions are retried for the following cases. If any OTHER bits are set
@@ -296,12 +308,14 @@
 
 
 /* Generate the low word of a GRU instruction */
-static inline unsigned int
-__opword(unsigned char opcode, unsigned char exopc, unsigned char xtype,
+static inline unsigned long
+__opdword(unsigned char opcode, unsigned char exopc, unsigned char xtype,
        unsigned char iaa0, unsigned char iaa1,
-       unsigned char ima)
+       unsigned long idef2, unsigned char ima)
 {
     return (1 << GRU_CB_ICMD_SHFT) |
+	   ((unsigned long)CBS_ACTIVE << GRU_ISTATUS_SHFT) |
+	   (idef2<< GRU_IDEF2_SHFT) |
 	   (iaa0 << GRU_CB_IAA0_SHFT) |
 	   (iaa1 << GRU_CB_IAA1_SHFT) |
 	   (ima << GRU_CB_IMA_SHFT) |
@@ -319,12 +333,13 @@
 }
 
 /*
- * Store the lower 32 bits of the command including the "start" bit. Then
+ * Store the lower 64 bits of the command including the "start" bit. Then
  * start the instruction executing.
  */
-static inline void gru_start_instruction(struct gru_instruction *ins, int op32)
+static inline void gru_start_instruction(struct gru_instruction *ins, unsigned long op64)
 {
-	gru_ordered_store_int(ins, op32);
+	gru_ordered_store_ulong(ins, op64);
+	mb();
 	gru_flush_cache(ins);
 }
 
@@ -340,6 +355,30 @@
  *     	- nelem and stride are in elements
  *     	- tri0/tri1 is in bytes for the beginning of the data segment.
  */
+static inline void gru_vload_phys(void *cb, unsigned long gpa,
+		unsigned int tri0, int iaa, unsigned long hints)
+{
+	struct gru_instruction *ins = (struct gru_instruction *)cb;
+
+	ins->baddr0 = (long)gpa | ((unsigned long)iaa << 62);
+	ins->nelem = 1;
+	ins->op1_stride = 1;
+	gru_start_instruction(ins, __opdword(OP_VLOAD, 0, XTYPE_DW, iaa, 0,
+					(unsigned long)tri0, CB_IMA(hints)));
+}
+
+static inline void gru_vstore_phys(void *cb, unsigned long gpa,
+		unsigned int tri0, int iaa, unsigned long hints)
+{
+	struct gru_instruction *ins = (struct gru_instruction *)cb;
+
+	ins->baddr0 = (long)gpa | ((unsigned long)iaa << 62);
+	ins->nelem = 1;
+	ins->op1_stride = 1;
+	gru_start_instruction(ins, __opdword(OP_VSTORE, 0, XTYPE_DW, iaa, 0,
+					(unsigned long)tri0, CB_IMA(hints)));
+}
+
 static inline void gru_vload(void *cb, unsigned long mem_addr,
 		unsigned int tri0, unsigned char xtype, unsigned long nelem,
 		unsigned long stride, unsigned long hints)
@@ -348,10 +387,9 @@
 
 	ins->baddr0 = (long)mem_addr;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
 	ins->op1_stride = stride;
-	gru_start_instruction(ins, __opword(OP_VLOAD, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_VLOAD, 0, xtype, IAA_RAM, 0,
+					(unsigned long)tri0, CB_IMA(hints)));
 }
 
 static inline void gru_vstore(void *cb, unsigned long mem_addr,
@@ -362,10 +400,9 @@
 
 	ins->baddr0 = (long)mem_addr;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
 	ins->op1_stride = stride;
-	gru_start_instruction(ins, __opword(OP_VSTORE, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_VSTORE, 0, xtype, IAA_RAM, 0,
+					tri0, CB_IMA(hints)));
 }
 
 static inline void gru_ivload(void *cb, unsigned long mem_addr,
@@ -376,10 +413,9 @@
 
 	ins->baddr0 = (long)mem_addr;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
 	ins->tri1_bufsize = tri1;
-	gru_start_instruction(ins, __opword(OP_IVLOAD, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_IVLOAD, 0, xtype, IAA_RAM, 0,
+					tri0, CB_IMA(hints)));
 }
 
 static inline void gru_ivstore(void *cb, unsigned long mem_addr,
@@ -390,10 +426,9 @@
 
 	ins->baddr0 = (long)mem_addr;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
 	ins->tri1_bufsize = tri1;
-	gru_start_instruction(ins, __opword(OP_IVSTORE, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_IVSTORE, 0, xtype, IAA_RAM, 0,
+					tri0, CB_IMA(hints)));
 }
 
 static inline void gru_vset(void *cb, unsigned long mem_addr,
@@ -406,8 +441,8 @@
 	ins->op2_value_baddr1 = value;
 	ins->nelem = nelem;
 	ins->op1_stride = stride;
-	gru_start_instruction(ins, __opword(OP_VSET, 0, xtype, IAA_RAM, 0,
-					 CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_VSET, 0, xtype, IAA_RAM, 0,
+					 0, CB_IMA(hints)));
 }
 
 static inline void gru_ivset(void *cb, unsigned long mem_addr,
@@ -420,8 +455,8 @@
 	ins->op2_value_baddr1 = value;
 	ins->nelem = nelem;
 	ins->tri1_bufsize = tri1;
-	gru_start_instruction(ins, __opword(OP_IVSET, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_IVSET, 0, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_vflush(void *cb, unsigned long mem_addr,
@@ -433,15 +468,15 @@
 	ins->baddr0 = (long)mem_addr;
 	ins->op1_stride = stride;
 	ins->nelem = nelem;
-	gru_start_instruction(ins, __opword(OP_VFLUSH, 0, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_VFLUSH, 0, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_nop(void *cb, int hints)
 {
 	struct gru_instruction *ins = (void *)cb;
 
-	gru_start_instruction(ins, __opword(OP_NOP, 0, 0, 0, 0, CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_NOP, 0, 0, 0, 0, 0, CB_IMA(hints)));
 }
 
 
@@ -455,10 +490,9 @@
 	ins->baddr0 = (long)src;
 	ins->op2_value_baddr1 = (long)dest;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
 	ins->tri1_bufsize = bufsize;
-	gru_start_instruction(ins, __opword(OP_BCOPY, 0, xtype, IAA_RAM,
-					IAA_RAM, CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_BCOPY, 0, xtype, IAA_RAM,
+					IAA_RAM, tri0, CB_IMA(hints)));
 }
 
 static inline void gru_bstore(void *cb, const unsigned long src,
@@ -470,9 +504,8 @@
 	ins->baddr0 = (long)src;
 	ins->op2_value_baddr1 = (long)dest;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
-	gru_start_instruction(ins, __opword(OP_BSTORE, 0, xtype, 0, IAA_RAM,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_BSTORE, 0, xtype, 0, IAA_RAM,
+					tri0, CB_IMA(hints)));
 }
 
 static inline void gru_gamir(void *cb, int exopc, unsigned long src,
@@ -481,8 +514,8 @@
 	struct gru_instruction *ins = (void *)cb;
 
 	ins->baddr0 = (long)src;
-	gru_start_instruction(ins, __opword(OP_GAMIR, exopc, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_GAMIR, exopc, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_gamirr(void *cb, int exopc, unsigned long src,
@@ -491,8 +524,8 @@
 	struct gru_instruction *ins = (void *)cb;
 
 	ins->baddr0 = (long)src;
-	gru_start_instruction(ins, __opword(OP_GAMIRR, exopc, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_GAMIRR, exopc, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_gamer(void *cb, int exopc, unsigned long src,
@@ -505,8 +538,8 @@
 	ins->baddr0 = (long)src;
 	ins->op1_stride = operand1;
 	ins->op2_value_baddr1 = operand2;
-	gru_start_instruction(ins, __opword(OP_GAMER, exopc, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_GAMER, exopc, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_gamerr(void *cb, int exopc, unsigned long src,
@@ -518,8 +551,8 @@
 	ins->baddr0 = (long)src;
 	ins->op1_stride = operand1;
 	ins->op2_value_baddr1 = operand2;
-	gru_start_instruction(ins, __opword(OP_GAMERR, exopc, xtype, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_GAMERR, exopc, xtype, IAA_RAM, 0,
+					0, CB_IMA(hints)));
 }
 
 static inline void gru_gamxr(void *cb, unsigned long src,
@@ -529,8 +562,8 @@
 
 	ins->baddr0 = (long)src;
 	ins->nelem = 4;
-	gru_start_instruction(ins, __opword(OP_GAMXR, EOP_XR_CSWAP, XTYPE_DW,
-				 IAA_RAM, 0, CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_GAMXR, EOP_XR_CSWAP, XTYPE_DW,
+				 IAA_RAM, 0, 0, CB_IMA(hints)));
 }
 
 static inline void gru_mesq(void *cb, unsigned long queue,
@@ -541,9 +574,8 @@
 
 	ins->baddr0 = (long)queue;
 	ins->nelem = nelem;
-	ins->tri0 = tri0;
-	gru_start_instruction(ins, __opword(OP_MESQ, 0, XTYPE_CL, IAA_RAM, 0,
-					CB_IMA(hints)));
+	gru_start_instruction(ins, __opdword(OP_MESQ, 0, XTYPE_CL, IAA_RAM, 0,
+					tri0, CB_IMA(hints)));
 }
 
 static inline unsigned long gru_get_amo_value(void *cb)
@@ -662,6 +694,14 @@
 	gru_wait_abort_proc(cb);
 }
 
+/*
+ * Get a pointer to the start of a gseg
+ * 	p	- Any valid pointer within the gseg
+ */
+static inline void *gru_get_gseg_pointer (void *p)
+{
+	return (void *)((unsigned long)p & ~(GRU_GSEG_PAGESIZE - 1));
+}
 
 /*
  * Get a pointer to a control block
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 679e017..38657cd 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -40,6 +40,12 @@
 #include "gru_instructions.h"
 #include <asm/uv/uv_hub.h>
 
+/* Return codes for vtop functions */
+#define VTOP_SUCCESS               0
+#define VTOP_INVALID               -1
+#define VTOP_RETRY                 -2
+
+
 /*
  * Test if a physical address is a valid GRU GSEG address
  */
@@ -90,19 +96,22 @@
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	struct gru_thread_state *gts = NULL;
+	struct gru_thread_state *gts = ERR_PTR(-EINVAL);
 
 	down_write(&mm->mmap_sem);
 	vma = gru_find_vma(vaddr);
-	if (vma)
-		gts = gru_alloc_thread_state(vma, TSID(vaddr, vma));
-	if (gts) {
-		mutex_lock(&gts->ts_ctxlock);
-		downgrade_write(&mm->mmap_sem);
-	} else {
-		up_write(&mm->mmap_sem);
-	}
+	if (!vma)
+		goto err;
 
+	gts = gru_alloc_thread_state(vma, TSID(vaddr, vma));
+	if (IS_ERR(gts))
+		goto err;
+	mutex_lock(&gts->ts_ctxlock);
+	downgrade_write(&mm->mmap_sem);
+	return gts;
+
+err:
+	up_write(&mm->mmap_sem);
 	return gts;
 }
 
@@ -122,39 +131,15 @@
  * is necessary to prevent the user from seeing a stale cb.istatus that will
  * change as soon as the TFH restart is complete. Races may cause an
  * occasional failure to clear the cb.istatus, but that is ok.
- *
- * If the cb address is not valid (should not happen, but...), nothing
- * bad will happen.. The get_user()/put_user() will fail but there
- * are no bad side-effects.
  */
-static void gru_cb_set_istatus_active(unsigned long __user *cb)
+static void gru_cb_set_istatus_active(struct gru_instruction_bits *cbk)
 {
-	union {
-		struct gru_instruction_bits bits;
-		unsigned long dw;
-	} u;
-
-	if (cb) {
-		get_user(u.dw, cb);
-		u.bits.istatus = CBS_ACTIVE;
-		put_user(u.dw, cb);
+	if (cbk) {
+		cbk->istatus = CBS_ACTIVE;
 	}
 }
 
 /*
- * Convert a interrupt IRQ to a pointer to the GRU GTS that caused the
- * interrupt. Interrupts are always sent to a cpu on the blade that contains the
- * GRU (except for headless blades which are not currently supported). A blade
- * has N grus; a block of N consecutive IRQs is assigned to the GRUs. The IRQ
- * number uniquely identifies the GRU chiplet on the local blade that caused the
- * interrupt. Always called in interrupt context.
- */
-static inline struct gru_state *irq_to_gru(int irq)
-{
-	return &gru_base[uv_numa_blade_id()]->bs_grus[irq - IRQ_GRU];
-}
-
-/*
  * Read & clear a TFM
  *
  * The GRU has an array of fault maps. A map is private to a cpu
@@ -207,10 +192,11 @@
 {
 	struct page *page;
 
-	/* ZZZ Need to handle HUGE pages */
-	if (is_vm_hugetlb_page(vma))
-		return -EFAULT;
+#ifdef CONFIG_HUGETLB_PAGE
+	*pageshift = is_vm_hugetlb_page(vma) ? HPAGE_SHIFT : PAGE_SHIFT;
+#else
 	*pageshift = PAGE_SHIFT;
+#endif
 	if (get_user_pages
 	    (current, current->mm, vaddr, 1, write, 0, &page, NULL) <= 0)
 		return -EFAULT;
@@ -268,7 +254,6 @@
 	return 0;
 
 err:
-	local_irq_enable();
 	return 1;
 }
 
@@ -301,16 +286,71 @@
 	paddr = paddr & ~((1UL << ps) - 1);
 	*gpa = uv_soc_phys_ram_to_gpa(paddr);
 	*pageshift = ps;
-	return 0;
+	return VTOP_SUCCESS;
 
 inval:
-	return -1;
+	return VTOP_INVALID;
 upm:
-	return -2;
+	return VTOP_RETRY;
 }
 
 
 /*
+ * Flush a CBE from cache. The CBE is clean in the cache. Dirty the
+ * CBE cacheline so that the line will be written back to home agent.
+ * Otherwise the line may be silently dropped. This has no impact
+ * except on performance.
+ */
+static void gru_flush_cache_cbe(struct gru_control_block_extended *cbe)
+{
+	if (unlikely(cbe)) {
+		cbe->cbrexecstatus = 0;         /* make CL dirty */
+		gru_flush_cache(cbe);
+	}
+}
+
+/*
+ * Preload the TLB with entries that may be required. Currently, preloading
+ * is implemented only for BCOPY. Preload  <tlb_preload_count> pages OR to
+ * the end of the bcopy tranfer, whichever is smaller.
+ */
+static void gru_preload_tlb(struct gru_state *gru,
+			struct gru_thread_state *gts, int atomic,
+			unsigned long fault_vaddr, int asid, int write,
+			unsigned char tlb_preload_count,
+			struct gru_tlb_fault_handle *tfh,
+			struct gru_control_block_extended *cbe)
+{
+	unsigned long vaddr = 0, gpa;
+	int ret, pageshift;
+
+	if (cbe->opccpy != OP_BCOPY)
+		return;
+
+	if (fault_vaddr == cbe->cbe_baddr0)
+		vaddr = fault_vaddr + GRU_CACHE_LINE_BYTES * cbe->cbe_src_cl - 1;
+	else if (fault_vaddr == cbe->cbe_baddr1)
+		vaddr = fault_vaddr + (1 << cbe->xtypecpy) * cbe->cbe_nelemcur - 1;
+
+	fault_vaddr &= PAGE_MASK;
+	vaddr &= PAGE_MASK;
+	vaddr = min(vaddr, fault_vaddr + tlb_preload_count * PAGE_SIZE);
+
+	while (vaddr > fault_vaddr) {
+		ret = gru_vtop(gts, vaddr, write, atomic, &gpa, &pageshift);
+		if (ret || tfh_write_only(tfh, gpa, GAA_RAM, vaddr, asid, write,
+					  GRU_PAGESIZE(pageshift)))
+			return;
+		gru_dbg(grudev,
+			"%s: gid %d, gts 0x%p, tfh 0x%p, vaddr 0x%lx, asid 0x%x, rw %d, ps %d, gpa 0x%lx\n",
+			atomic ? "atomic" : "non-atomic", gru->gs_gid, gts, tfh,
+			vaddr, asid, write, pageshift, gpa);
+		vaddr -= PAGE_SIZE;
+		STAT(tlb_preload_page);
+	}
+}
+
+/*
  * Drop a TLB entry into the GRU. The fault is described by info in an TFH.
  *	Input:
  *		cb    Address of user CBR. Null if not running in user context
@@ -320,11 +360,14 @@
  * 		< 0 = error code
  *
  */
-static int gru_try_dropin(struct gru_thread_state *gts,
+static int gru_try_dropin(struct gru_state *gru,
+			  struct gru_thread_state *gts,
 			  struct gru_tlb_fault_handle *tfh,
-			  unsigned long __user *cb)
+			  struct gru_instruction_bits *cbk)
 {
-	int pageshift = 0, asid, write, ret, atomic = !cb;
+	struct gru_control_block_extended *cbe = NULL;
+	unsigned char tlb_preload_count = gts->ts_tlb_preload_count;
+	int pageshift = 0, asid, write, ret, atomic = !cbk, indexway;
 	unsigned long gpa = 0, vaddr = 0;
 
 	/*
@@ -335,24 +378,34 @@
 	 */
 
 	/*
+	 * Prefetch the CBE if doing TLB preloading
+	 */
+	if (unlikely(tlb_preload_count)) {
+		cbe = gru_tfh_to_cbe(tfh);
+		prefetchw(cbe);
+	}
+
+	/*
 	 * Error if TFH state is IDLE or FMM mode & the user issuing a UPM call.
 	 * Might be a hardware race OR a stupid user. Ignore FMM because FMM
 	 * is a transient state.
 	 */
 	if (tfh->status != TFHSTATUS_EXCEPTION) {
 		gru_flush_cache(tfh);
+		sync_core();
 		if (tfh->status != TFHSTATUS_EXCEPTION)
 			goto failnoexception;
 		STAT(tfh_stale_on_fault);
 	}
 	if (tfh->state == TFHSTATE_IDLE)
 		goto failidle;
-	if (tfh->state == TFHSTATE_MISS_FMM && cb)
+	if (tfh->state == TFHSTATE_MISS_FMM && cbk)
 		goto failfmm;
 
 	write = (tfh->cause & TFHCAUSE_TLB_MOD) != 0;
 	vaddr = tfh->missvaddr;
 	asid = tfh->missasid;
+	indexway = tfh->indexway;
 	if (asid == 0)
 		goto failnoasid;
 
@@ -366,41 +419,51 @@
 		goto failactive;
 
 	ret = gru_vtop(gts, vaddr, write, atomic, &gpa, &pageshift);
-	if (ret == -1)
+	if (ret == VTOP_INVALID)
 		goto failinval;
-	if (ret == -2)
+	if (ret == VTOP_RETRY)
 		goto failupm;
 
 	if (!(gts->ts_sizeavail & GRU_SIZEAVAIL(pageshift))) {
 		gts->ts_sizeavail |= GRU_SIZEAVAIL(pageshift);
-		if (atomic || !gru_update_cch(gts, 0)) {
+		if (atomic || !gru_update_cch(gts)) {
 			gts->ts_force_cch_reload = 1;
 			goto failupm;
 		}
 	}
-	gru_cb_set_istatus_active(cb);
+
+	if (unlikely(cbe) && pageshift == PAGE_SHIFT) {
+		gru_preload_tlb(gru, gts, atomic, vaddr, asid, write, tlb_preload_count, tfh, cbe);
+		gru_flush_cache_cbe(cbe);
+	}
+
+	gru_cb_set_istatus_active(cbk);
+	gts->ustats.tlbdropin++;
 	tfh_write_restart(tfh, gpa, GAA_RAM, vaddr, asid, write,
 			  GRU_PAGESIZE(pageshift));
-	STAT(tlb_dropin);
 	gru_dbg(grudev,
-		"%s: tfh 0x%p, vaddr 0x%lx, asid 0x%x, ps %d, gpa 0x%lx\n",
-		ret ? "non-atomic" : "atomic", tfh, vaddr, asid,
-		pageshift, gpa);
+		"%s: gid %d, gts 0x%p, tfh 0x%p, vaddr 0x%lx, asid 0x%x, indexway 0x%x,"
+		" rw %d, ps %d, gpa 0x%lx\n",
+		atomic ? "atomic" : "non-atomic", gru->gs_gid, gts, tfh, vaddr, asid,
+		indexway, write, pageshift, gpa);
+	STAT(tlb_dropin);
 	return 0;
 
 failnoasid:
 	/* No asid (delayed unload). */
 	STAT(tlb_dropin_fail_no_asid);
 	gru_dbg(grudev, "FAILED no_asid tfh: 0x%p, vaddr 0x%lx\n", tfh, vaddr);
-	if (!cb)
+	if (!cbk)
 		tfh_user_polling_mode(tfh);
 	else
 		gru_flush_cache(tfh);
+	gru_flush_cache_cbe(cbe);
 	return -EAGAIN;
 
 failupm:
 	/* Atomic failure switch CBR to UPM */
 	tfh_user_polling_mode(tfh);
+	gru_flush_cache_cbe(cbe);
 	STAT(tlb_dropin_fail_upm);
 	gru_dbg(grudev, "FAILED upm tfh: 0x%p, vaddr 0x%lx\n", tfh, vaddr);
 	return 1;
@@ -408,6 +471,7 @@
 failfmm:
 	/* FMM state on UPM call */
 	gru_flush_cache(tfh);
+	gru_flush_cache_cbe(cbe);
 	STAT(tlb_dropin_fail_fmm);
 	gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state);
 	return 0;
@@ -415,17 +479,20 @@
 failnoexception:
 	/* TFH status did not show exception pending */
 	gru_flush_cache(tfh);
-	if (cb)
-		gru_flush_cache(cb);
+	gru_flush_cache_cbe(cbe);
+	if (cbk)
+		gru_flush_cache(cbk);
 	STAT(tlb_dropin_fail_no_exception);
-	gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state);
+	gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n",
+		tfh, tfh->status, tfh->state);
 	return 0;
 
 failidle:
 	/* TFH state was idle  - no miss pending */
 	gru_flush_cache(tfh);
-	if (cb)
-		gru_flush_cache(cb);
+	gru_flush_cache_cbe(cbe);
+	if (cbk)
+		gru_flush_cache(cbk);
 	STAT(tlb_dropin_fail_idle);
 	gru_dbg(grudev, "FAILED idle tfh: 0x%p, state %d\n", tfh, tfh->state);
 	return 0;
@@ -433,16 +500,18 @@
 failinval:
 	/* All errors (atomic & non-atomic) switch CBR to EXCEPTION state */
 	tfh_exception(tfh);
+	gru_flush_cache_cbe(cbe);
 	STAT(tlb_dropin_fail_invalid);
 	gru_dbg(grudev, "FAILED inval tfh: 0x%p, vaddr 0x%lx\n", tfh, vaddr);
 	return -EFAULT;
 
 failactive:
 	/* Range invalidate active. Switch to UPM iff atomic */
-	if (!cb)
+	if (!cbk)
 		tfh_user_polling_mode(tfh);
 	else
 		gru_flush_cache(tfh);
+	gru_flush_cache_cbe(cbe);
 	STAT(tlb_dropin_fail_range_active);
 	gru_dbg(grudev, "FAILED range active: tfh 0x%p, vaddr 0x%lx\n",
 		tfh, vaddr);
@@ -455,31 +524,41 @@
  * Note that this is the interrupt handler that is registered with linux
  * interrupt handlers.
  */
-irqreturn_t gru_intr(int irq, void *dev_id)
+static irqreturn_t gru_intr(int chiplet, int blade)
 {
 	struct gru_state *gru;
 	struct gru_tlb_fault_map imap, dmap;
 	struct gru_thread_state *gts;
 	struct gru_tlb_fault_handle *tfh = NULL;
+	struct completion *cmp;
 	int cbrnum, ctxnum;
 
 	STAT(intr);
 
-	gru = irq_to_gru(irq);
+	gru = &gru_base[blade]->bs_grus[chiplet];
 	if (!gru) {
-		dev_err(grudev, "GRU: invalid interrupt: cpu %d, irq %d\n",
-			raw_smp_processor_id(), irq);
+		dev_err(grudev, "GRU: invalid interrupt: cpu %d, chiplet %d\n",
+			raw_smp_processor_id(), chiplet);
 		return IRQ_NONE;
 	}
 	get_clear_fault_map(gru, &imap, &dmap);
+	gru_dbg(grudev,
+		"cpu %d, chiplet %d, gid %d, imap %016lx %016lx, dmap %016lx %016lx\n",
+		smp_processor_id(), chiplet, gru->gs_gid,
+		imap.fault_bits[0], imap.fault_bits[1],
+		dmap.fault_bits[0], dmap.fault_bits[1]);
 
 	for_each_cbr_in_tfm(cbrnum, dmap.fault_bits) {
-		complete(gru->gs_blade->bs_async_wq);
+		STAT(intr_cbr);
+		cmp = gru->gs_blade->bs_async_wq;
+		if (cmp)
+			complete(cmp);
 		gru_dbg(grudev, "gid %d, cbr_done %d, done %d\n",
-			gru->gs_gid, cbrnum, gru->gs_blade->bs_async_wq->done);
+			gru->gs_gid, cbrnum, cmp ? cmp->done : -1);
 	}
 
 	for_each_cbr_in_tfm(cbrnum, imap.fault_bits) {
+		STAT(intr_tfh);
 		tfh = get_tfh_by_index(gru, cbrnum);
 		prefetchw(tfh);	/* Helps on hdw, required for emulator */
 
@@ -492,14 +571,20 @@
 		ctxnum = tfh->ctxnum;
 		gts = gru->gs_gts[ctxnum];
 
+		/* Spurious interrupts can cause this. Ignore. */
+		if (!gts) {
+			STAT(intr_spurious);
+			continue;
+		}
+
 		/*
 		 * This is running in interrupt context. Trylock the mmap_sem.
 		 * If it fails, retry the fault in user context.
 		 */
+		gts->ustats.fmm_tlbmiss++;
 		if (!gts->ts_force_cch_reload &&
 					down_read_trylock(&gts->ts_mm->mmap_sem)) {
-			gts->ustats.fmm_tlbdropin++;
-			gru_try_dropin(gts, tfh, NULL);
+			gru_try_dropin(gru, gts, tfh, NULL);
 			up_read(&gts->ts_mm->mmap_sem);
 		} else {
 			tfh_user_polling_mode(tfh);
@@ -509,20 +594,43 @@
 	return IRQ_HANDLED;
 }
 
+irqreturn_t gru0_intr(int irq, void *dev_id)
+{
+	return gru_intr(0, uv_numa_blade_id());
+}
+
+irqreturn_t gru1_intr(int irq, void *dev_id)
+{
+	return gru_intr(1, uv_numa_blade_id());
+}
+
+irqreturn_t gru_intr_mblade(int irq, void *dev_id)
+{
+	int blade;
+
+	for_each_possible_blade(blade) {
+		if (uv_blade_nr_possible_cpus(blade))
+			continue;
+		 gru_intr(0, blade);
+		 gru_intr(1, blade);
+	}
+	return IRQ_HANDLED;
+}
+
 
 static int gru_user_dropin(struct gru_thread_state *gts,
 			   struct gru_tlb_fault_handle *tfh,
-			   unsigned long __user *cb)
+			   void *cb)
 {
 	struct gru_mm_struct *gms = gts->ts_gms;
 	int ret;
 
-	gts->ustats.upm_tlbdropin++;
+	gts->ustats.upm_tlbmiss++;
 	while (1) {
 		wait_event(gms->ms_wait_queue,
 			   atomic_read(&gms->ms_range_active) == 0);
 		prefetchw(tfh);	/* Helps on hdw, required for emulator */
-		ret = gru_try_dropin(gts, tfh, cb);
+		ret = gru_try_dropin(gts->ts_gru, gts, tfh, cb);
 		if (ret <= 0)
 			return ret;
 		STAT(call_os_wait_queue);
@@ -538,52 +646,41 @@
 {
 	struct gru_tlb_fault_handle *tfh;
 	struct gru_thread_state *gts;
-	unsigned long __user *cbp;
+	void *cbk;
 	int ucbnum, cbrnum, ret = -EINVAL;
 
 	STAT(call_os);
-	gru_dbg(grudev, "address 0x%lx\n", cb);
 
 	/* sanity check the cb pointer */
 	ucbnum = get_cb_number((void *)cb);
 	if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB)
 		return -EINVAL;
-	cbp = (unsigned long *)cb;
 
 	gts = gru_find_lock_gts(cb);
 	if (!gts)
 		return -EINVAL;
+	gru_dbg(grudev, "address 0x%lx, gid %d, gts 0x%p\n", cb, gts->ts_gru ? gts->ts_gru->gs_gid : -1, gts);
 
 	if (ucbnum >= gts->ts_cbr_au_count * GRU_CBR_AU_SIZE)
 		goto exit;
 
-	/*
-	 * If force_unload is set, the UPM TLB fault is phony. The task
-	 * has migrated to another node and the GSEG must be moved. Just
-	 * unload the context. The task will page fault and assign a new
-	 * context.
-	 */
-	if (gts->ts_tgid_owner == current->tgid && gts->ts_blade >= 0 &&
-				gts->ts_blade != uv_numa_blade_id()) {
-		STAT(call_os_offnode_reference);
-		gts->ts_force_unload = 1;
-	}
+	gru_check_context_placement(gts);
 
 	/*
 	 * CCH may contain stale data if ts_force_cch_reload is set.
 	 */
 	if (gts->ts_gru && gts->ts_force_cch_reload) {
 		gts->ts_force_cch_reload = 0;
-		gru_update_cch(gts, 0);
+		gru_update_cch(gts);
 	}
 
 	ret = -EAGAIN;
 	cbrnum = thread_cbr_number(gts, ucbnum);
-	if (gts->ts_force_unload) {
-		gru_unload_context(gts, 1);
-	} else if (gts->ts_gru) {
+	if (gts->ts_gru) {
 		tfh = get_tfh_by_index(gts->ts_gru, cbrnum);
-		ret = gru_user_dropin(gts, tfh, cbp);
+		cbk = get_gseg_base_address_cb(gts->ts_gru->gs_gru_base_vaddr,
+				gts->ts_ctxnum, ucbnum);
+		ret = gru_user_dropin(gts, tfh, cbk);
 	}
 exit:
 	gru_unlock_gts(gts);
@@ -605,11 +702,11 @@
 	if (copy_from_user(&excdet, (void __user *)arg, sizeof(excdet)))
 		return -EFAULT;
 
-	gru_dbg(grudev, "address 0x%lx\n", excdet.cb);
 	gts = gru_find_lock_gts(excdet.cb);
 	if (!gts)
 		return -EINVAL;
 
+	gru_dbg(grudev, "address 0x%lx, gid %d, gts 0x%p\n", excdet.cb, gts->ts_gru ? gts->ts_gru->gs_gid : -1, gts);
 	ucbnum = get_cb_number((void *)excdet.cb);
 	if (ucbnum >= gts->ts_cbr_au_count * GRU_CBR_AU_SIZE) {
 		ret = -EINVAL;
@@ -617,6 +714,7 @@
 		cbrnum = thread_cbr_number(gts, ucbnum);
 		cbe = get_cbe_by_index(gts->ts_gru, cbrnum);
 		gru_flush_cache(cbe);	/* CBE not coherent */
+		sync_core();		/* make sure we are have current data */
 		excdet.opc = cbe->opccpy;
 		excdet.exopc = cbe->exopccpy;
 		excdet.ecause = cbe->ecause;
@@ -624,7 +722,7 @@
 		excdet.exceptdet1 = cbe->idef3upd;
 		excdet.cbrstate = cbe->cbrstate;
 		excdet.cbrexecstatus = cbe->cbrexecstatus;
-		gru_flush_cache(cbe);
+		gru_flush_cache_cbe(cbe);
 		ret = 0;
 	} else {
 		ret = -EAGAIN;
@@ -733,6 +831,11 @@
 	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
 		return -EFAULT;
 
+	/*
+	 * The library creates arrays of contexts for threaded programs.
+	 * If no gts exists in the array, the context has never been used & all
+	 * statistics are implicitly 0.
+	 */
 	gts = gru_find_lock_gts(req.gseg);
 	if (gts) {
 		memcpy(&req.stats, &gts->ustats, sizeof(gts->ustats));
@@ -762,11 +865,25 @@
 		return -EFAULT;
 	gru_dbg(grudev, "op %d, gseg 0x%lx, value1 0x%lx\n", req.op, req.gseg, req.val1);
 
-	gts = gru_alloc_locked_gts(req.gseg);
-	if (!gts)
-		return -EINVAL;
+	gts = gru_find_lock_gts(req.gseg);
+	if (!gts) {
+		gts = gru_alloc_locked_gts(req.gseg);
+		if (IS_ERR(gts))
+			return PTR_ERR(gts);
+	}
 
 	switch (req.op) {
+	case sco_blade_chiplet:
+		/* Select blade/chiplet for GRU context */
+		if (req.val1 < -1 || req.val1 >= GRU_MAX_BLADES || !gru_base[req.val1] ||
+		    req.val0 < -1 || req.val0 >= GRU_CHIPLETS_PER_HUB) {
+			ret = -EINVAL;
+		} else {
+			gts->ts_user_blade_id = req.val1;
+			gts->ts_user_chiplet_id = req.val0;
+			gru_check_context_placement(gts);
+		}
+		break;
 	case sco_gseg_owner:
  		/* Register the current task as the GSEG owner */
 		gts->ts_tgid_owner = current->tgid;
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c
index ce5eda9..cb3b4d2 100644
--- a/drivers/misc/sgi-gru/grufile.c
+++ b/drivers/misc/sgi-gru/grufile.c
@@ -35,6 +35,9 @@
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/uaccess.h>
+#ifdef CONFIG_X86_64
+#include <asm/uv/uv_irq.h>
+#endif
 #include <asm/uv/uv.h>
 #include "gru.h"
 #include "grulib.h"
@@ -130,7 +133,6 @@
 	struct gru_vma_data *vdata;
 	int ret = -EINVAL;
 
-
 	if (copy_from_user(&req, (void __user *)arg, sizeof(req)))
 		return -EFAULT;
 
@@ -150,6 +152,7 @@
 		vdata->vd_dsr_au_count =
 		    GRU_DS_BYTES_TO_AU(req.data_segment_bytes);
 		vdata->vd_cbr_au_count = GRU_CB_COUNT_TO_AU(req.control_blocks);
+		vdata->vd_tlb_preload_count = req.tlb_preload_count;
 		ret = 0;
 	}
 	up_write(&current->mm->mmap_sem);
@@ -190,7 +193,7 @@
 {
 	int err = -EBADRQC;
 
-	gru_dbg(grudev, "file %p\n", file);
+	gru_dbg(grudev, "file %p, req 0x%x, 0x%lx\n", file, req, arg);
 
 	switch (req) {
 	case GRU_CREATE_CONTEXT:
@@ -232,23 +235,24 @@
  * system.
  */
 static void gru_init_chiplet(struct gru_state *gru, unsigned long paddr,
-			     void *vaddr, int nid, int bid, int grunum)
+			     void *vaddr, int blade_id, int chiplet_id)
 {
 	spin_lock_init(&gru->gs_lock);
 	spin_lock_init(&gru->gs_asid_lock);
 	gru->gs_gru_base_paddr = paddr;
 	gru->gs_gru_base_vaddr = vaddr;
-	gru->gs_gid = bid * GRU_CHIPLETS_PER_BLADE + grunum;
-	gru->gs_blade = gru_base[bid];
-	gru->gs_blade_id = bid;
+	gru->gs_gid = blade_id * GRU_CHIPLETS_PER_BLADE + chiplet_id;
+	gru->gs_blade = gru_base[blade_id];
+	gru->gs_blade_id = blade_id;
+	gru->gs_chiplet_id = chiplet_id;
 	gru->gs_cbr_map = (GRU_CBR_AU == 64) ? ~0 : (1UL << GRU_CBR_AU) - 1;
 	gru->gs_dsr_map = (1UL << GRU_DSR_AU) - 1;
 	gru->gs_asid_limit = MAX_ASID;
 	gru_tgh_flush_init(gru);
 	if (gru->gs_gid >= gru_max_gids)
 		gru_max_gids = gru->gs_gid + 1;
-	gru_dbg(grudev, "bid %d, nid %d, gid %d, vaddr %p (0x%lx)\n",
-		bid, nid, gru->gs_gid, gru->gs_gru_base_vaddr,
+	gru_dbg(grudev, "bid %d, gid %d, vaddr %p (0x%lx)\n",
+		blade_id, gru->gs_gid, gru->gs_gru_base_vaddr,
 		gru->gs_gru_base_paddr);
 }
 
@@ -264,12 +268,10 @@
 
 	max_user_cbrs = GRU_NUM_CB;
 	max_user_dsr_bytes = GRU_NUM_DSR_BYTES;
-	for_each_online_node(nid) {
-		bid = uv_node_to_blade_id(nid);
-		pnode = uv_node_to_pnode(nid);
-		if (bid < 0 || gru_base[bid])
-			continue;
-		page = alloc_pages_exact_node(nid, GFP_KERNEL, order);
+	for_each_possible_blade(bid) {
+		pnode = uv_blade_to_pnode(bid);
+		nid = uv_blade_to_memory_nid(bid);/* -1 if no memory on blade */
+		page = alloc_pages_node(nid, GFP_KERNEL, order);
 		if (!page)
 			goto fail;
 		gru_base[bid] = page_address(page);
@@ -285,7 +287,7 @@
 				chip++, gru++) {
 			paddr = gru_chiplet_paddr(gru_base_paddr, pnode, chip);
 			vaddr = gru_chiplet_vaddr(gru_base_vaddr, pnode, chip);
-			gru_init_chiplet(gru, paddr, vaddr, nid, bid, chip);
+			gru_init_chiplet(gru, paddr, vaddr, bid, chip);
 			n = hweight64(gru->gs_cbr_map) * GRU_CBR_AU_SIZE;
 			cbrs = max(cbrs, n);
 			n = hweight64(gru->gs_dsr_map) * GRU_DSR_AU_BYTES;
@@ -298,39 +300,215 @@
 	return 0;
 
 fail:
-	for (nid--; nid >= 0; nid--)
-		free_pages((unsigned long)gru_base[nid], order);
+	for (bid--; bid >= 0; bid--)
+		free_pages((unsigned long)gru_base[bid], order);
 	return -ENOMEM;
 }
 
+static void gru_free_tables(void)
+{
+	int bid;
+	int order = get_order(sizeof(struct gru_state) *
+			      GRU_CHIPLETS_PER_BLADE);
+
+	for (bid = 0; bid < GRU_MAX_BLADES; bid++)
+		free_pages((unsigned long)gru_base[bid], order);
+}
+
+static unsigned long gru_chiplet_cpu_to_mmr(int chiplet, int cpu, int *corep)
+{
+	unsigned long mmr = 0;
+	int core;
+
+	/*
+	 * We target the cores of a blade and not the hyperthreads themselves.
+	 * There is a max of 8 cores per socket and 2 sockets per blade,
+	 * making for a max total of 16 cores (i.e., 16 CPUs without
+	 * hyperthreading and 32 CPUs with hyperthreading).
+	 */
+	core = uv_cpu_core_number(cpu) + UV_MAX_INT_CORES * uv_cpu_socket_number(cpu);
+	if (core >= GRU_NUM_TFM || uv_cpu_ht_number(cpu))
+		return 0;
+
+	if (chiplet == 0) {
+		mmr = UVH_GR0_TLB_INT0_CONFIG +
+		    core * (UVH_GR0_TLB_INT1_CONFIG - UVH_GR0_TLB_INT0_CONFIG);
+	} else if (chiplet == 1) {
+		mmr = UVH_GR1_TLB_INT0_CONFIG +
+		    core * (UVH_GR1_TLB_INT1_CONFIG - UVH_GR1_TLB_INT0_CONFIG);
+	} else {
+		BUG();
+	}
+
+	*corep = core;
+	return mmr;
+}
+
 #ifdef CONFIG_IA64
 
-static int get_base_irq(void)
+static int gru_irq_count[GRU_CHIPLETS_PER_BLADE];
+
+static void gru_noop(unsigned int irq)
 {
-	return IRQ_GRU;
+}
+
+static struct irq_chip gru_chip[GRU_CHIPLETS_PER_BLADE] = {
+	[0 ... GRU_CHIPLETS_PER_BLADE - 1] {
+		.mask		= gru_noop,
+		.unmask		= gru_noop,
+		.ack		= gru_noop
+	}
+};
+
+static int gru_chiplet_setup_tlb_irq(int chiplet, char *irq_name,
+			irq_handler_t irq_handler, int cpu, int blade)
+{
+	unsigned long mmr;
+	int irq = IRQ_GRU + chiplet;
+	int ret, core;
+
+	mmr = gru_chiplet_cpu_to_mmr(chiplet, cpu, &core);
+	if (mmr == 0)
+		return 0;
+
+	if (gru_irq_count[chiplet] == 0) {
+		gru_chip[chiplet].name = irq_name;
+		ret = set_irq_chip(irq, &gru_chip[chiplet]);
+		if (ret) {
+			printk(KERN_ERR "%s: set_irq_chip failed, errno=%d\n",
+			       GRU_DRIVER_ID_STR, -ret);
+			return ret;
+		}
+
+		ret = request_irq(irq, irq_handler, 0, irq_name, NULL);
+		if (ret) {
+			printk(KERN_ERR "%s: request_irq failed, errno=%d\n",
+			       GRU_DRIVER_ID_STR, -ret);
+			return ret;
+		}
+	}
+	gru_irq_count[chiplet]++;
+
+	return 0;
+}
+
+static void gru_chiplet_teardown_tlb_irq(int chiplet, int cpu, int blade)
+{
+	unsigned long mmr;
+	int core, irq = IRQ_GRU + chiplet;
+
+	if (gru_irq_count[chiplet] == 0)
+		return;
+
+	mmr = gru_chiplet_cpu_to_mmr(chiplet, cpu, &core);
+	if (mmr == 0)
+		return;
+
+	if (--gru_irq_count[chiplet] == 0)
+		free_irq(irq, NULL);
 }
 
 #elif defined CONFIG_X86_64
 
-static void noop(unsigned int irq)
+static int gru_chiplet_setup_tlb_irq(int chiplet, char *irq_name,
+			irq_handler_t irq_handler, int cpu, int blade)
 {
+	unsigned long mmr;
+	int irq, core;
+	int ret;
+
+	mmr = gru_chiplet_cpu_to_mmr(chiplet, cpu, &core);
+	if (mmr == 0)
+		return 0;
+
+	irq = uv_setup_irq(irq_name, cpu, blade, mmr, UV_AFFINITY_CPU);
+	if (irq < 0) {
+		printk(KERN_ERR "%s: uv_setup_irq failed, errno=%d\n",
+		       GRU_DRIVER_ID_STR, -irq);
+		return irq;
+	}
+
+	ret = request_irq(irq, irq_handler, 0, irq_name, NULL);
+	if (ret) {
+		uv_teardown_irq(irq);
+		printk(KERN_ERR "%s: request_irq failed, errno=%d\n",
+		       GRU_DRIVER_ID_STR, -ret);
+		return ret;
+	}
+	gru_base[blade]->bs_grus[chiplet].gs_irq[core] = irq;
+	return 0;
 }
 
-static struct irq_chip gru_chip = {
-	.name		= "gru",
-	.mask		= noop,
-	.unmask		= noop,
-	.ack		= noop,
-};
-
-static int get_base_irq(void)
+static void gru_chiplet_teardown_tlb_irq(int chiplet, int cpu, int blade)
 {
-	set_irq_chip(IRQ_GRU, &gru_chip);
-	set_irq_chip(IRQ_GRU + 1, &gru_chip);
-	return IRQ_GRU;
+	int irq, core;
+	unsigned long mmr;
+
+	mmr = gru_chiplet_cpu_to_mmr(chiplet, cpu, &core);
+	if (mmr) {
+		irq = gru_base[blade]->bs_grus[chiplet].gs_irq[core];
+		if (irq) {
+			free_irq(irq, NULL);
+			uv_teardown_irq(irq);
+		}
+	}
 }
+
 #endif
 
+static void gru_teardown_tlb_irqs(void)
+{
+	int blade;
+	int cpu;
+
+	for_each_online_cpu(cpu) {
+		blade = uv_cpu_to_blade_id(cpu);
+		gru_chiplet_teardown_tlb_irq(0, cpu, blade);
+		gru_chiplet_teardown_tlb_irq(1, cpu, blade);
+	}
+	for_each_possible_blade(blade) {
+		if (uv_blade_nr_possible_cpus(blade))
+			continue;
+		gru_chiplet_teardown_tlb_irq(0, 0, blade);
+		gru_chiplet_teardown_tlb_irq(1, 0, blade);
+	}
+}
+
+static int gru_setup_tlb_irqs(void)
+{
+	int blade;
+	int cpu;
+	int ret;
+
+	for_each_online_cpu(cpu) {
+		blade = uv_cpu_to_blade_id(cpu);
+		ret = gru_chiplet_setup_tlb_irq(0, "GRU0_TLB", gru0_intr, cpu, blade);
+		if (ret != 0)
+			goto exit1;
+
+		ret = gru_chiplet_setup_tlb_irq(1, "GRU1_TLB", gru1_intr, cpu, blade);
+		if (ret != 0)
+			goto exit1;
+	}
+	for_each_possible_blade(blade) {
+		if (uv_blade_nr_possible_cpus(blade))
+			continue;
+		ret = gru_chiplet_setup_tlb_irq(0, "GRU0_TLB", gru_intr_mblade, 0, blade);
+		if (ret != 0)
+			goto exit1;
+
+		ret = gru_chiplet_setup_tlb_irq(1, "GRU1_TLB", gru_intr_mblade, 0, blade);
+		if (ret != 0)
+			goto exit1;
+	}
+
+	return 0;
+
+exit1:
+	gru_teardown_tlb_irqs();
+	return ret;
+}
+
 /*
  * gru_init
  *
@@ -338,8 +516,7 @@
  */
 static int __init gru_init(void)
 {
-	int ret, irq, chip;
-	char id[10];
+	int ret;
 
 	if (!is_uv_system())
 		return 0;
@@ -354,41 +531,29 @@
 	gru_end_paddr = gru_start_paddr + GRU_MAX_BLADES * GRU_SIZE;
 	printk(KERN_INFO "GRU space: 0x%lx - 0x%lx\n",
 	       gru_start_paddr, gru_end_paddr);
-	irq = get_base_irq();
-	for (chip = 0; chip < GRU_CHIPLETS_PER_BLADE; chip++) {
-		ret = request_irq(irq + chip, gru_intr, 0, id, NULL);
-		/* TODO: fix irq handling on x86. For now ignore failure because
-		 * interrupts are not required & not yet fully supported */
-		if (ret) {
-			printk(KERN_WARNING
-			       "!!!WARNING: GRU ignoring request failure!!!\n");
-			ret = 0;
-		}
-		if (ret) {
-			printk(KERN_ERR "%s: request_irq failed\n",
-			       GRU_DRIVER_ID_STR);
-			goto exit1;
-		}
-	}
-
 	ret = misc_register(&gru_miscdev);
 	if (ret) {
 		printk(KERN_ERR "%s: misc_register failed\n",
 		       GRU_DRIVER_ID_STR);
-		goto exit1;
+		goto exit0;
 	}
 
 	ret = gru_proc_init();
 	if (ret) {
 		printk(KERN_ERR "%s: proc init failed\n", GRU_DRIVER_ID_STR);
-		goto exit2;
+		goto exit1;
 	}
 
 	ret = gru_init_tables(gru_start_paddr, gru_start_vaddr);
 	if (ret) {
 		printk(KERN_ERR "%s: init tables failed\n", GRU_DRIVER_ID_STR);
-		goto exit3;
+		goto exit2;
 	}
+
+	ret = gru_setup_tlb_irqs();
+	if (ret != 0)
+		goto exit3;
+
 	gru_kservices_init();
 
 	printk(KERN_INFO "%s: v%s\n", GRU_DRIVER_ID_STR,
@@ -396,31 +561,24 @@
 	return 0;
 
 exit3:
-	gru_proc_exit();
+	gru_free_tables();
 exit2:
-	misc_deregister(&gru_miscdev);
+	gru_proc_exit();
 exit1:
-	for (--chip; chip >= 0; chip--)
-		free_irq(irq + chip, NULL);
+	misc_deregister(&gru_miscdev);
+exit0:
 	return ret;
 
 }
 
 static void __exit gru_exit(void)
 {
-	int i, bid;
-	int order = get_order(sizeof(struct gru_state) *
-			      GRU_CHIPLETS_PER_BLADE);
-
 	if (!is_uv_system())
 		return;
 
-	for (i = 0; i < GRU_CHIPLETS_PER_BLADE; i++)
-		free_irq(IRQ_GRU + i, NULL);
+	gru_teardown_tlb_irqs();
 	gru_kservices_exit();
-	for (bid = 0; bid < GRU_MAX_BLADES; bid++)
-		free_pages((unsigned long)gru_base[bid], order);
-
+	gru_free_tables();
 	misc_deregister(&gru_miscdev);
 	gru_proc_exit();
 }
diff --git a/drivers/misc/sgi-gru/gruhandles.c b/drivers/misc/sgi-gru/gruhandles.c
index 37e7cfc..2f30bad 100644
--- a/drivers/misc/sgi-gru/gruhandles.c
+++ b/drivers/misc/sgi-gru/gruhandles.c
@@ -27,9 +27,11 @@
 #ifdef CONFIG_IA64
 #include <asm/processor.h>
 #define GRU_OPERATION_TIMEOUT	(((cycles_t) local_cpu_data->itc_freq)*10)
+#define CLKS2NSEC(c)		((c) *1000000000 / local_cpu_data->itc_freq)
 #else
 #include <asm/tsc.h>
 #define GRU_OPERATION_TIMEOUT	((cycles_t) tsc_khz*10*1000)
+#define CLKS2NSEC(c)		((c) * 1000000 / tsc_khz)
 #endif
 
 /* Extract the status field from a kernel handle */
@@ -39,21 +41,39 @@
 
 static void update_mcs_stats(enum mcs_op op, unsigned long clks)
 {
+	unsigned long nsec;
+
+	nsec = CLKS2NSEC(clks);
 	atomic_long_inc(&mcs_op_statistics[op].count);
-	atomic_long_add(clks, &mcs_op_statistics[op].total);
-	if (mcs_op_statistics[op].max < clks)
-		mcs_op_statistics[op].max = clks;
+	atomic_long_add(nsec, &mcs_op_statistics[op].total);
+	if (mcs_op_statistics[op].max < nsec)
+		mcs_op_statistics[op].max = nsec;
 }
 
 static void start_instruction(void *h)
 {
 	unsigned long *w0 = h;
 
-	wmb();		/* setting CMD bit must be last */
-	*w0 = *w0 | 1;
+	wmb();		/* setting CMD/STATUS bits must be last */
+	*w0 = *w0 | 0x20001;
 	gru_flush_cache(h);
 }
 
+static void report_instruction_timeout(void *h)
+{
+	unsigned long goff = GSEGPOFF((unsigned long)h);
+	char *id = "???";
+
+	if (TYPE_IS(CCH, goff))
+		id = "CCH";
+	else if (TYPE_IS(TGH, goff))
+		id = "TGH";
+	else if (TYPE_IS(TFH, goff))
+		id = "TFH";
+
+	panic(KERN_ALERT "GRU %p (%s) is malfunctioning\n", h, id);
+}
+
 static int wait_instruction_complete(void *h, enum mcs_op opc)
 {
 	int status;
@@ -64,9 +84,10 @@
 		status = GET_MSEG_HANDLE_STATUS(h);
 		if (status != CCHSTATUS_ACTIVE)
 			break;
-		if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time))
-			panic("GRU %p is malfunctioning: start %ld, end %ld\n",
-			      h, start_time, (unsigned long)get_cycles());
+		if (GRU_OPERATION_TIMEOUT < (get_cycles() - start_time)) {
+			report_instruction_timeout(h);
+			start_time = get_cycles();
+		}
 	}
 	if (gru_options & OPT_STATS)
 		update_mcs_stats(opc, get_cycles() - start_time);
@@ -75,9 +96,18 @@
 
 int cch_allocate(struct gru_context_configuration_handle *cch)
 {
+	int ret;
+
 	cch->opc = CCHOP_ALLOCATE;
 	start_instruction(cch);
-	return wait_instruction_complete(cch, cchop_allocate);
+	ret = wait_instruction_complete(cch, cchop_allocate);
+
+	/*
+	 * Stop speculation into the GSEG being mapped by the previous ALLOCATE.
+	 * The GSEG memory does not exist until the ALLOCATE completes.
+	 */
+	sync_core();
+	return ret;
 }
 
 int cch_start(struct gru_context_configuration_handle *cch)
@@ -96,9 +126,18 @@
 
 int cch_deallocate(struct gru_context_configuration_handle *cch)
 {
+	int ret;
+
 	cch->opc = CCHOP_DEALLOCATE;
 	start_instruction(cch);
-	return wait_instruction_complete(cch, cchop_deallocate);
+	ret = wait_instruction_complete(cch, cchop_deallocate);
+
+	/*
+	 * Stop speculation into the GSEG being unmapped by the previous
+	 * DEALLOCATE.
+	 */
+	sync_core();
+	return ret;
 }
 
 int cch_interrupt_sync(struct gru_context_configuration_handle
@@ -126,17 +165,20 @@
 	return wait_instruction_complete(tgh, tghop_invalidate);
 }
 
-void tfh_write_only(struct gru_tlb_fault_handle *tfh,
-				  unsigned long pfn, unsigned long vaddr,
-				  int asid, int dirty, int pagesize)
+int tfh_write_only(struct gru_tlb_fault_handle *tfh,
+				  unsigned long paddr, int gaa,
+				  unsigned long vaddr, int asid, int dirty,
+				  int pagesize)
 {
 	tfh->fillasid = asid;
 	tfh->fillvaddr = vaddr;
-	tfh->pfn = pfn;
+	tfh->pfn = paddr >> GRU_PADDR_SHIFT;
+	tfh->gaa = gaa;
 	tfh->dirty = dirty;
 	tfh->pagesize = pagesize;
 	tfh->opc = TFHOP_WRITE_ONLY;
 	start_instruction(tfh);
+	return wait_instruction_complete(tfh, tfhop_write_only);
 }
 
 void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
diff --git a/drivers/misc/sgi-gru/gruhandles.h b/drivers/misc/sgi-gru/gruhandles.h
index f441122..3f998b9 100644
--- a/drivers/misc/sgi-gru/gruhandles.h
+++ b/drivers/misc/sgi-gru/gruhandles.h
@@ -91,6 +91,12 @@
 /* Convert an arbitrary handle address to the beginning of the GRU segment */
 #define GRUBASE(h)		((void *)((unsigned long)(h) & ~(GRU_SIZE - 1)))
 
+/* Test a valid handle address to determine the type */
+#define TYPE_IS(hn, h)		((h) >= GRU_##hn##_BASE && (h) <	\
+		GRU_##hn##_BASE + GRU_NUM_##hn * GRU_HANDLE_STRIDE &&   \
+		(((h) & (GRU_HANDLE_STRIDE - 1)) == 0))
+
+
 /* General addressing macros. */
 static inline void *get_gseg_base_address(void *base, int ctxnum)
 {
@@ -158,6 +164,16 @@
 	return vaddr + GRU_SIZE * (2 * pnode  + chiplet);
 }
 
+static inline struct gru_control_block_extended *gru_tfh_to_cbe(
+					struct gru_tlb_fault_handle *tfh)
+{
+	unsigned long cbe;
+
+	cbe = (unsigned long)tfh - GRU_TFH_BASE + GRU_CBE_BASE;
+	return (struct gru_control_block_extended*)cbe;
+}
+
+
 
 
 /*
@@ -236,6 +252,17 @@
 	TGHSTATE_RESTART_CTX,
 };
 
+enum gru_tgh_cause {
+	TGHCAUSE_RR_ECC,
+	TGHCAUSE_TLB_ECC,
+	TGHCAUSE_LRU_ECC,
+	TGHCAUSE_PS_ECC,
+	TGHCAUSE_MUL_ERR,
+	TGHCAUSE_DATA_ERR,
+	TGHCAUSE_SW_FORCE
+};
+
+
 /*
  * TFH - TLB Global Handle
  * 	Used for TLB dropins into the GRU TLB.
@@ -440,6 +467,12 @@
 	unsigned int cbrexecstatus:8;
 };
 
+/* CBE fields for active BCOPY instructions */
+#define cbe_baddr0	idef1upd
+#define cbe_baddr1	idef3upd
+#define cbe_src_cl	idef6cpy
+#define cbe_nelemcur	idef5upd
+
 enum gru_cbr_state {
 	CBRSTATE_INACTIVE,
 	CBRSTATE_IDLE,
@@ -487,8 +520,8 @@
 int tgh_invalidate(struct gru_tlb_global_handle *tgh, unsigned long vaddr,
 	unsigned long vaddrmask, int asid, int pagesize, int global, int n,
 	unsigned short ctxbitmap);
-void tfh_write_only(struct gru_tlb_fault_handle *tfh, unsigned long pfn,
-	unsigned long vaddr, int asid, int dirty, int pagesize);
+int tfh_write_only(struct gru_tlb_fault_handle *tfh, unsigned long paddr,
+	int gaa, unsigned long vaddr, int asid, int dirty, int pagesize);
 void tfh_write_restart(struct gru_tlb_fault_handle *tfh, unsigned long paddr,
 	int gaa, unsigned long vaddr, int asid, int dirty, int pagesize);
 void tfh_restart(struct gru_tlb_fault_handle *tfh);
diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c
index 55eabfa..9b2062d 100644
--- a/drivers/misc/sgi-gru/grukdump.c
+++ b/drivers/misc/sgi-gru/grukdump.c
@@ -44,7 +44,8 @@
 
 static int gru_dump_context_data(void *grubase,
 			struct gru_context_configuration_handle *cch,
-			void __user *ubuf, int ctxnum, int dsrcnt)
+			void __user *ubuf, int ctxnum, int dsrcnt,
+			int flush_cbrs)
 {
 	void *cb, *cbe, *tfh, *gseg;
 	int i, scr;
@@ -55,6 +56,8 @@
 	tfh = grubase + GRU_TFH_BASE;
 
 	for_each_cbr_in_allocation_map(i, &cch->cbr_allocation_map, scr) {
+		if (flush_cbrs)
+			gru_flush_cache(cb);
 		if (gru_user_copy_handle(&ubuf, cb))
 			goto fail;
 		if (gru_user_copy_handle(&ubuf, tfh + i * GRU_HANDLE_STRIDE))
@@ -115,7 +118,7 @@
 
 static int gru_dump_context(struct gru_state *gru, int ctxnum,
 		void __user *ubuf, void __user *ubufend, char data_opt,
-		char lock_cch)
+		char lock_cch, char flush_cbrs)
 {
 	struct gru_dump_context_header hdr;
 	struct gru_dump_context_header __user *uhdr = ubuf;
@@ -159,8 +162,7 @@
 			ret = -EFBIG;
 		else
 			ret = gru_dump_context_data(grubase, cch, ubuf, ctxnum,
-							dsrcnt);
-
+							dsrcnt, flush_cbrs);
 	}
 	if (cch_locked)
 		unlock_cch_handle(cch);
@@ -215,7 +217,8 @@
 	for (ctxnum = 0; ctxnum < GRU_NUM_CCH; ctxnum++) {
 		if (req.ctxnum == ctxnum || req.ctxnum < 0) {
 			ret = gru_dump_context(gru, ctxnum, ubuf, ubufend,
-						req.data_opt, req.lock_cch);
+						req.data_opt, req.lock_cch,
+						req.flush_cbrs);
 			if (ret < 0)
 				goto fail;
 			ubuf += ret;
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 766e21e..34749ee 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
 #include <linux/delay.h>
+#include <asm/io_apic.h>
 #include "gru.h"
 #include "grulib.h"
 #include "grutables.h"
@@ -97,9 +98,6 @@
 #define ASYNC_HAN_TO_BID(h)	((h) - 1)
 #define ASYNC_BID_TO_HAN(b)	((b) + 1)
 #define ASYNC_HAN_TO_BS(h)	gru_base[ASYNC_HAN_TO_BID(h)]
-#define KCB_TO_GID(cb)		((cb - gru_start_vaddr) /		\
-					(GRU_SIZE * GRU_CHIPLETS_PER_BLADE))
-#define KCB_TO_BS(cb)		gru_base[KCB_TO_GID(cb)]
 
 #define GRU_NUM_KERNEL_CBR	1
 #define GRU_NUM_KERNEL_DSR_BYTES 256
@@ -160,8 +158,10 @@
 	up_read(&bs->bs_kgts_sema);
 	down_write(&bs->bs_kgts_sema);
 
-	if (!bs->bs_kgts)
-		bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0);
+	if (!bs->bs_kgts) {
+		bs->bs_kgts = gru_alloc_gts(NULL, 0, 0, 0, 0, 0);
+		bs->bs_kgts->ts_user_blade_id = blade_id;
+	}
 	kgts = bs->bs_kgts;
 
 	if (!kgts->ts_gru) {
@@ -172,9 +172,9 @@
 		kgts->ts_dsr_au_count = GRU_DS_BYTES_TO_AU(
 			GRU_NUM_KERNEL_DSR_BYTES * ncpus +
 				bs->bs_async_dsr_bytes);
-		while (!gru_assign_gru_context(kgts, blade_id)) {
+		while (!gru_assign_gru_context(kgts)) {
 			msleep(1);
-			gru_steal_context(kgts, blade_id);
+			gru_steal_context(kgts);
 		}
 		gru_load_context(kgts);
 		gru = bs->bs_kgts->ts_gru;
@@ -200,13 +200,15 @@
 		bs = gru_base[bid];
 		if (!bs)
 			continue;
+
+		/* Ignore busy contexts. Don't want to block here.  */
 		if (down_write_trylock(&bs->bs_kgts_sema)) {
 			kgts = bs->bs_kgts;
 			if (kgts && kgts->ts_gru)
 				gru_unload_context(kgts, 0);
-			kfree(kgts);
 			bs->bs_kgts = NULL;
 			up_write(&bs->bs_kgts_sema);
+			kfree(kgts);
 		} else {
 			ret++;
 		}
@@ -220,13 +222,21 @@
 static struct gru_blade_state *gru_lock_kernel_context(int blade_id)
 {
 	struct gru_blade_state *bs;
+	int bid;
 
 	STAT(lock_kernel_context);
-	bs = gru_base[blade_id];
+again:
+	bid = blade_id < 0 ? uv_numa_blade_id() : blade_id;
+	bs = gru_base[bid];
 
+	/* Handle the case where migration occured while waiting for the sema */
 	down_read(&bs->bs_kgts_sema);
+	if (blade_id < 0 && bid != uv_numa_blade_id()) {
+		up_read(&bs->bs_kgts_sema);
+		goto again;
+	}
 	if (!bs->bs_kgts || !bs->bs_kgts->ts_gru)
-		gru_load_kernel_context(bs, blade_id);
+		gru_load_kernel_context(bs, bid);
 	return bs;
 
 }
@@ -255,7 +265,7 @@
 
 	BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
 	preempt_disable();
-	bs = gru_lock_kernel_context(uv_numa_blade_id());
+	bs = gru_lock_kernel_context(-1);
 	lcpu = uv_blade_processor_id();
 	*cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
 	*dsr = bs->kernel_dsr + lcpu * GRU_NUM_KERNEL_DSR_BYTES;
@@ -384,13 +394,31 @@
 		struct control_block_extended_exc_detail *excdet)
 {
 	struct gru_control_block_extended *cbe;
-	struct gru_blade_state *bs;
-	int cbrnum;
+	struct gru_thread_state *kgts = NULL;
+	unsigned long off;
+	int cbrnum, bid;
 
-	bs = KCB_TO_BS(cb);
-	cbrnum = thread_cbr_number(bs->bs_kgts, get_cb_number(cb));
+	/*
+	 * Locate kgts for cb. This algorithm is SLOW but
+	 * this function is rarely called (ie., almost never).
+	 * Performance does not matter.
+	 */
+	for_each_possible_blade(bid) {
+		if (!gru_base[bid])
+			break;
+		kgts = gru_base[bid]->bs_kgts;
+		if (!kgts || !kgts->ts_gru)
+			continue;
+		off = cb - kgts->ts_gru->gs_gru_base_vaddr;
+		if (off < GRU_SIZE)
+			break;
+		kgts = NULL;
+	}
+	BUG_ON(!kgts);
+	cbrnum = thread_cbr_number(kgts, get_cb_number(cb));
 	cbe = get_cbe(GRUBASE(cb), cbrnum);
 	gru_flush_cache(cbe);	/* CBE not coherent */
+	sync_core();
 	excdet->opc = cbe->opccpy;
 	excdet->exopc = cbe->exopccpy;
 	excdet->ecause = cbe->ecause;
@@ -409,8 +437,8 @@
 	if (ret > 0 && gen->istatus == CBS_EXCEPTION) {
 		gru_get_cb_exception_detail(cb, &excdet);
 		snprintf(buf, size,
-			"GRU exception: cb %p, opc %d, exopc %d, ecause 0x%x,"
-			"excdet0 0x%lx, excdet1 0x%x",
+			"GRU:%d exception: cb %p, opc %d, exopc %d, ecause 0x%x,"
+			"excdet0 0x%lx, excdet1 0x%x", smp_processor_id(),
 			gen, excdet.opc, excdet.exopc, excdet.ecause,
 			excdet.exceptdet0, excdet.exceptdet1);
 	} else {
@@ -457,9 +485,10 @@
 	int ret;
 
 	ret = gen->istatus;
-	if (ret != CBS_EXCEPTION)
-		return ret;
-	return gru_retry_exception(cb);
+	if (ret == CBS_EXCEPTION)
+		ret = gru_retry_exception(cb);
+	rmb();
+	return ret;
 
 }
 
@@ -471,7 +500,7 @@
 	ret = gru_wait_idle_or_exception(gen);
 	if (ret == CBS_EXCEPTION)
 		ret = gru_retry_exception(cb);
-
+	rmb();
 	return ret;
 }
 
@@ -538,7 +567,7 @@
 	mqd->mq = mq;
 	mqd->mq_gpa = uv_gpa(mq);
 	mqd->qlines = qlines;
-	mqd->interrupt_pnode = UV_NASID_TO_PNODE(nasid);
+	mqd->interrupt_pnode = nasid >> 1;
 	mqd->interrupt_vector = vector;
 	mqd->interrupt_apicid = apicid;
 	return 0;
@@ -598,6 +627,8 @@
 				ret = MQE_UNEXPECTED_CB_ERR;
 			break;
 		case CBSS_PAGE_OVERFLOW:
+			STAT(mesq_noop_page_overflow);
+			/* fallthru */
 		default:
 			BUG();
 		}
@@ -673,18 +704,6 @@
 }
 
 /*
- * Send a cross-partition interrupt to the SSI that contains the target
- * message queue. Normally, the interrupt is automatically delivered by hardware
- * but some error conditions require explicit delivery.
- */
-static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd)
-{
-	if (mqd->interrupt_vector)
-		uv_hub_send_ipi(mqd->interrupt_pnode, mqd->interrupt_apicid,
-				mqd->interrupt_vector);
-}
-
-/*
  * Handle a PUT failure. Note: if message was a 2-line message, one of the
  * lines might have successfully have been written. Before sending the
  * message, "present" must be cleared in BOTH lines to prevent the receiver
@@ -693,7 +712,8 @@
 static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
 			void *mesg, int lines)
 {
-	unsigned long m;
+	unsigned long m, *val = mesg, gpa, save;
+	int ret;
 
 	m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
 	if (lines == 2) {
@@ -704,7 +724,26 @@
 	gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
 	if (gru_wait(cb) != CBS_IDLE)
 		return MQE_UNEXPECTED_CB_ERR;
-	send_message_queue_interrupt(mqd);
+
+	if (!mqd->interrupt_vector)
+		return MQE_OK;
+
+	/*
+	 * Send a cross-partition interrupt to the SSI that contains the target
+	 * message queue. Normally, the interrupt is automatically delivered by
+	 * hardware but some error conditions require explicit delivery.
+	 * Use the GRU to deliver the interrupt. Otherwise partition failures
+	 * could cause unrecovered errors.
+	 */
+	gpa = uv_global_gru_mmr_address(mqd->interrupt_pnode, UVH_IPI_INT);
+	save = *val;
+	*val = uv_hub_ipi_value(mqd->interrupt_apicid, mqd->interrupt_vector,
+				dest_Fixed);
+	gru_vstore_phys(cb, gpa, gru_get_tri(mesg), IAA_REGISTER, IMA);
+	ret = gru_wait(cb);
+	*val = save;
+	if (ret != CBS_IDLE)
+		return MQE_UNEXPECTED_CB_ERR;
 	return MQE_OK;
 }
 
@@ -739,6 +778,9 @@
 		STAT(mesq_send_put_nacked);
 		ret = send_message_put_nacked(cb, mqd, mesg, lines);
 		break;
+	case CBSS_PAGE_OVERFLOW:
+		STAT(mesq_page_overflow);
+		/* fallthru */
 	default:
 		BUG();
 	}
@@ -831,7 +873,6 @@
 	int present = mhdr->present;
 
 	/* skip NOOP messages */
-	STAT(mesq_receive);
 	while (present == MQS_NOOP) {
 		gru_free_message(mqd, mhdr);
 		mhdr = mq->next;
@@ -851,6 +892,7 @@
 	if (mhdr->lines == 2)
 		restore_present2(mhdr, mhdr->present2);
 
+	STAT(mesq_receive);
 	return mhdr;
 }
 EXPORT_SYMBOL_GPL(gru_get_next_message);
@@ -858,6 +900,29 @@
 /* ---------------------- GRU DATA COPY FUNCTIONS ---------------------------*/
 
 /*
+ * Load a DW from a global GPA. The GPA can be a memory or MMR address.
+ */
+int gru_read_gpa(unsigned long *value, unsigned long gpa)
+{
+	void *cb;
+	void *dsr;
+	int ret, iaa;
+
+	STAT(read_gpa);
+	if (gru_get_cpu_resources(GRU_NUM_KERNEL_DSR_BYTES, &cb, &dsr))
+		return MQE_BUG_NO_RESOURCES;
+	iaa = gpa >> 62;
+	gru_vload_phys(cb, gpa, gru_get_tri(dsr), iaa, IMA);
+	ret = gru_wait(cb);
+	if (ret == CBS_IDLE)
+		*value = *(unsigned long *)dsr;
+	gru_free_cpu_resources(cb, dsr);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(gru_read_gpa);
+
+
+/*
  * Copy a block of data using the GRU resources
  */
 int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa,
@@ -898,24 +963,24 @@
 
 	gru_vload(cb, uv_gpa(&word0), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
 	if (gru_wait(cb) != CBS_IDLE) {
-		printk(KERN_DEBUG "GRU quicktest0: CBR failure 1\n");
+		printk(KERN_DEBUG "GRU:%d quicktest0: CBR failure 1\n", smp_processor_id());
 		goto done;
 	}
 
 	if (*p != MAGIC) {
-		printk(KERN_DEBUG "GRU: quicktest0 bad magic 0x%lx\n", *p);
+		printk(KERN_DEBUG "GRU:%d quicktest0 bad magic 0x%lx\n", smp_processor_id(), *p);
 		goto done;
 	}
 	gru_vstore(cb, uv_gpa(&word1), gru_get_tri(dsr), XTYPE_DW, 1, 1, IMA);
 	if (gru_wait(cb) != CBS_IDLE) {
-		printk(KERN_DEBUG "GRU quicktest0: CBR failure 2\n");
+		printk(KERN_DEBUG "GRU:%d quicktest0: CBR failure 2\n", smp_processor_id());
 		goto done;
 	}
 
 	if (word0 != word1 || word1 != MAGIC) {
 		printk(KERN_DEBUG
-		       "GRU quicktest0 err: found 0x%lx, expected 0x%lx\n",
-		     word1, MAGIC);
+		       "GRU:%d quicktest0 err: found 0x%lx, expected 0x%lx\n",
+		     smp_processor_id(), word1, MAGIC);
 		goto done;
 	}
 	ret = 0;
@@ -952,8 +1017,11 @@
 		if (ret)
 			break;
 	}
-	if (ret != MQE_QUEUE_FULL || i != 4)
+	if (ret != MQE_QUEUE_FULL || i != 4) {
+		printk(KERN_DEBUG "GRU:%d quicktest1: unexpect status %d, i %d\n",
+		       smp_processor_id(), ret, i);
 		goto done;
+	}
 
 	for (i = 0; i < 6; i++) {
 		m = gru_get_next_message(&mqd);
@@ -961,7 +1029,12 @@
 			break;
 		gru_free_message(&mqd, m);
 	}
-	ret = (i == 4) ? 0 : -EIO;
+	if (i != 4) {
+		printk(KERN_DEBUG "GRU:%d quicktest2: bad message, i %d, m %p, m8 %d\n",
+			smp_processor_id(), i, m, m ? m[8] : -1);
+		goto done;
+	}
+	ret = 0;
 
 done:
 	kfree(p);
@@ -977,6 +1050,7 @@
 	int ret = 0;
 	unsigned long *buf;
 	void *cb0, *cb;
+	struct gru_control_block_status *gen;
 	int i, k, istatus, bytes;
 
 	bytes = numcb * 4 * 8;
@@ -996,20 +1070,30 @@
 				XTYPE_DW, 4, 1, IMA_INTERRUPT);
 
 	ret = 0;
-	for (k = 0; k < numcb; k++) {
+	k = numcb;
+	do {
 		gru_wait_async_cbr(han);
 		for (i = 0; i < numcb; i++) {
 			cb = cb0 + i * GRU_HANDLE_STRIDE;
 			istatus = gru_check_status(cb);
-			if (istatus == CBS_ACTIVE)
-				continue;
-			if (istatus == CBS_EXCEPTION)
-				ret = -EFAULT;
-			else if (buf[i] || buf[i + 1] || buf[i + 2] ||
-					buf[i + 3])
-				ret = -EIO;
+			if (istatus != CBS_ACTIVE && istatus != CBS_CALL_OS)
+				break;
 		}
-	}
+		if (i == numcb)
+			continue;
+		if (istatus != CBS_IDLE) {
+			printk(KERN_DEBUG "GRU:%d quicktest2: cb %d, exception\n", smp_processor_id(), i);
+			ret = -EFAULT;
+		} else if (buf[4 * i] || buf[4 * i + 1] || buf[4 * i + 2] ||
+				buf[4 * i + 3]) {
+			printk(KERN_DEBUG "GRU:%d quicktest2:cb %d,  buf 0x%lx, 0x%lx, 0x%lx, 0x%lx\n",
+			       smp_processor_id(), i, buf[4 * i], buf[4 * i + 1], buf[4 * i + 2], buf[4 * i + 3]);
+			ret = -EIO;
+		}
+		k--;
+		gen = cb;
+		gen->istatus = CBS_CALL_OS; /* don't handle this CBR again */
+	} while (k);
 	BUG_ON(cmp.done);
 
 	gru_unlock_async_resource(han);
@@ -1019,6 +1103,22 @@
 	return ret;
 }
 
+#define BUFSIZE 200
+static int quicktest3(unsigned long arg)
+{
+	char buf1[BUFSIZE], buf2[BUFSIZE];
+	int ret = 0;
+
+	memset(buf2, 0, sizeof(buf2));
+	memset(buf1, get_cycles() & 255, sizeof(buf1));
+	gru_copy_gpa(uv_gpa(buf2), uv_gpa(buf1), BUFSIZE);
+	if (memcmp(buf1, buf2, BUFSIZE)) {
+		printk(KERN_DEBUG "GRU:%d quicktest3 error\n", smp_processor_id());
+		ret = -EIO;
+	}
+	return ret;
+}
+
 /*
  * Debugging only. User hook for various kernel tests
  * of driver & gru.
@@ -1037,6 +1137,9 @@
 	case 2:
 		ret = quicktest2(arg);
 		break;
+	case 3:
+		ret = quicktest3(arg);
+		break;
 	case 99:
 		ret = gru_free_kernel_contexts();
 		break;
diff --git a/drivers/misc/sgi-gru/grukservices.h b/drivers/misc/sgi-gru/grukservices.h
index d60d34b..02aa94d 100644
--- a/drivers/misc/sgi-gru/grukservices.h
+++ b/drivers/misc/sgi-gru/grukservices.h
@@ -131,6 +131,20 @@
 
 
 /*
+ * Read a GRU global GPA. Source can be located in a remote partition.
+ *
+ *    Input:
+ *    	value		memory address where MMR value is returned
+ *    	gpa		source numalink physical address of GPA
+ *
+ *    Output:
+ *	0		OK
+ *	>0		error
+ */
+int gru_read_gpa(unsigned long *value, unsigned long gpa);
+
+
+/*
  * Copy data using the GRU. Source or destination can be located in a remote
  * partition.
  *
diff --git a/drivers/misc/sgi-gru/grulib.h b/drivers/misc/sgi-gru/grulib.h
index 889bc44..e77d1b1 100644
--- a/drivers/misc/sgi-gru/grulib.h
+++ b/drivers/misc/sgi-gru/grulib.h
@@ -63,18 +63,9 @@
 #define THREAD_POINTER(p, th)		(p + GRU_GSEG_PAGESIZE * (th))
 #define GSEG_START(cb)			((void *)((unsigned long)(cb) & ~(GRU_GSEG_PAGESIZE - 1)))
 
-/*
- * Statictics kept on a per-GTS basis.
- */
-struct gts_statistics {
-	unsigned long	fmm_tlbdropin;
-	unsigned long	upm_tlbdropin;
-	unsigned long	context_stolen;
-};
-
 struct gru_get_gseg_statistics_req {
-	unsigned long		gseg;
-	struct gts_statistics	stats;
+	unsigned long			gseg;
+	struct gru_gseg_statistics	stats;
 };
 
 /*
@@ -86,6 +77,7 @@
 	unsigned int		control_blocks;
 	unsigned int		maximum_thread_count;
 	unsigned int		options;
+	unsigned char		tlb_preload_count;
 };
 
 /*
@@ -98,11 +90,12 @@
 /*
  * Structure used to set context options
  */
-enum {sco_gseg_owner, sco_cch_req_slice};
+enum {sco_gseg_owner, sco_cch_req_slice, sco_blade_chiplet};
 struct gru_set_context_option_req {
 	unsigned long	gseg;
 	int		op;
-	unsigned long	val1;
+	int		val0;
+	long		val1;
 };
 
 /*
@@ -124,6 +117,8 @@
 	int		ctxnum;
 	char		data_opt;
 	char		lock_cch;
+	char		flush_cbrs;
+	char		fill[10];
 	pid_t		pid;
 	void		*buf;
 	size_t		buflen;
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 3bc643d..f8538bb 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -27,6 +27,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/list.h>
+#include <linux/err.h>
 #include <asm/uv/uv_hub.h>
 #include "gru.h"
 #include "grutables.h"
@@ -48,12 +49,20 @@
 /*
  * Select a gru fault map to be used by the current cpu. Note that
  * multiple cpus may be using the same map.
- *	ZZZ should "shift" be used?? Depends on HT cpu numbering
  *	ZZZ should be inline but did not work on emulator
  */
 int gru_cpu_fault_map_id(void)
 {
+#ifdef CONFIG_IA64
 	return uv_blade_processor_id() % GRU_NUM_TFM;
+#else
+	int cpu = smp_processor_id();
+	int id, core;
+
+	core = uv_cpu_core_number(cpu);
+	id = core + UV_MAX_INT_CORES * uv_cpu_socket_number(cpu);
+	return id;
+#endif
 }
 
 /*--------- ASID Management -------------------------------------------
@@ -286,7 +295,8 @@
 void gts_drop(struct gru_thread_state *gts)
 {
 	if (gts && atomic_dec_return(&gts->ts_refcnt) == 0) {
-		gru_drop_mmu_notifier(gts->ts_gms);
+		if (gts->ts_gms)
+			gru_drop_mmu_notifier(gts->ts_gms);
 		kfree(gts);
 		STAT(gts_free);
 	}
@@ -310,16 +320,18 @@
  * Allocate a thread state structure.
  */
 struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
-		int cbr_au_count, int dsr_au_count, int options, int tsid)
+		int cbr_au_count, int dsr_au_count,
+		unsigned char tlb_preload_count, int options, int tsid)
 {
 	struct gru_thread_state *gts;
+	struct gru_mm_struct *gms;
 	int bytes;
 
 	bytes = DSR_BYTES(dsr_au_count) + CBR_BYTES(cbr_au_count);
 	bytes += sizeof(struct gru_thread_state);
 	gts = kmalloc(bytes, GFP_KERNEL);
 	if (!gts)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	STAT(gts_alloc);
 	memset(gts, 0, sizeof(struct gru_thread_state)); /* zero out header */
@@ -327,7 +339,10 @@
 	mutex_init(&gts->ts_ctxlock);
 	gts->ts_cbr_au_count = cbr_au_count;
 	gts->ts_dsr_au_count = dsr_au_count;
+	gts->ts_tlb_preload_count = tlb_preload_count;
 	gts->ts_user_options = options;
+	gts->ts_user_blade_id = -1;
+	gts->ts_user_chiplet_id = -1;
 	gts->ts_tsid = tsid;
 	gts->ts_ctxnum = NULLCTX;
 	gts->ts_tlb_int_select = -1;
@@ -336,9 +351,10 @@
 	if (vma) {
 		gts->ts_mm = current->mm;
 		gts->ts_vma = vma;
-		gts->ts_gms = gru_register_mmu_notifier();
-		if (!gts->ts_gms)
+		gms = gru_register_mmu_notifier();
+		if (IS_ERR(gms))
 			goto err;
+		gts->ts_gms = gms;
 	}
 
 	gru_dbg(grudev, "alloc gts %p\n", gts);
@@ -346,7 +362,7 @@
 
 err:
 	gts_drop(gts);
-	return NULL;
+	return ERR_CAST(gms);
 }
 
 /*
@@ -360,6 +376,7 @@
 	if (!vdata)
 		return NULL;
 
+	STAT(vdata_alloc);
 	INIT_LIST_HEAD(&vdata->vd_head);
 	spin_lock_init(&vdata->vd_lock);
 	gru_dbg(grudev, "alloc vdata %p\n", vdata);
@@ -392,10 +409,12 @@
 	struct gru_vma_data *vdata = vma->vm_private_data;
 	struct gru_thread_state *gts, *ngts;
 
-	gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count, vdata->vd_dsr_au_count,
+	gts = gru_alloc_gts(vma, vdata->vd_cbr_au_count,
+			    vdata->vd_dsr_au_count,
+			    vdata->vd_tlb_preload_count,
 			    vdata->vd_user_options, tsid);
-	if (!gts)
-		return NULL;
+	if (IS_ERR(gts))
+		return gts;
 
 	spin_lock(&vdata->vd_lock);
 	ngts = gru_find_current_gts_nolock(vdata, tsid);
@@ -493,6 +512,9 @@
 			memset(cbe + i * GRU_HANDLE_STRIDE, 0,
 						GRU_CACHE_LINE_BYTES);
 		}
+		/* Flush CBE to hide race in context restart */
+		mb();
+		gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE);
 		cb += GRU_HANDLE_STRIDE;
 	}
 
@@ -513,6 +535,12 @@
 	cb = gseg + GRU_CB_BASE;
 	cbe = grubase + GRU_CBE_BASE;
 	length = hweight64(dsrmap) * GRU_DSR_AU_BYTES;
+
+	/* CBEs may not be coherent. Flush them from cache */
+	for_each_cbr_in_allocation_map(i, &cbrmap, scr)
+		gru_flush_cache(cbe + i * GRU_HANDLE_STRIDE);
+	mb();		/* Let the CL flush complete */
+
 	gru_prefetch_context(gseg, cb, cbe, cbrmap, length);
 
 	for_each_cbr_in_allocation_map(i, &cbrmap, scr) {
@@ -533,7 +561,8 @@
 		zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
 	cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
 
-	gru_dbg(grudev, "gts %p\n", gts);
+	gru_dbg(grudev, "gts %p, cbrmap 0x%lx, dsrmap 0x%lx\n",
+		gts, gts->ts_cbr_map, gts->ts_dsr_map);
 	lock_cch_handle(cch);
 	if (cch_interrupt_sync(cch))
 		BUG();
@@ -549,7 +578,6 @@
 
 	if (cch_deallocate(cch))
 		BUG();
-	gts->ts_force_unload = 0;	/* ts_force_unload locked by CCH lock */
 	unlock_cch_handle(cch);
 
 	gru_free_gru_context(gts);
@@ -565,9 +593,7 @@
 	struct gru_context_configuration_handle *cch;
 	int i, err, asid, ctxnum = gts->ts_ctxnum;
 
-	gru_dbg(grudev, "gts %p\n", gts);
 	cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
-
 	lock_cch_handle(cch);
 	cch->tfm_fault_bit_enable =
 	    (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
@@ -591,6 +617,7 @@
 		cch->unmap_enable = 1;
 		cch->tfm_done_bit_enable = 1;
 		cch->cb_int_enable = 1;
+		cch->tlb_int_select = 0;	/* For now, ints go to cpu 0 */
 	} else {
 		cch->unmap_enable = 0;
 		cch->tfm_done_bit_enable = 0;
@@ -616,17 +643,18 @@
 	if (cch_start(cch))
 		BUG();
 	unlock_cch_handle(cch);
+
+	gru_dbg(grudev, "gid %d, gts %p, cbrmap 0x%lx, dsrmap 0x%lx, tie %d, tis %d\n",
+		gts->ts_gru->gs_gid, gts, gts->ts_cbr_map, gts->ts_dsr_map,
+		(gts->ts_user_options == GRU_OPT_MISS_FMM_INTR), gts->ts_tlb_int_select);
 }
 
 /*
  * Update fields in an active CCH:
  * 	- retarget interrupts on local blade
  * 	- update sizeavail mask
- * 	- force a delayed context unload by clearing the CCH asids. This
- * 	  forces TLB misses for new GRU instructions. The context is unloaded
- * 	  when the next TLB miss occurs.
  */
-int gru_update_cch(struct gru_thread_state *gts, int force_unload)
+int gru_update_cch(struct gru_thread_state *gts)
 {
 	struct gru_context_configuration_handle *cch;
 	struct gru_state *gru = gts->ts_gru;
@@ -640,21 +668,13 @@
 			goto exit;
 		if (cch_interrupt(cch))
 			BUG();
-		if (!force_unload) {
-			for (i = 0; i < 8; i++)
-				cch->sizeavail[i] = gts->ts_sizeavail;
-			gts->ts_tlb_int_select = gru_cpu_fault_map_id();
-			cch->tlb_int_select = gru_cpu_fault_map_id();
-			cch->tfm_fault_bit_enable =
-			  (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
-			    || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
-		} else {
-			for (i = 0; i < 8; i++)
-				cch->asid[i] = 0;
-			cch->tfm_fault_bit_enable = 0;
-			cch->tlb_int_enable = 0;
-			gts->ts_force_unload = 1;
-		}
+		for (i = 0; i < 8; i++)
+			cch->sizeavail[i] = gts->ts_sizeavail;
+		gts->ts_tlb_int_select = gru_cpu_fault_map_id();
+		cch->tlb_int_select = gru_cpu_fault_map_id();
+		cch->tfm_fault_bit_enable =
+		  (gts->ts_user_options == GRU_OPT_MISS_FMM_POLL
+		    || gts->ts_user_options == GRU_OPT_MISS_FMM_INTR);
 		if (cch_start(cch))
 			BUG();
 		ret = 1;
@@ -679,7 +699,54 @@
 
 	gru_dbg(grudev, "retarget from %d to %d\n", gts->ts_tlb_int_select,
 		gru_cpu_fault_map_id());
-	return gru_update_cch(gts, 0);
+	return gru_update_cch(gts);
+}
+
+/*
+ * Check if a GRU context is allowed to use a specific chiplet. By default
+ * a context is assigned to any blade-local chiplet. However, users can
+ * override this.
+ * 	Returns 1 if assignment allowed, 0 otherwise
+ */
+static int gru_check_chiplet_assignment(struct gru_state *gru,
+					struct gru_thread_state *gts)
+{
+	int blade_id;
+	int chiplet_id;
+
+	blade_id = gts->ts_user_blade_id;
+	if (blade_id < 0)
+		blade_id = uv_numa_blade_id();
+
+	chiplet_id = gts->ts_user_chiplet_id;
+	return gru->gs_blade_id == blade_id &&
+		(chiplet_id < 0 || chiplet_id == gru->gs_chiplet_id);
+}
+
+/*
+ * Unload the gru context if it is not assigned to the correct blade or
+ * chiplet. Misassignment can occur if the process migrates to a different
+ * blade or if the user changes the selected blade/chiplet.
+ */
+void gru_check_context_placement(struct gru_thread_state *gts)
+{
+	struct gru_state *gru;
+
+	/*
+	 * If the current task is the context owner, verify that the
+	 * context is correctly placed. This test is skipped for non-owner
+	 * references. Pthread apps use non-owner references to the CBRs.
+	 */
+	gru = gts->ts_gru;
+	if (!gru || gts->ts_tgid_owner != current->tgid)
+		return;
+
+	if (!gru_check_chiplet_assignment(gru, gts)) {
+		STAT(check_context_unload);
+		gru_unload_context(gts, 1);
+	} else if (gru_retarget_intr(gts)) {
+		STAT(check_context_retarget_intr);
+	}
 }
 
 
@@ -712,13 +779,17 @@
 	}
 }
 
-void gru_steal_context(struct gru_thread_state *gts, int blade_id)
+void gru_steal_context(struct gru_thread_state *gts)
 {
 	struct gru_blade_state *blade;
 	struct gru_state *gru, *gru0;
 	struct gru_thread_state *ngts = NULL;
 	int ctxnum, ctxnum0, flag = 0, cbr, dsr;
+	int blade_id;
 
+	blade_id = gts->ts_user_blade_id;
+	if (blade_id < 0)
+		blade_id = uv_numa_blade_id();
 	cbr = gts->ts_cbr_au_count;
 	dsr = gts->ts_dsr_au_count;
 
@@ -729,35 +800,39 @@
 	gru = blade->bs_lru_gru;
 	if (ctxnum == 0)
 		gru = next_gru(blade, gru);
+	blade->bs_lru_gru = gru;
+	blade->bs_lru_ctxnum = ctxnum;
 	ctxnum0 = ctxnum;
 	gru0 = gru;
 	while (1) {
-		if (check_gru_resources(gru, cbr, dsr, GRU_NUM_CCH))
-			break;
-		spin_lock(&gru->gs_lock);
-		for (; ctxnum < GRU_NUM_CCH; ctxnum++) {
-			if (flag && gru == gru0 && ctxnum == ctxnum0)
+		if (gru_check_chiplet_assignment(gru, gts)) {
+			if (check_gru_resources(gru, cbr, dsr, GRU_NUM_CCH))
 				break;
-			ngts = gru->gs_gts[ctxnum];
-			/*
-			 * We are grabbing locks out of order, so trylock is
-			 * needed. GTSs are usually not locked, so the odds of
-			 * success are high. If trylock fails, try to steal a
-			 * different GSEG.
-			 */
-			if (ngts && is_gts_stealable(ngts, blade))
+			spin_lock(&gru->gs_lock);
+			for (; ctxnum < GRU_NUM_CCH; ctxnum++) {
+				if (flag && gru == gru0 && ctxnum == ctxnum0)
+					break;
+				ngts = gru->gs_gts[ctxnum];
+				/*
+			 	* We are grabbing locks out of order, so trylock is
+			 	* needed. GTSs are usually not locked, so the odds of
+			 	* success are high. If trylock fails, try to steal a
+			 	* different GSEG.
+			 	*/
+				if (ngts && is_gts_stealable(ngts, blade))
+					break;
+				ngts = NULL;
+			}
+			spin_unlock(&gru->gs_lock);
+			if (ngts || (flag && gru == gru0 && ctxnum == ctxnum0))
 				break;
-			ngts = NULL;
-			flag = 1;
 		}
-		spin_unlock(&gru->gs_lock);
-		if (ngts || (flag && gru == gru0 && ctxnum == ctxnum0))
+		if (flag && gru == gru0)
 			break;
+		flag = 1;
 		ctxnum = 0;
 		gru = next_gru(blade, gru);
 	}
-	blade->bs_lru_gru = gru;
-	blade->bs_lru_ctxnum = ctxnum;
 	spin_unlock(&blade->bs_lock);
 
 	if (ngts) {
@@ -776,19 +851,34 @@
 }
 
 /*
+ * Assign a gru context.
+ */
+static int gru_assign_context_number(struct gru_state *gru)
+{
+	int ctxnum;
+
+	ctxnum = find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
+	__set_bit(ctxnum, &gru->gs_context_map);
+	return ctxnum;
+}
+
+/*
  * Scan the GRUs on the local blade & assign a GRU context.
  */
-struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
-						int blade)
+struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts)
 {
 	struct gru_state *gru, *grux;
 	int i, max_active_contexts;
+	int blade_id = gts->ts_user_blade_id;
 
-
+	if (blade_id < 0)
+		blade_id = uv_numa_blade_id();
 again:
 	gru = NULL;
 	max_active_contexts = GRU_NUM_CCH;
-	for_each_gru_on_blade(grux, blade, i) {
+	for_each_gru_on_blade(grux, blade_id, i) {
+		if (!gru_check_chiplet_assignment(grux, gts))
+			continue;
 		if (check_gru_resources(grux, gts->ts_cbr_au_count,
 					gts->ts_dsr_au_count,
 					max_active_contexts)) {
@@ -809,12 +899,9 @@
 		reserve_gru_resources(gru, gts);
 		gts->ts_gru = gru;
 		gts->ts_blade = gru->gs_blade_id;
-		gts->ts_ctxnum =
-		    find_first_zero_bit(&gru->gs_context_map, GRU_NUM_CCH);
-		BUG_ON(gts->ts_ctxnum == GRU_NUM_CCH);
+		gts->ts_ctxnum = gru_assign_context_number(gru);
 		atomic_inc(&gts->ts_refcnt);
 		gru->gs_gts[gts->ts_ctxnum] = gts;
-		__set_bit(gts->ts_ctxnum, &gru->gs_context_map);
 		spin_unlock(&gru->gs_lock);
 
 		STAT(assign_context);
@@ -842,7 +929,6 @@
 {
 	struct gru_thread_state *gts;
 	unsigned long paddr, vaddr;
-	int blade_id;
 
 	vaddr = (unsigned long)vmf->virtual_address;
 	gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
@@ -857,28 +943,18 @@
 again:
 	mutex_lock(&gts->ts_ctxlock);
 	preempt_disable();
-	blade_id = uv_numa_blade_id();
 
-	if (gts->ts_gru) {
-		if (gts->ts_gru->gs_blade_id != blade_id) {
-			STAT(migrated_nopfn_unload);
-			gru_unload_context(gts, 1);
-		} else {
-			if (gru_retarget_intr(gts))
-				STAT(migrated_nopfn_retarget);
-		}
-	}
+	gru_check_context_placement(gts);
 
 	if (!gts->ts_gru) {
 		STAT(load_user_context);
-		if (!gru_assign_gru_context(gts, blade_id)) {
+		if (!gru_assign_gru_context(gts)) {
 			preempt_enable();
 			mutex_unlock(&gts->ts_ctxlock);
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(GRU_ASSIGN_DELAY);  /* true hack ZZZ */
-			blade_id = uv_numa_blade_id();
 			if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
-				gru_steal_context(gts, blade_id);
+				gru_steal_context(gts);
 			goto again;
 		}
 		gru_load_context(gts);
diff --git a/drivers/misc/sgi-gru/gruprocfs.c b/drivers/misc/sgi-gru/gruprocfs.c
index 3f2375c..7768b87 100644
--- a/drivers/misc/sgi-gru/gruprocfs.c
+++ b/drivers/misc/sgi-gru/gruprocfs.c
@@ -36,8 +36,7 @@
 {
 	unsigned long val = atomic_long_read(v);
 
-	if (val)
-		seq_printf(s, "%16lu %s\n", val, id);
+	seq_printf(s, "%16lu %s\n", val, id);
 }
 
 static int statistics_show(struct seq_file *s, void *p)
@@ -46,7 +45,8 @@
 	printstat(s, vdata_free);
 	printstat(s, gts_alloc);
 	printstat(s, gts_free);
-	printstat(s, vdata_double_alloc);
+	printstat(s, gms_alloc);
+	printstat(s, gms_free);
 	printstat(s, gts_double_allocate);
 	printstat(s, assign_context);
 	printstat(s, assign_context_failed);
@@ -59,28 +59,25 @@
 	printstat(s, steal_kernel_context);
 	printstat(s, steal_context_failed);
 	printstat(s, nopfn);
-	printstat(s, break_cow);
 	printstat(s, asid_new);
 	printstat(s, asid_next);
 	printstat(s, asid_wrap);
 	printstat(s, asid_reuse);
 	printstat(s, intr);
+	printstat(s, intr_cbr);
+	printstat(s, intr_tfh);
+	printstat(s, intr_spurious);
 	printstat(s, intr_mm_lock_failed);
 	printstat(s, call_os);
-	printstat(s, call_os_offnode_reference);
-	printstat(s, call_os_check_for_bug);
 	printstat(s, call_os_wait_queue);
 	printstat(s, user_flush_tlb);
 	printstat(s, user_unload_context);
 	printstat(s, user_exception);
 	printstat(s, set_context_option);
-	printstat(s, migrate_check);
-	printstat(s, migrated_retarget);
-	printstat(s, migrated_unload);
-	printstat(s, migrated_unload_delay);
-	printstat(s, migrated_nopfn_retarget);
-	printstat(s, migrated_nopfn_unload);
+	printstat(s, check_context_retarget_intr);
+	printstat(s, check_context_unload);
 	printstat(s, tlb_dropin);
+	printstat(s, tlb_preload_page);
 	printstat(s, tlb_dropin_fail_no_asid);
 	printstat(s, tlb_dropin_fail_upm);
 	printstat(s, tlb_dropin_fail_invalid);
@@ -88,16 +85,15 @@
 	printstat(s, tlb_dropin_fail_idle);
 	printstat(s, tlb_dropin_fail_fmm);
 	printstat(s, tlb_dropin_fail_no_exception);
-	printstat(s, tlb_dropin_fail_no_exception_war);
 	printstat(s, tfh_stale_on_fault);
 	printstat(s, mmu_invalidate_range);
 	printstat(s, mmu_invalidate_page);
-	printstat(s, mmu_clear_flush_young);
 	printstat(s, flush_tlb);
 	printstat(s, flush_tlb_gru);
 	printstat(s, flush_tlb_gru_tgh);
 	printstat(s, flush_tlb_gru_zero_asid);
 	printstat(s, copy_gpa);
+	printstat(s, read_gpa);
 	printstat(s, mesq_receive);
 	printstat(s, mesq_receive_none);
 	printstat(s, mesq_send);
@@ -108,7 +104,6 @@
 	printstat(s, mesq_send_qlimit_reached);
 	printstat(s, mesq_send_amo_nacked);
 	printstat(s, mesq_send_put_nacked);
-	printstat(s, mesq_qf_not_full);
 	printstat(s, mesq_qf_locked);
 	printstat(s, mesq_qf_noop_not_full);
 	printstat(s, mesq_qf_switch_head_failed);
@@ -118,6 +113,7 @@
 	printstat(s, mesq_noop_qlimit_reached);
 	printstat(s, mesq_noop_amo_nacked);
 	printstat(s, mesq_noop_put_nacked);
+	printstat(s, mesq_noop_page_overflow);
 	return 0;
 }
 
@@ -133,8 +129,10 @@
 	int op;
 	unsigned long total, count, max;
 	static char *id[] = {"cch_allocate", "cch_start", "cch_interrupt",
-		"cch_interrupt_sync", "cch_deallocate", "tgh_invalidate"};
+		"cch_interrupt_sync", "cch_deallocate", "tfh_write_only",
+		"tfh_write_restart", "tgh_invalidate"};
 
+	seq_printf(s, "%-20s%12s%12s%12s\n", "#id", "count", "aver-clks", "max-clks");
 	for (op = 0; op < mcsop_last; op++) {
 		count = atomic_long_read(&mcs_op_statistics[op].count);
 		total = atomic_long_read(&mcs_op_statistics[op].total);
@@ -154,6 +152,7 @@
 
 static int options_show(struct seq_file *s, void *p)
 {
+	seq_printf(s, "#bitmask: 1=trace, 2=statistics\n");
 	seq_printf(s, "0x%lx\n", gru_options);
 	return 0;
 }
@@ -183,16 +182,17 @@
 	const char *mode[] = { "??", "UPM", "INTR", "OS_POLL" };
 
 	if (gid == 0)
-		seq_printf(file, "#%5s%5s%6s%9s%6s%8s%8s\n", "gid", "bid",
-			   "ctx#", "pid", "cbrs", "dsbytes", "mode");
+		seq_printf(file, "#%5s%5s%6s%7s%9s%6s%8s%8s\n", "gid", "bid",
+			   "ctx#", "asid", "pid", "cbrs", "dsbytes", "mode");
 	if (gru)
 		for (i = 0; i < GRU_NUM_CCH; i++) {
 			ts = gru->gs_gts[i];
 			if (!ts)
 				continue;
-			seq_printf(file, " %5d%5d%6d%9d%6d%8d%8s\n",
+			seq_printf(file, " %5d%5d%6d%7d%9d%6d%8d%8s\n",
 				   gru->gs_gid, gru->gs_blade_id, i,
-				   ts->ts_tgid_owner,
+				   is_kernel_context(ts) ? 0 : ts->ts_gms->ms_asids[gid].mt_asid,
+				   is_kernel_context(ts) ? 0 : ts->ts_tgid_owner,
 				   ts->ts_cbr_au_count * GRU_CBR_AU_SIZE,
 				   ts->ts_cbr_au_count * GRU_DSR_AU_BYTES,
 				   mode[ts->ts_user_options &
@@ -355,7 +355,7 @@
 		for (p = proc_files; p->name; p++)
 			if (p->entry)
 				remove_proc_entry(p->name, proc_gru);
-		remove_proc_entry("gru", NULL);
+		remove_proc_entry("gru", proc_gru->parent);
 	}
 }
 
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h
index 46990bc..02a77b8 100644
--- a/drivers/misc/sgi-gru/grutables.h
+++ b/drivers/misc/sgi-gru/grutables.h
@@ -161,7 +161,7 @@
 #define GRU_MAX_GRUS		(GRU_MAX_BLADES * GRU_CHIPLETS_PER_BLADE)
 
 #define GRU_DRIVER_ID_STR	"SGI GRU Device Driver"
-#define GRU_DRIVER_VERSION_STR	"0.80"
+#define GRU_DRIVER_VERSION_STR	"0.85"
 
 /*
  * GRU statistics.
@@ -171,7 +171,8 @@
 	atomic_long_t vdata_free;
 	atomic_long_t gts_alloc;
 	atomic_long_t gts_free;
-	atomic_long_t vdata_double_alloc;
+	atomic_long_t gms_alloc;
+	atomic_long_t gms_free;
 	atomic_long_t gts_double_allocate;
 	atomic_long_t assign_context;
 	atomic_long_t assign_context_failed;
@@ -184,28 +185,25 @@
 	atomic_long_t steal_kernel_context;
 	atomic_long_t steal_context_failed;
 	atomic_long_t nopfn;
-	atomic_long_t break_cow;
 	atomic_long_t asid_new;
 	atomic_long_t asid_next;
 	atomic_long_t asid_wrap;
 	atomic_long_t asid_reuse;
 	atomic_long_t intr;
+	atomic_long_t intr_cbr;
+	atomic_long_t intr_tfh;
+	atomic_long_t intr_spurious;
 	atomic_long_t intr_mm_lock_failed;
 	atomic_long_t call_os;
-	atomic_long_t call_os_offnode_reference;
-	atomic_long_t call_os_check_for_bug;
 	atomic_long_t call_os_wait_queue;
 	atomic_long_t user_flush_tlb;
 	atomic_long_t user_unload_context;
 	atomic_long_t user_exception;
 	atomic_long_t set_context_option;
-	atomic_long_t migrate_check;
-	atomic_long_t migrated_retarget;
-	atomic_long_t migrated_unload;
-	atomic_long_t migrated_unload_delay;
-	atomic_long_t migrated_nopfn_retarget;
-	atomic_long_t migrated_nopfn_unload;
+	atomic_long_t check_context_retarget_intr;
+	atomic_long_t check_context_unload;
 	atomic_long_t tlb_dropin;
+	atomic_long_t tlb_preload_page;
 	atomic_long_t tlb_dropin_fail_no_asid;
 	atomic_long_t tlb_dropin_fail_upm;
 	atomic_long_t tlb_dropin_fail_invalid;
@@ -213,17 +211,16 @@
 	atomic_long_t tlb_dropin_fail_idle;
 	atomic_long_t tlb_dropin_fail_fmm;
 	atomic_long_t tlb_dropin_fail_no_exception;
-	atomic_long_t tlb_dropin_fail_no_exception_war;
 	atomic_long_t tfh_stale_on_fault;
 	atomic_long_t mmu_invalidate_range;
 	atomic_long_t mmu_invalidate_page;
-	atomic_long_t mmu_clear_flush_young;
 	atomic_long_t flush_tlb;
 	atomic_long_t flush_tlb_gru;
 	atomic_long_t flush_tlb_gru_tgh;
 	atomic_long_t flush_tlb_gru_zero_asid;
 
 	atomic_long_t copy_gpa;
+	atomic_long_t read_gpa;
 
 	atomic_long_t mesq_receive;
 	atomic_long_t mesq_receive_none;
@@ -235,7 +232,7 @@
 	atomic_long_t mesq_send_qlimit_reached;
 	atomic_long_t mesq_send_amo_nacked;
 	atomic_long_t mesq_send_put_nacked;
-	atomic_long_t mesq_qf_not_full;
+	atomic_long_t mesq_page_overflow;
 	atomic_long_t mesq_qf_locked;
 	atomic_long_t mesq_qf_noop_not_full;
 	atomic_long_t mesq_qf_switch_head_failed;
@@ -245,11 +242,13 @@
 	atomic_long_t mesq_noop_qlimit_reached;
 	atomic_long_t mesq_noop_amo_nacked;
 	atomic_long_t mesq_noop_put_nacked;
+	atomic_long_t mesq_noop_page_overflow;
 
 };
 
 enum mcs_op {cchop_allocate, cchop_start, cchop_interrupt, cchop_interrupt_sync,
-	cchop_deallocate, tghop_invalidate, mcsop_last};
+	cchop_deallocate, tfhop_write_only, tfhop_write_restart,
+	tghop_invalidate, mcsop_last};
 
 struct mcs_op_statistic {
 	atomic_long_t	count;
@@ -259,8 +258,8 @@
 
 extern struct mcs_op_statistic mcs_op_statistics[mcsop_last];
 
-#define OPT_DPRINT	1
-#define OPT_STATS	2
+#define OPT_DPRINT		1
+#define OPT_STATS		2
 
 
 #define IRQ_GRU			110	/* Starting IRQ number for interrupts */
@@ -283,7 +282,7 @@
 #define gru_dbg(dev, fmt, x...)						\
 	do {								\
 		if (gru_options & OPT_DPRINT)				\
-			dev_dbg(dev, "%s: " fmt, __func__, x);		\
+			printk(KERN_DEBUG "GRU:%d %s: " fmt, smp_processor_id(), __func__, x);\
 	} while (0)
 #else
 #define gru_dbg(x...)
@@ -297,13 +296,7 @@
 #define ASID_INC	8	/* number of regions */
 
 /* Generate a GRU asid value from a GRU base asid & a virtual address. */
-#if defined CONFIG_IA64
 #define VADDR_HI_BIT		64
-#elif defined CONFIG_X86_64
-#define VADDR_HI_BIT		48
-#else
-#error "Unsupported architecture"
-#endif
 #define GRUREGION(addr)		((addr) >> (VADDR_HI_BIT - 3) & 3)
 #define GRUASID(asid, addr)	((asid) + GRUREGION(addr))
 
@@ -345,6 +338,7 @@
 	long			vd_user_options;/* misc user option flags */
 	int			vd_cbr_au_count;
 	int			vd_dsr_au_count;
+	unsigned char		vd_tlb_preload_count;
 };
 
 /*
@@ -360,6 +354,7 @@
 	struct gru_state	*ts_gru;	/* GRU where the context is
 						   loaded */
 	struct gru_mm_struct	*ts_gms;	/* asid & ioproc struct */
+	unsigned char		ts_tlb_preload_count; /* TLB preload pages */
 	unsigned long		ts_cbr_map;	/* map of allocated CBRs */
 	unsigned long		ts_dsr_map;	/* map of allocated DATA
 						   resources */
@@ -368,6 +363,8 @@
 	long			ts_user_options;/* misc user option flags */
 	pid_t			ts_tgid_owner;	/* task that is using the
 						   context - for migration */
+	short			ts_user_blade_id;/* user selected blade */
+	char			ts_user_chiplet_id;/* user selected chiplet */
 	unsigned short		ts_sizeavail;	/* Pagesizes in use */
 	int			ts_tsid;	/* thread that owns the
 						   structure */
@@ -384,13 +381,11 @@
 	char			ts_blade;	/* If >= 0, migrate context if
 						   ref from diferent blade */
 	char			ts_force_cch_reload;
-	char			ts_force_unload;/* force context to be unloaded
-						   after migration */
 	char			ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each
 							  allocated CB */
 	int			ts_data_valid;	/* Indicates if ts_gdata has
 						   valid data */
-	struct gts_statistics	ustats;		/* User statistics */
+	struct gru_gseg_statistics ustats;	/* User statistics */
 	unsigned long		ts_gdata[0];	/* save area for GRU data (CB,
 						   DS, CBE) */
 };
@@ -422,6 +417,7 @@
 							   gru segments (64) */
 	unsigned short		gs_gid;			/* unique GRU number */
 	unsigned short		gs_blade_id;		/* blade of GRU */
+	unsigned char		gs_chiplet_id;		/* blade chiplet of GRU */
 	unsigned char		gs_tgh_local_shift;	/* used to pick TGH for
 							   local flush */
 	unsigned char		gs_tgh_first_remote;	/* starting TGH# for
@@ -453,6 +449,7 @@
 							   in use */
 	struct gru_thread_state	*gs_gts[GRU_NUM_CCH];	/* GTS currently using
 							   the context */
+	int			gs_irq[GRU_NUM_TFM];	/* Interrupt irqs */
 };
 
 /*
@@ -619,6 +616,15 @@
 	return !gts->ts_mm;
 }
 
+/*
+ * The following are for Nehelem-EX. A more general scheme is needed for
+ * future processors.
+ */
+#define UV_MAX_INT_CORES		8
+#define uv_cpu_socket_number(p)		((cpu_physical_id(p) >> 5) & 1)
+#define uv_cpu_ht_number(p)		(cpu_physical_id(p) & 1)
+#define uv_cpu_core_number(p)		(((cpu_physical_id(p) >> 2) & 4) |	\
+					((cpu_physical_id(p) >> 1) & 3))
 /*-----------------------------------------------------------------------------
  * Function prototypes & externs
  */
@@ -633,24 +639,26 @@
 				*vma, int tsid);
 extern struct gru_thread_state *gru_alloc_thread_state(struct vm_area_struct
 				*vma, int tsid);
-extern struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts,
-		int blade);
+extern struct gru_state *gru_assign_gru_context(struct gru_thread_state *gts);
 extern void gru_load_context(struct gru_thread_state *gts);
-extern void gru_steal_context(struct gru_thread_state *gts, int blade_id);
+extern void gru_steal_context(struct gru_thread_state *gts);
 extern void gru_unload_context(struct gru_thread_state *gts, int savestate);
-extern int gru_update_cch(struct gru_thread_state *gts, int force_unload);
+extern int gru_update_cch(struct gru_thread_state *gts);
 extern void gts_drop(struct gru_thread_state *gts);
 extern void gru_tgh_flush_init(struct gru_state *gru);
 extern int gru_kservices_init(void);
 extern void gru_kservices_exit(void);
+extern irqreturn_t gru0_intr(int irq, void *dev_id);
+extern irqreturn_t gru1_intr(int irq, void *dev_id);
+extern irqreturn_t gru_intr_mblade(int irq, void *dev_id);
 extern int gru_dump_chiplet_request(unsigned long arg);
 extern long gru_get_gseg_statistics(unsigned long arg);
-extern irqreturn_t gru_intr(int irq, void *dev_id);
 extern int gru_handle_user_call_os(unsigned long address);
 extern int gru_user_flush_tlb(unsigned long arg);
 extern int gru_user_unload_context(unsigned long arg);
 extern int gru_get_exception_detail(unsigned long arg);
 extern int gru_set_context_option(unsigned long address);
+extern void gru_check_context_placement(struct gru_thread_state *gts);
 extern int gru_cpu_fault_map_id(void);
 extern struct vm_area_struct *gru_find_vma(unsigned long vaddr);
 extern void gru_flush_all_tlb(struct gru_state *gru);
@@ -658,7 +666,8 @@
 extern void gru_proc_exit(void);
 
 extern struct gru_thread_state *gru_alloc_gts(struct vm_area_struct *vma,
-		int cbr_au_count, int dsr_au_count, int options, int tsid);
+		int cbr_au_count, int dsr_au_count,
+		unsigned char tlb_preload_count, int options, int tsid);
 extern unsigned long gru_reserve_cb_resources(struct gru_state *gru,
 		int cbr_au_count, char *cbmap);
 extern unsigned long gru_reserve_ds_resources(struct gru_state *gru,
diff --git a/drivers/misc/sgi-gru/grutlbpurge.c b/drivers/misc/sgi-gru/grutlbpurge.c
index 1d12509..240a6d3 100644
--- a/drivers/misc/sgi-gru/grutlbpurge.c
+++ b/drivers/misc/sgi-gru/grutlbpurge.c
@@ -184,8 +184,8 @@
 			STAT(flush_tlb_gru_tgh);
 			asid = GRUASID(asid, start);
 			gru_dbg(grudev,
-	"  FLUSH gruid %d, asid 0x%x, num %ld, cbmap 0x%x\n",
-				gid, asid, num, asids->mt_ctxbitmap);
+	"  FLUSH gruid %d, asid 0x%x, vaddr 0x%lx, vamask 0x%x, num %ld, cbmap 0x%x\n",
+			      gid, asid, start, grupagesize, num, asids->mt_ctxbitmap);
 			tgh = get_lock_tgh_handle(gru);
 			tgh_invalidate(tgh, start, ~0, asid, grupagesize, 0,
 				       num - 1, asids->mt_ctxbitmap);
@@ -299,6 +299,7 @@
 {
 	struct gru_mm_struct *gms;
 	struct mmu_notifier *mn;
+	int err;
 
 	mn = mmu_find_ops(current->mm, &gru_mmuops);
 	if (mn) {
@@ -307,16 +308,22 @@
 	} else {
 		gms = kzalloc(sizeof(*gms), GFP_KERNEL);
 		if (gms) {
+			STAT(gms_alloc);
 			spin_lock_init(&gms->ms_asid_lock);
 			gms->ms_notifier.ops = &gru_mmuops;
 			atomic_set(&gms->ms_refcnt, 1);
 			init_waitqueue_head(&gms->ms_wait_queue);
-			__mmu_notifier_register(&gms->ms_notifier, current->mm);
+			err = __mmu_notifier_register(&gms->ms_notifier, current->mm);
+			if (err)
+				goto error;
 		}
 	}
 	gru_dbg(grudev, "gms %p, refcnt %d\n", gms,
 		atomic_read(&gms->ms_refcnt));
 	return gms;
+error:
+	kfree(gms);
+	return ERR_PTR(err);
 }
 
 void gru_drop_mmu_notifier(struct gru_mm_struct *gms)
@@ -327,6 +334,7 @@
 		if (!gms->ms_released)
 			mmu_notifier_unregister(&gms->ms_notifier, current->mm);
 		kfree(gms);
+		STAT(gms_free);
 	}
 }
 
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index 2275126..851b2f2 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -339,6 +339,7 @@
 extern u8 xp_region_size;
 
 extern unsigned long (*xp_pa) (void *);
+extern unsigned long (*xp_socket_pa) (unsigned long);
 extern enum xp_retval (*xp_remote_memcpy) (unsigned long, const unsigned long,
 		       size_t);
 extern int (*xp_cpu_to_nasid) (int);
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 7896849..01be66d 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -44,6 +44,9 @@
 unsigned long (*xp_pa) (void *addr);
 EXPORT_SYMBOL_GPL(xp_pa);
 
+unsigned long (*xp_socket_pa) (unsigned long gpa);
+EXPORT_SYMBOL_GPL(xp_socket_pa);
+
 enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
 				    const unsigned long src_gpa, size_t len);
 EXPORT_SYMBOL_GPL(xp_remote_memcpy);
diff --git a/drivers/misc/sgi-xp/xp_sn2.c b/drivers/misc/sgi-xp/xp_sn2.c
index fb3ec9d..d8e463f 100644
--- a/drivers/misc/sgi-xp/xp_sn2.c
+++ b/drivers/misc/sgi-xp/xp_sn2.c
@@ -84,6 +84,15 @@
 }
 
 /*
+ * Convert a global physical to a socket physical address.
+ */
+static unsigned long
+xp_socket_pa_sn2(unsigned long gpa)
+{
+	return gpa;
+}
+
+/*
  * Wrapper for bte_copy().
  *
  *	dst_pa - physical address of the destination of the transfer.
@@ -162,6 +171,7 @@
 	xp_region_size = sn_region_size;
 
 	xp_pa = xp_pa_sn2;
+	xp_socket_pa = xp_socket_pa_sn2;
 	xp_remote_memcpy = xp_remote_memcpy_sn2;
 	xp_cpu_to_nasid = xp_cpu_to_nasid_sn2;
 	xp_expand_memprotect = xp_expand_memprotect_sn2;
diff --git a/drivers/misc/sgi-xp/xp_uv.c b/drivers/misc/sgi-xp/xp_uv.c
index d238576..a0d0932 100644
--- a/drivers/misc/sgi-xp/xp_uv.c
+++ b/drivers/misc/sgi-xp/xp_uv.c
@@ -32,12 +32,44 @@
 	return uv_gpa(addr);
 }
 
+/*
+ * Convert a global physical to socket physical address.
+ */
+static unsigned long
+xp_socket_pa_uv(unsigned long gpa)
+{
+	return uv_gpa_to_soc_phys_ram(gpa);
+}
+
+static enum xp_retval
+xp_remote_mmr_read(unsigned long dst_gpa, const unsigned long src_gpa,
+		   size_t len)
+{
+	int ret;
+	unsigned long *dst_va = __va(uv_gpa_to_soc_phys_ram(dst_gpa));
+
+	BUG_ON(!uv_gpa_in_mmr_space(src_gpa));
+	BUG_ON(len != 8);
+
+	ret = gru_read_gpa(dst_va, src_gpa);
+	if (ret == 0)
+		return xpSuccess;
+
+	dev_err(xp, "gru_read_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
+		"len=%ld\n", dst_gpa, src_gpa, len);
+	return xpGruCopyError;
+}
+
+
 static enum xp_retval
 xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
 		    size_t len)
 {
 	int ret;
 
+	if (uv_gpa_in_mmr_space(src_gpa))
+		return xp_remote_mmr_read(dst_gpa, src_gpa, len);
+
 	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
 	if (ret == 0)
 		return xpSuccess;
@@ -123,6 +155,7 @@
 	xp_region_size = sn_region_size;
 
 	xp_pa = xp_pa_uv;
+	xp_socket_pa = xp_socket_pa_uv;
 	xp_remote_memcpy = xp_remote_memcpy_uv;
 	xp_cpu_to_nasid = xp_cpu_to_nasid_uv;
 	xp_expand_memprotect = xp_expand_memprotect_uv;
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
index 65877bc..9a6268c 100644
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/hardirq.h>
 #include "xpc.h"
+#include <asm/uv/uv_hub.h>
 
 /* XPC is exiting flag */
 int xpc_exiting;
@@ -92,8 +93,12 @@
 			break;
 
 		/* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */
-		if (L1_CACHE_ALIGN(len) > buf_len) {
-			kfree(buf_base);
+		if (is_shub())
+			len = L1_CACHE_ALIGN(len);
+
+		if (len > buf_len) {
+			if (buf_base != NULL)
+				kfree(buf_base);
 			buf_len = L1_CACHE_ALIGN(len);
 			buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL,
 							    &buf_base);
@@ -105,7 +110,7 @@
 			}
 		}
 
-		ret = xp_remote_memcpy(xp_pa(buf), rp_pa, buf_len);
+		ret = xp_remote_memcpy(xp_pa(buf), rp_pa, len);
 		if (ret != xpSuccess) {
 			dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret);
 			break;
@@ -143,7 +148,7 @@
 		dev_err(xpc_part, "SAL failed to locate the reserved page\n");
 		return -ESRCH;
 	}
-	rp = (struct xpc_rsvd_page *)__va(rp_pa);
+	rp = (struct xpc_rsvd_page *)__va(xp_socket_pa(rp_pa));
 
 	if (rp->SAL_version < 3) {
 		/* SAL_versions < 3 had a SAL_partid defined as a u8 */
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index b5bbe59..8725d5e 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -157,22 +157,24 @@
 {
 	int ret;
 
-#if defined CONFIG_X86_64
-	ret = uv_bios_mq_watchlist_alloc(mq->mmr_blade, uv_gpa(mq->address),
-					 mq->order, &mq->mmr_offset);
-	if (ret < 0) {
-		dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
-			"ret=%d\n", ret);
-		return ret;
-	}
-#elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
-	ret = sn_mq_watchlist_alloc(mq->mmr_blade, (void *)uv_gpa(mq->address),
+#if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
+	int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
+
+	ret = sn_mq_watchlist_alloc(mmr_pnode, (void *)uv_gpa(mq->address),
 				    mq->order, &mq->mmr_offset);
 	if (ret < 0) {
 		dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n",
 			ret);
 		return -EBUSY;
 	}
+#elif defined CONFIG_X86_64
+	ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address),
+					 mq->order, &mq->mmr_offset);
+	if (ret < 0) {
+		dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
+			"ret=%d\n", ret);
+		return ret;
+	}
 #else
 	#error not a supported configuration
 #endif
@@ -185,12 +187,13 @@
 xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
 {
 	int ret;
+	int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
 
 #if defined CONFIG_X86_64
-	ret = uv_bios_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num);
+	ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
 	BUG_ON(ret != BIOS_STATUS_SUCCESS);
 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
-	ret = sn_mq_watchlist_free(mq->mmr_blade, mq->watchlist_num);
+	ret = sn_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
 	BUG_ON(ret != SALRET_OK);
 #else
 	#error not a supported configuration
@@ -204,6 +207,7 @@
 	enum xp_retval xp_ret;
 	int ret;
 	int nid;
+	int nasid;
 	int pg_order;
 	struct page *page;
 	struct xpc_gru_mq_uv *mq;
@@ -259,9 +263,11 @@
 		goto out_5;
 	}
 
+	nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu));
+
 	mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value;
 	ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size,
-				       nid, mmr_value->vector, mmr_value->dest);
+				     nasid, mmr_value->vector, mmr_value->dest);
 	if (ret != 0) {
 		dev_err(xpc_part, "gru_create_message_queue() returned "
 			"error=%d\n", ret);
@@ -946,11 +952,13 @@
 		head->first = first->next;
 		if (head->first == NULL)
 			head->last = NULL;
+
+		head->n_entries--;
+		BUG_ON(head->n_entries < 0);
+
+		first->next = NULL;
 	}
-	head->n_entries--;
-	BUG_ON(head->n_entries < 0);
 	spin_unlock_irqrestore(&head->lock, irq_flags);
-	first->next = NULL;
 	return first;
 }
 
@@ -1019,7 +1027,8 @@
 	xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
 				      XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
 
-	while (part->sn.uv.remote_act_state != XPC_P_AS_ACTIVATING) {
+	while (!((part->sn.uv.remote_act_state == XPC_P_AS_ACTIVATING) ||
+		 (part->sn.uv.remote_act_state == XPC_P_AS_ACTIVE))) {
 
 		dev_dbg(xpc_part, "waiting to make first contact with "
 			"partition %d\n", XPC_PARTID(part));
@@ -1422,7 +1431,6 @@
 	msg_slot = ch_uv->recv_msg_slots +
 	    (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
 
-	BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
 	BUG_ON(msg_slot->hdr.size != 0);
 
 	memcpy(msg_slot, msg, msg->hdr.size);
@@ -1646,8 +1654,6 @@
 			       sizeof(struct xpc_notify_mq_msghdr_uv));
 	if (ret != xpSuccess)
 		XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
-
-	msg->hdr.msg_slot_number += ch->remote_nentries;
 }
 
 static struct xpc_arch_operations xpc_arch_ops_uv = {
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index cdb845b..06b6408 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -516,7 +516,8 @@
 	 * The number of functions on the card is encoded inside
 	 * the ocr.
 	 */
-	card->sdio_funcs = funcs = (ocr & 0x70000000) >> 28;
+	funcs = (ocr & 0x70000000) >> 28;
+	card->sdio_funcs = 0;
 
 	/*
 	 * If needed, disconnect card detection pull-up resistor.
@@ -528,7 +529,7 @@
 	/*
 	 * Initialize (but don't add) all present functions.
 	 */
-	for (i = 0;i < funcs;i++) {
+	for (i = 0; i < funcs; i++, card->sdio_funcs++) {
 		err = sdio_init_func(host->card, i + 1);
 		if (err)
 			goto remove;
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index d37464e..9e060c8 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -248,12 +248,15 @@
 /*
  * Unregister a SDIO function with the driver model, and
  * (eventually) free it.
+ * This function can be called through error paths where sdio_add_func() was
+ * never executed (because a failure occurred at an earlier point).
  */
 void sdio_remove_func(struct sdio_func *func)
 {
-	if (sdio_func_present(func))
-		device_del(&func->dev);
+	if (!sdio_func_present(func))
+		return;
 
+	device_del(&func->dev);
 	put_device(&func->dev);
 }
 
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 9d405b1..ce1d288 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -44,6 +44,19 @@
 	  This is silent Kconfig symbol that is selected by the drivers that
 	  need to overwrite SDHCI IO memory accessors.
 
+config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	bool
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This option is selected by drivers running on big endian hosts
+	  and performing I/O to a SDHCI controller through a bus that
+	  implements a hardware byte swapper using a 32-bit datum.
+	  This endian mapping mode is called "data invariance" and
+	  has the effect of scrambling the addresses and formats of data
+	  accessed in sizes other than the datum size.
+
+	  This is the case for the Freescale eSDHC and Nintendo Wii SDHCI.
+
 config MMC_SDHCI_PCI
 	tristate "SDHCI support on PCI bus"
 	depends on MMC_SDHCI && PCI
@@ -75,11 +88,29 @@
 config MMC_SDHCI_OF
 	tristate "SDHCI support on OpenFirmware platforms"
 	depends on MMC_SDHCI && PPC_OF
-	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the OF support for Secure Digital Host Controller
-	  Interfaces. So far, only the Freescale eSDHC controller is known
-	  to exist on OF platforms.
+	  Interfaces.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_OF_ESDHC
+	bool "SDHCI OF support for the Freescale eSDHC controller"
+	depends on MMC_SDHCI_OF
+	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	help
+	  This selects the Freescale eSDHC controller support.
+
+	  If unsure, say N.
+
+config MMC_SDHCI_OF_HLWD
+	bool "SDHCI OF support for the Nintendo Wii SDHCI controllers"
+	depends on MMC_SDHCI_OF
+	select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+	help
+	  This selects the Secure Digital Host Controller Interface (SDHCI)
+	  found in the "Hollywood" chipset of the Nintendo Wii video game
+	  console.
 
 	  If unsure, say N.
 
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index ded4d8cd..3d253dd 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -13,7 +13,6 @@
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_RICOH_MMC)	+= ricoh_mmc.o
-obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
 obj-$(CONFIG_MMC_SDHCI_PLTFM)	+= sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
@@ -37,6 +36,11 @@
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 
+obj-$(CONFIG_MMC_SDHCI_OF)	+= sdhci-of.o
+sdhci-of-y				:= sdhci-of-core.o
+sdhci-of-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
+sdhci-of-$(CONFIG_MMC_SDHCI_OF_HLWD)	+= sdhci-of-hlwd.o
+
 ifeq ($(CONFIG_CB710_DEBUG),y)
 	CFLAGS-cb710-mmc	+= -DDEBUG
 endif
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
new file mode 100644
index 0000000..55e3313
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -0,0 +1,231 @@
+/*
+ * OpenFirmware bindings for Secure Digital Host Controller Interface.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *	    Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/mmc/host.h>
+#include <asm/machdep.h>
+#include "sdhci-of.h"
+#include "sdhci.h"
+
+#ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
+
+/*
+ * These accessors are designed for big endian hosts doing I/O to
+ * little endian controllers incorporating a 32-bit hardware byte swapper.
+ */
+
+u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg)
+{
+	return in_be32(host->ioaddr + reg);
+}
+
+u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg)
+{
+	return in_be16(host->ioaddr + (reg ^ 0x2));
+}
+
+u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg)
+{
+	return in_8(host->ioaddr + (reg ^ 0x3));
+}
+
+void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	out_be32(host->ioaddr + reg, val);
+}
+
+void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	struct sdhci_of_host *of_host = sdhci_priv(host);
+	int base = reg & ~0x3;
+	int shift = (reg & 0x2) * 8;
+
+	switch (reg) {
+	case SDHCI_TRANSFER_MODE:
+		/*
+		 * Postpone this write, we must do it together with a
+		 * command write that is down below.
+		 */
+		of_host->xfer_mode_shadow = val;
+		return;
+	case SDHCI_COMMAND:
+		sdhci_be32bs_writel(host, val << 16 | of_host->xfer_mode_shadow,
+				    SDHCI_TRANSFER_MODE);
+		return;
+	}
+	clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
+}
+
+void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	int base = reg & ~0x3;
+	int shift = (reg & 0x3) * 8;
+
+	clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
+}
+#endif /* CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER */
+
+#ifdef CONFIG_PM
+
+static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state)
+{
+	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
+
+	return mmc_suspend_host(host->mmc, state);
+}
+
+static int sdhci_of_resume(struct of_device *ofdev)
+{
+	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
+
+	return mmc_resume_host(host->mmc);
+}
+
+#else
+
+#define sdhci_of_suspend NULL
+#define sdhci_of_resume NULL
+
+#endif
+
+static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
+{
+	if (of_get_property(np, "sdhci,wp-inverted", NULL))
+		return true;
+
+	/* Old device trees don't have the wp-inverted property. */
+	return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
+}
+
+static int __devinit sdhci_of_probe(struct of_device *ofdev,
+				 const struct of_device_id *match)
+{
+	struct device_node *np = ofdev->node;
+	struct sdhci_of_data *sdhci_of_data = match->data;
+	struct sdhci_host *host;
+	struct sdhci_of_host *of_host;
+	const u32 *clk;
+	int size;
+	int ret;
+
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
+	if (IS_ERR(host))
+		return -ENOMEM;
+
+	of_host = sdhci_priv(host);
+	dev_set_drvdata(&ofdev->dev, host);
+
+	host->ioaddr = of_iomap(np, 0);
+	if (!host->ioaddr) {
+		ret = -ENOMEM;
+		goto err_addr_map;
+	}
+
+	host->irq = irq_of_parse_and_map(np, 0);
+	if (!host->irq) {
+		ret = -EINVAL;
+		goto err_no_irq;
+	}
+
+	host->hw_name = dev_name(&ofdev->dev);
+	if (sdhci_of_data) {
+		host->quirks = sdhci_of_data->quirks;
+		host->ops = &sdhci_of_data->ops;
+	}
+
+	if (of_get_property(np, "sdhci,1-bit-only", NULL))
+		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+
+	if (sdhci_of_wp_inverted(np))
+		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+
+	clk = of_get_property(np, "clock-frequency", &size);
+	if (clk && size == sizeof(*clk) && *clk)
+		of_host->clock = *clk;
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		goto err_add_host;
+
+	return 0;
+
+err_add_host:
+	irq_dispose_mapping(host->irq);
+err_no_irq:
+	iounmap(host->ioaddr);
+err_addr_map:
+	sdhci_free_host(host);
+	return ret;
+}
+
+static int __devexit sdhci_of_remove(struct of_device *ofdev)
+{
+	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
+
+	sdhci_remove_host(host, 0);
+	sdhci_free_host(host);
+	irq_dispose_mapping(host->irq);
+	iounmap(host->ioaddr);
+	return 0;
+}
+
+static const struct of_device_id sdhci_of_match[] = {
+#ifdef CONFIG_MMC_SDHCI_OF_ESDHC
+	{ .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
+	{ .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
+	{ .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
+#endif
+#ifdef CONFIG_MMC_SDHCI_OF_HLWD
+	{ .compatible = "nintendo,hollywood-sdhci", .data = &sdhci_hlwd, },
+#endif
+	{ .compatible = "generic-sdhci", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sdhci_of_match);
+
+static struct of_platform_driver sdhci_of_driver = {
+	.driver.name = "sdhci-of",
+	.match_table = sdhci_of_match,
+	.probe = sdhci_of_probe,
+	.remove = __devexit_p(sdhci_of_remove),
+	.suspend = sdhci_of_suspend,
+	.resume	= sdhci_of_resume,
+};
+
+static int __init sdhci_of_init(void)
+{
+	return of_register_platform_driver(&sdhci_of_driver);
+}
+module_init(sdhci_of_init);
+
+static void __exit sdhci_of_exit(void)
+{
+	of_unregister_platform_driver(&sdhci_of_driver);
+}
+module_exit(sdhci_of_exit);
+
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
+MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
+	      "Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
new file mode 100644
index 0000000..d5b11a1
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -0,0 +1,143 @@
+/*
+ * Freescale eSDHC controller driver.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *	    Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mmc/host.h>
+#include "sdhci-of.h"
+#include "sdhci.h"
+
+/*
+ * Ops and quirks for the Freescale eSDHC controller.
+ */
+
+#define ESDHC_DMA_SYSCTL	0x40c
+#define ESDHC_DMA_SNOOP		0x00000040
+
+#define ESDHC_SYSTEM_CONTROL	0x2c
+#define ESDHC_CLOCK_MASK	0x0000fff0
+#define ESDHC_PREDIV_SHIFT	8
+#define ESDHC_DIVIDER_SHIFT	4
+#define ESDHC_CLOCK_PEREN	0x00000004
+#define ESDHC_CLOCK_HCKEN	0x00000002
+#define ESDHC_CLOCK_IPGEN	0x00000001
+
+#define ESDHC_HOST_CONTROL_RES	0x05
+
+static u16 esdhc_readw(struct sdhci_host *host, int reg)
+{
+	u16 ret;
+
+	if (unlikely(reg == SDHCI_HOST_VERSION))
+		ret = in_be16(host->ioaddr + reg);
+	else
+		ret = sdhci_be32bs_readw(host, reg);
+	return ret;
+}
+
+static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	if (reg == SDHCI_BLOCK_SIZE) {
+		/*
+		 * Two last DMA bits are reserved, and first one is used for
+		 * non-standard blksz of 4096 bytes that we don't support
+		 * yet. So clear the DMA boundary bits.
+		 */
+		val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
+	}
+	sdhci_be32bs_writew(host, val, reg);
+}
+
+static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
+	if (reg == SDHCI_HOST_CONTROL)
+		val &= ~ESDHC_HOST_CONTROL_RES;
+	sdhci_be32bs_writeb(host, val, reg);
+}
+
+static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	int pre_div = 2;
+	int div = 1;
+
+	clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
+		  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
+
+	if (clock == 0)
+		goto out;
+
+	while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
+		pre_div *= 2;
+
+	while (host->max_clk / pre_div / div > clock && div < 16)
+		div++;
+
+	dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+		clock, host->max_clk / pre_div / div);
+
+	pre_div >>= 1;
+	div--;
+
+	setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
+		  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
+		  div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT);
+	mdelay(100);
+out:
+	host->clock = clock;
+}
+
+static int esdhc_enable_dma(struct sdhci_host *host)
+{
+	setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
+	return 0;
+}
+
+static unsigned int esdhc_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_of_host *of_host = sdhci_priv(host);
+
+	return of_host->clock;
+}
+
+static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
+{
+	struct sdhci_of_host *of_host = sdhci_priv(host);
+
+	return of_host->clock / 256 / 16;
+}
+
+struct sdhci_of_data sdhci_esdhc = {
+	.quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
+		  SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+		  SDHCI_QUIRK_NO_BUSY_IRQ |
+		  SDHCI_QUIRK_NONSTANDARD_CLOCK |
+		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+		  SDHCI_QUIRK_PIO_NEEDS_DELAY |
+		  SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
+		  SDHCI_QUIRK_NO_CARD_NO_RESET,
+	.ops = {
+		.readl = sdhci_be32bs_readl,
+		.readw = esdhc_readw,
+		.readb = sdhci_be32bs_readb,
+		.writel = sdhci_be32bs_writel,
+		.writew = esdhc_writew,
+		.writeb = esdhc_writeb,
+		.set_clock = esdhc_set_clock,
+		.enable_dma = esdhc_enable_dma,
+		.get_max_clock = esdhc_get_max_clock,
+		.get_min_clock = esdhc_get_min_clock,
+	},
+};
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c
new file mode 100644
index 0000000..35117f3
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-hlwd.c
@@ -0,0 +1,65 @@
+/*
+ * drivers/mmc/host/sdhci-of-hlwd.c
+ *
+ * Nintendo Wii Secure Digital Host Controller Interface.
+ * Copyright (C) 2009 The GameCube Linux Team
+ * Copyright (C) 2009 Albert Herranz
+ *
+ * Based on sdhci-of-esdhc.c
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *	    Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/mmc/host.h>
+#include "sdhci-of.h"
+#include "sdhci.h"
+
+/*
+ * Ops and quirks for the Nintendo Wii SDHCI controllers.
+ */
+
+/*
+ * We need a small delay after each write, or things go horribly wrong.
+ */
+#define SDHCI_HLWD_WRITE_DELAY	5 /* usecs */
+
+static void sdhci_hlwd_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	sdhci_be32bs_writel(host, val, reg);
+	udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+static void sdhci_hlwd_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	sdhci_be32bs_writew(host, val, reg);
+	udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+static void sdhci_hlwd_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	sdhci_be32bs_writeb(host, val, reg);
+	udelay(SDHCI_HLWD_WRITE_DELAY);
+}
+
+struct sdhci_of_data sdhci_hlwd = {
+	.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
+		  SDHCI_QUIRK_32BIT_DMA_SIZE,
+	.ops = {
+		.readl = sdhci_be32bs_readl,
+		.readw = sdhci_be32bs_readw,
+		.readb = sdhci_be32bs_readb,
+		.writel = sdhci_hlwd_writel,
+		.writew = sdhci_hlwd_writew,
+		.writeb = sdhci_hlwd_writeb,
+	},
+};
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c
deleted file mode 100644
index 01ab916..0000000
--- a/drivers/mmc/host/sdhci-of.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * OpenFirmware bindings for Secure Digital Host Controller Interface.
- *
- * Copyright (c) 2007 Freescale Semiconductor, Inc.
- * Copyright (c) 2009 MontaVista Software, Inc.
- *
- * Authors: Xiaobo Xie <X.Xie@freescale.com>
- *	    Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/mmc/host.h>
-#include <asm/machdep.h>
-#include "sdhci.h"
-
-struct sdhci_of_data {
-	unsigned int quirks;
-	struct sdhci_ops ops;
-};
-
-struct sdhci_of_host {
-	unsigned int clock;
-	u16 xfer_mode_shadow;
-};
-
-/*
- * Ops and quirks for the Freescale eSDHC controller.
- */
-
-#define ESDHC_DMA_SYSCTL	0x40c
-#define ESDHC_DMA_SNOOP		0x00000040
-
-#define ESDHC_SYSTEM_CONTROL	0x2c
-#define ESDHC_CLOCK_MASK	0x0000fff0
-#define ESDHC_PREDIV_SHIFT	8
-#define ESDHC_DIVIDER_SHIFT	4
-#define ESDHC_CLOCK_PEREN	0x00000004
-#define ESDHC_CLOCK_HCKEN	0x00000002
-#define ESDHC_CLOCK_IPGEN	0x00000001
-
-#define ESDHC_HOST_CONTROL_RES	0x05
-
-static u32 esdhc_readl(struct sdhci_host *host, int reg)
-{
-	return in_be32(host->ioaddr + reg);
-}
-
-static u16 esdhc_readw(struct sdhci_host *host, int reg)
-{
-	u16 ret;
-
-	if (unlikely(reg == SDHCI_HOST_VERSION))
-		ret = in_be16(host->ioaddr + reg);
-	else
-		ret = in_be16(host->ioaddr + (reg ^ 0x2));
-	return ret;
-}
-
-static u8 esdhc_readb(struct sdhci_host *host, int reg)
-{
-	return in_8(host->ioaddr + (reg ^ 0x3));
-}
-
-static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
-{
-	out_be32(host->ioaddr + reg, val);
-}
-
-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
-{
-	struct sdhci_of_host *of_host = sdhci_priv(host);
-	int base = reg & ~0x3;
-	int shift = (reg & 0x2) * 8;
-
-	switch (reg) {
-	case SDHCI_TRANSFER_MODE:
-		/*
-		 * Postpone this write, we must do it together with a
-		 * command write that is down below.
-		 */
-		of_host->xfer_mode_shadow = val;
-		return;
-	case SDHCI_COMMAND:
-		esdhc_writel(host, val << 16 | of_host->xfer_mode_shadow,
-			     SDHCI_TRANSFER_MODE);
-		return;
-	case SDHCI_BLOCK_SIZE:
-		/*
-		 * Two last DMA bits are reserved, and first one is used for
-		 * non-standard blksz of 4096 bytes that we don't support
-		 * yet. So clear the DMA boundary bits.
-		 */
-		val &= ~SDHCI_MAKE_BLKSZ(0x7, 0);
-		/* fall through */
-	}
-	clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift);
-}
-
-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
-{
-	int base = reg & ~0x3;
-	int shift = (reg & 0x3) * 8;
-
-	/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
-	if (reg == SDHCI_HOST_CONTROL)
-		val &= ~ESDHC_HOST_CONTROL_RES;
-
-	clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift);
-}
-
-static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
-{
-	int pre_div = 2;
-	int div = 1;
-
-	clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
-		  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK);
-
-	if (clock == 0)
-		goto out;
-
-	while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
-		pre_div *= 2;
-
-	while (host->max_clk / pre_div / div > clock && div < 16)
-		div++;
-
-	dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
-		clock, host->max_clk / pre_div / div);
-
-	pre_div >>= 1;
-	div--;
-
-	setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN |
-		  ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
-		  div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT);
-	mdelay(100);
-out:
-	host->clock = clock;
-}
-
-static int esdhc_enable_dma(struct sdhci_host *host)
-{
-	setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
-	return 0;
-}
-
-static unsigned int esdhc_get_max_clock(struct sdhci_host *host)
-{
-	struct sdhci_of_host *of_host = sdhci_priv(host);
-
-	return of_host->clock;
-}
-
-static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
-{
-	struct sdhci_of_host *of_host = sdhci_priv(host);
-
-	return of_host->clock / 256 / 16;
-}
-
-static struct sdhci_of_data sdhci_esdhc = {
-	.quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
-		  SDHCI_QUIRK_BROKEN_CARD_DETECTION |
-		  SDHCI_QUIRK_NO_BUSY_IRQ |
-		  SDHCI_QUIRK_NONSTANDARD_CLOCK |
-		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
-		  SDHCI_QUIRK_PIO_NEEDS_DELAY |
-		  SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET |
-		  SDHCI_QUIRK_NO_CARD_NO_RESET,
-	.ops = {
-		.readl = esdhc_readl,
-		.readw = esdhc_readw,
-		.readb = esdhc_readb,
-		.writel = esdhc_writel,
-		.writew = esdhc_writew,
-		.writeb = esdhc_writeb,
-		.set_clock = esdhc_set_clock,
-		.enable_dma = esdhc_enable_dma,
-		.get_max_clock = esdhc_get_max_clock,
-		.get_min_clock = esdhc_get_min_clock,
-	},
-};
-
-#ifdef CONFIG_PM
-
-static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	return mmc_suspend_host(host->mmc, state);
-}
-
-static int sdhci_of_resume(struct of_device *ofdev)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	return mmc_resume_host(host->mmc);
-}
-
-#else
-
-#define sdhci_of_suspend NULL
-#define sdhci_of_resume NULL
-
-#endif
-
-static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
-{
-	if (of_get_property(np, "sdhci,wp-inverted", NULL))
-		return true;
-
-	/* Old device trees don't have the wp-inverted property. */
-	return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds);
-}
-
-static int __devinit sdhci_of_probe(struct of_device *ofdev,
-				 const struct of_device_id *match)
-{
-	struct device_node *np = ofdev->node;
-	struct sdhci_of_data *sdhci_of_data = match->data;
-	struct sdhci_host *host;
-	struct sdhci_of_host *of_host;
-	const u32 *clk;
-	int size;
-	int ret;
-
-	if (!of_device_is_available(np))
-		return -ENODEV;
-
-	host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
-	if (IS_ERR(host))
-		return -ENOMEM;
-
-	of_host = sdhci_priv(host);
-	dev_set_drvdata(&ofdev->dev, host);
-
-	host->ioaddr = of_iomap(np, 0);
-	if (!host->ioaddr) {
-		ret = -ENOMEM;
-		goto err_addr_map;
-	}
-
-	host->irq = irq_of_parse_and_map(np, 0);
-	if (!host->irq) {
-		ret = -EINVAL;
-		goto err_no_irq;
-	}
-
-	host->hw_name = dev_name(&ofdev->dev);
-	if (sdhci_of_data) {
-		host->quirks = sdhci_of_data->quirks;
-		host->ops = &sdhci_of_data->ops;
-	}
-
-	if (of_get_property(np, "sdhci,1-bit-only", NULL))
-		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-
-	if (sdhci_of_wp_inverted(np))
-		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-
-	clk = of_get_property(np, "clock-frequency", &size);
-	if (clk && size == sizeof(*clk) && *clk)
-		of_host->clock = *clk;
-
-	ret = sdhci_add_host(host);
-	if (ret)
-		goto err_add_host;
-
-	return 0;
-
-err_add_host:
-	irq_dispose_mapping(host->irq);
-err_no_irq:
-	iounmap(host->ioaddr);
-err_addr_map:
-	sdhci_free_host(host);
-	return ret;
-}
-
-static int __devexit sdhci_of_remove(struct of_device *ofdev)
-{
-	struct sdhci_host *host = dev_get_drvdata(&ofdev->dev);
-
-	sdhci_remove_host(host, 0);
-	sdhci_free_host(host);
-	irq_dispose_mapping(host->irq);
-	iounmap(host->ioaddr);
-	return 0;
-}
-
-static const struct of_device_id sdhci_of_match[] = {
-	{ .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, },
-	{ .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, },
-	{ .compatible = "fsl,esdhc", .data = &sdhci_esdhc, },
-	{ .compatible = "generic-sdhci", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, sdhci_of_match);
-
-static struct of_platform_driver sdhci_of_driver = {
-	.driver.name = "sdhci-of",
-	.match_table = sdhci_of_match,
-	.probe = sdhci_of_probe,
-	.remove = __devexit_p(sdhci_of_remove),
-	.suspend = sdhci_of_suspend,
-	.resume	= sdhci_of_resume,
-};
-
-static int __init sdhci_of_init(void)
-{
-	return of_register_platform_driver(&sdhci_of_driver);
-}
-module_init(sdhci_of_init);
-
-static void __exit sdhci_of_exit(void)
-{
-	of_unregister_platform_driver(&sdhci_of_driver);
-}
-module_exit(sdhci_of_exit);
-
-MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
-MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
-	      "Anton Vorontsov <avorontsov@ru.mvista.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/sdhci-of.h b/drivers/mmc/host/sdhci-of.h
new file mode 100644
index 0000000..ad09ad9
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of.h
@@ -0,0 +1,42 @@
+/*
+ * OpenFirmware bindings for Secure Digital Host Controller Interface.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2009 MontaVista Software, Inc.
+ *
+ * Authors: Xiaobo Xie <X.Xie@freescale.com>
+ *	    Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef __SDHCI_OF_H
+#define __SDHCI_OF_H
+
+#include <linux/types.h>
+#include "sdhci.h"
+
+struct sdhci_of_data {
+	unsigned int quirks;
+	struct sdhci_ops ops;
+};
+
+struct sdhci_of_host {
+	unsigned int clock;
+	u16 xfer_mode_shadow;
+};
+
+extern u32 sdhci_be32bs_readl(struct sdhci_host *host, int reg);
+extern u16 sdhci_be32bs_readw(struct sdhci_host *host, int reg);
+extern u8 sdhci_be32bs_readb(struct sdhci_host *host, int reg);
+extern void sdhci_be32bs_writel(struct sdhci_host *host, u32 val, int reg);
+extern void sdhci_be32bs_writew(struct sdhci_host *host, u16 val, int reg);
+extern void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg);
+
+extern struct sdhci_of_data sdhci_esdhc;
+extern struct sdhci_of_data sdhci_hlwd;
+
+#endif /* __SDHCI_OF_H */
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index ce5f1d7..842f46f 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -8,6 +8,8 @@
  * the Free Software Foundation; either version 2 of the License, or (at
  * your option) any later version.
  */
+#ifndef __SDHCI_H
+#define __SDHCI_H
 
 #include <linux/scatterlist.h>
 #include <linux/compiler.h>
@@ -408,3 +410,5 @@
 extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
 extern int sdhci_resume_host(struct sdhci_host *host);
 #endif
+
+#endif /* __SDHCI_H */
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index e7563a9..5fbf29e 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -43,15 +43,17 @@
 // debugging, turns off buffer write mode if set to 1
 #define FORCE_WORD_WRITE 0
 
-#define MANUFACTURER_INTEL	0x0089
+/* Intel chips */
 #define I82802AB	0x00ad
 #define I82802AC	0x00ac
 #define PF38F4476	0x881c
-#define MANUFACTURER_ST         0x0020
+/* STMicroelectronics chips */
 #define M50LPW080       0x002F
 #define M50FLW080A	0x0080
 #define M50FLW080B	0x0081
+/* Atmel chips */
 #define AT49BV640D	0x02de
+#define AT49BV640DT	0x02db
 
 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@ -199,6 +201,16 @@
 	cfi->cfiq->BufWriteTimeoutMax = 0;
 }
 
+static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
+
+	cfip->FeatureSupport |= (1 << 5);
+	mtd->flags |= MTD_POWERUP_LOCK;
+}
+
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
 static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
@@ -283,6 +295,8 @@
 
 static struct cfi_fixup cfi_fixup_table[] = {
 	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
+	{ CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock, NULL },
+	{ CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock, NULL },
 #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
 #endif
@@ -294,16 +308,16 @@
 #endif
 	{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
 	{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
-	{ MANUFACTURER_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
+	{ CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
 	{ 0, 0, NULL, NULL }
 };
 
 static struct cfi_fixup jedec_fixup_table[] = {
-	{ MANUFACTURER_INTEL, I82802AB,   fixup_use_fwh_lock, NULL, },
-	{ MANUFACTURER_INTEL, I82802AC,   fixup_use_fwh_lock, NULL, },
-	{ MANUFACTURER_ST,    M50LPW080,  fixup_use_fwh_lock, NULL, },
-	{ MANUFACTURER_ST,    M50FLW080A, fixup_use_fwh_lock, NULL, },
-	{ MANUFACTURER_ST,    M50FLW080B, fixup_use_fwh_lock, NULL, },
+	{ CFI_MFR_INTEL, I82802AB,   fixup_use_fwh_lock, NULL, },
+	{ CFI_MFR_INTEL, I82802AC,   fixup_use_fwh_lock, NULL, },
+	{ CFI_MFR_ST,    M50LPW080,  fixup_use_fwh_lock, NULL, },
+	{ CFI_MFR_ST,    M50FLW080A, fixup_use_fwh_lock, NULL, },
+	{ CFI_MFR_ST,    M50FLW080B, fixup_use_fwh_lock, NULL, },
 	{ 0, 0, NULL, NULL }
 };
 static struct cfi_fixup fixup_table[] = {
@@ -319,7 +333,7 @@
 static void cfi_fixup_major_minor(struct cfi_private *cfi,
 						struct cfi_pri_intelext *extp)
 {
-	if (cfi->mfr == MANUFACTURER_INTEL &&
+	if (cfi->mfr == CFI_MFR_INTEL &&
 			cfi->id == PF38F4476 && extp->MinorVersion == '3')
 		extp->MinorVersion = '1';
 }
@@ -2235,7 +2249,7 @@
 
 	/* Some chips have OTP located in the _top_ partition only.
 	   For example: Intel 28F256L18T (T means top-parameter device) */
-	if (cfi->mfr == MANUFACTURER_INTEL) {
+	if (cfi->mfr == CFI_MFR_INTEL) {
 		switch (cfi->id) {
 		case 0x880b:
 		case 0x880c:
@@ -2564,6 +2578,7 @@
 		if (!ret) {
 			map_write(map, CMD(0xff), chip->start);
 			chip->state = FL_SHUTDOWN;
+			put_chip(map, chip, chip->start);
 		}
 		spin_unlock(chip->mutex);
 	}
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 94bb61e..f3600e8 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -490,10 +490,6 @@
 	}
 #endif
 
-	/* FIXME: erase-suspend-program is broken.  See
-	   http://lists.infradead.org/pipermail/linux-mtd/2003-December/009001.html */
-	printk(KERN_NOTICE "cfi_cmdset_0002: Disabling erase-suspend-program due to code brokenness.\n");
-
 	__module_get(THIS_MODULE);
 	return mtd;
 
@@ -573,7 +569,6 @@
 
 			if (time_after(jiffies, timeo)) {
 				printk(KERN_ERR "Waiting for chip to be ready timed out.\n");
-				spin_unlock(chip->mutex);
 				return -EIO;
 			}
 			spin_unlock(chip->mutex);
@@ -589,15 +584,9 @@
 		return 0;
 
 	case FL_ERASING:
-		if (mode == FL_WRITING) /* FIXME: Erase-suspend-program appears broken. */
-			goto sleep;
-
-		if (!(   mode == FL_READY
-		      || mode == FL_POINT
-		      || !cfip
-		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))
-		      || (mode == FL_WRITING && (cfip->EraseSuspend & 0x1)
-		    )))
+		if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
+		    !(mode == FL_READY || mode == FL_POINT ||
+		    (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
 			goto sleep;
 
 		/* We could check to see if we're trying to access the sector
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index c5a84fd..ca584d0 100755
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -71,6 +71,13 @@
 	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
 	if (cfi_qry_present(map, base, cfi))
 		return 1;
+	/* some old SST chips, e.g. 39VF160x/39VF320x */
+	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
+	if (cfi_qry_present(map, base, cfi))
+		return 1;
 	/* QRY not found */
 	return 0;
 }
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index 736a3be..1bec5e1 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -142,8 +142,8 @@
 
 /* ST - www.st.com */
 #define M29F800AB	0x0058
-#define M29W800DT	0x00D7
-#define M29W800DB	0x005B
+#define M29W800DT	0x22D7
+#define M29W800DB	0x225B
 #define M29W400DT	0x00EE
 #define M29W400DB	0x00EF
 #define M29W160DT	0x22C4
@@ -1575,7 +1575,7 @@
 		.dev_id		= M29W800DT,
 		.name		= "ST M29W800DT",
 		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-		.uaddr		= MTD_UADDR_0x5555_0x2AAA,	/* ???? */
+		.uaddr		= MTD_UADDR_0x0AAA_0x0555,
 		.dev_size	= SIZE_1MiB,
 		.cmd_set	= P_ID_AMD_STD,
 		.nr_regions	= 4,
@@ -1590,7 +1590,7 @@
 		.dev_id		= M29W800DB,
 		.name		= "ST M29W800DB",
 		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-		.uaddr		= MTD_UADDR_0x5555_0x2AAA,	/* ???? */
+		.uaddr		= MTD_UADDR_0x0AAA_0x0555,
 		.dev_size	= SIZE_1MiB,
 		.cmd_set	= P_ID_AMD_STD,
 		.nr_regions	= 4,
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 4c19269..f3f4768 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -22,6 +22,7 @@
 #include <linux/mutex.h>
 #include <linux/math64.h>
 #include <linux/sched.h>
+#include <linux/mod_devicetable.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -29,9 +30,6 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 
-
-#define FLASH_PAGESIZE		256
-
 /* Flash opcodes. */
 #define	OPCODE_WREN		0x06	/* Write enable */
 #define	OPCODE_RDSR		0x05	/* Read status register */
@@ -61,7 +59,7 @@
 
 /* Define max times to check status register before we give up. */
 #define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
-#define	CMD_SIZE		4
+#define	MAX_CMD_SIZE		4
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define OPCODE_READ 	OPCODE_FAST_READ
@@ -78,8 +76,10 @@
 	struct mutex		lock;
 	struct mtd_info		mtd;
 	unsigned		partitioned:1;
+	u16			page_size;
+	u16			addr_width;
 	u8			erase_opcode;
-	u8			command[CMD_SIZE + FAST_READ_DUMMY_BYTE];
+	u8			*command;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -198,6 +198,19 @@
 	return 0;
 }
 
+static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
+{
+	/* opcode is in cmd[0] */
+	cmd[1] = addr >> (flash->addr_width * 8 -  8);
+	cmd[2] = addr >> (flash->addr_width * 8 - 16);
+	cmd[3] = addr >> (flash->addr_width * 8 - 24);
+}
+
+static int m25p_cmdsz(struct m25p *flash)
+{
+	return 1 + flash->addr_width;
+}
+
 /*
  * Erase one sector of flash memory at offset ``offset'' which is any
  * address within the sector which should be erased.
@@ -219,11 +232,9 @@
 
 	/* Set up command buffer. */
 	flash->command[0] = flash->erase_opcode;
-	flash->command[1] = offset >> 16;
-	flash->command[2] = offset >> 8;
-	flash->command[3] = offset;
+	m25p_addr2cmd(flash, offset, flash->command);
 
-	spi_write(flash->spi, flash->command, CMD_SIZE);
+	spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
 
 	return 0;
 }
@@ -325,7 +336,7 @@
 	 * Should add 1 byte DUMMY_BYTE.
 	 */
 	t[0].tx_buf = flash->command;
-	t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE;
+	t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
 	spi_message_add_tail(&t[0], &m);
 
 	t[1].rx_buf = buf;
@@ -352,13 +363,11 @@
 
 	/* Set up the write data buffer. */
 	flash->command[0] = OPCODE_READ;
-	flash->command[1] = from >> 16;
-	flash->command[2] = from >> 8;
-	flash->command[3] = from;
+	m25p_addr2cmd(flash, from, flash->command);
 
 	spi_sync(flash->spi, &m);
 
-	*retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE;
+	*retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
 
 	mutex_unlock(&flash->lock);
 
@@ -396,7 +405,7 @@
 	memset(t, 0, (sizeof t));
 
 	t[0].tx_buf = flash->command;
-	t[0].len = CMD_SIZE;
+	t[0].len = m25p_cmdsz(flash);
 	spi_message_add_tail(&t[0], &m);
 
 	t[1].tx_buf = buf;
@@ -414,41 +423,36 @@
 
 	/* Set up the opcode in the write buffer. */
 	flash->command[0] = OPCODE_PP;
-	flash->command[1] = to >> 16;
-	flash->command[2] = to >> 8;
-	flash->command[3] = to;
+	m25p_addr2cmd(flash, to, flash->command);
 
-	/* what page do we start with? */
-	page_offset = to % FLASH_PAGESIZE;
+	page_offset = to & (flash->page_size - 1);
 
 	/* do all the bytes fit onto one page? */
-	if (page_offset + len <= FLASH_PAGESIZE) {
+	if (page_offset + len <= flash->page_size) {
 		t[1].len = len;
 
 		spi_sync(flash->spi, &m);
 
-		*retlen = m.actual_length - CMD_SIZE;
+		*retlen = m.actual_length - m25p_cmdsz(flash);
 	} else {
 		u32 i;
 
 		/* the size of data remaining on the first page */
-		page_size = FLASH_PAGESIZE - page_offset;
+		page_size = flash->page_size - page_offset;
 
 		t[1].len = page_size;
 		spi_sync(flash->spi, &m);
 
-		*retlen = m.actual_length - CMD_SIZE;
+		*retlen = m.actual_length - m25p_cmdsz(flash);
 
-		/* write everything in PAGESIZE chunks */
+		/* write everything in flash->page_size chunks */
 		for (i = page_size; i < len; i += page_size) {
 			page_size = len - i;
-			if (page_size > FLASH_PAGESIZE)
-				page_size = FLASH_PAGESIZE;
+			if (page_size > flash->page_size)
+				page_size = flash->page_size;
 
 			/* write the next page to flash */
-			flash->command[1] = (to + i) >> 16;
-			flash->command[2] = (to + i) >> 8;
-			flash->command[3] = (to + i);
+			m25p_addr2cmd(flash, to + i, flash->command);
 
 			t[1].tx_buf = buf + i;
 			t[1].len = page_size;
@@ -460,7 +464,7 @@
 			spi_sync(flash->spi, &m);
 
 			if (retlen)
-				*retlen += m.actual_length - CMD_SIZE;
+				*retlen += m.actual_length - m25p_cmdsz(flash);
 		}
 	}
 
@@ -492,7 +496,7 @@
 	memset(t, 0, (sizeof t));
 
 	t[0].tx_buf = flash->command;
-	t[0].len = CMD_SIZE;
+	t[0].len = m25p_cmdsz(flash);
 	spi_message_add_tail(&t[0], &m);
 
 	t[1].tx_buf = buf;
@@ -511,9 +515,7 @@
 	/* Start write from odd address. */
 	if (actual) {
 		flash->command[0] = OPCODE_BP;
-		flash->command[1] = to >> 16;
-		flash->command[2] = to >> 8;
-		flash->command[3] = to;
+		m25p_addr2cmd(flash, to, flash->command);
 
 		/* write one byte. */
 		t[1].len = 1;
@@ -521,17 +523,15 @@
 		ret = wait_till_ready(flash);
 		if (ret)
 			goto time_out;
-		*retlen += m.actual_length - CMD_SIZE;
+		*retlen += m.actual_length - m25p_cmdsz(flash);
 	}
 	to += actual;
 
 	flash->command[0] = OPCODE_AAI_WP;
-	flash->command[1] = to >> 16;
-	flash->command[2] = to >> 8;
-	flash->command[3] = to;
+	m25p_addr2cmd(flash, to, flash->command);
 
 	/* Write out most of the data here. */
-	cmd_sz = CMD_SIZE;
+	cmd_sz = m25p_cmdsz(flash);
 	for (; actual < len - 1; actual += 2) {
 		t[0].len = cmd_sz;
 		/* write two bytes. */
@@ -555,10 +555,8 @@
 	if (actual != len) {
 		write_enable(flash);
 		flash->command[0] = OPCODE_BP;
-		flash->command[1] = to >> 16;
-		flash->command[2] = to >> 8;
-		flash->command[3] = to;
-		t[0].len = CMD_SIZE;
+		m25p_addr2cmd(flash, to, flash->command);
+		t[0].len = m25p_cmdsz(flash);
 		t[1].len = 1;
 		t[1].tx_buf = buf + actual;
 
@@ -566,7 +564,7 @@
 		ret = wait_till_ready(flash);
 		if (ret)
 			goto time_out;
-		*retlen += m.actual_length - CMD_SIZE;
+		*retlen += m.actual_length - m25p_cmdsz(flash);
 		write_disable(flash);
 	}
 
@@ -582,8 +580,6 @@
  */
 
 struct flash_info {
-	char		*name;
-
 	/* JEDEC id zero means "no ID" (most older chips); otherwise it has
 	 * a high byte of zero plus three data bytes: the manufacturer id,
 	 * then a two byte device id.
@@ -597,87 +593,119 @@
 	unsigned	sector_size;
 	u16		n_sectors;
 
+	u16		page_size;
+	u16		addr_width;
+
 	u16		flags;
 #define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
+#define	M25P_NO_ERASE	0x02		/* No erase command needed */
 };
 
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
+	((kernel_ulong_t)&(struct flash_info) {				\
+		.jedec_id = (_jedec_id),				\
+		.ext_id = (_ext_id),					\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.addr_width = 3,					\
+		.flags = (_flags),					\
+	})
+
+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width)	\
+	((kernel_ulong_t)&(struct flash_info) {				\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = (_page_size),				\
+		.addr_width = (_addr_width),				\
+		.flags = M25P_NO_ERASE,					\
+	})
 
 /* NOTE: double check command sets and memory organization when you add
  * more flash chips.  This current list focusses on newer chips, which
  * have been converging on command sets which including JEDEC ID.
  */
-static struct flash_info __devinitdata m25p_data [] = {
-
+static const struct spi_device_id m25p_ids[] = {
 	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
-	{ "at25fs010",  0x1f6601, 0, 32 * 1024, 4, SECT_4K, },
-	{ "at25fs040",  0x1f6604, 0, 64 * 1024, 8, SECT_4K, },
+	{ "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, SECT_4K) },
+	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 
-	{ "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, },
-	{ "at25df641",  0x1f4800, 0, 64 * 1024, 128, SECT_4K, },
+	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
+	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
 
-	{ "at26f004",   0x1f0400, 0, 64 * 1024, 8, SECT_4K, },
-	{ "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, },
-	{ "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
-	{ "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
+	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
+	{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
+	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
+	{ "at26df321",  INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
 
 	/* Macronix */
-	{ "mx25l3205d", 0xc22016, 0, 64 * 1024, 64, },
-	{ "mx25l6405d", 0xc22017, 0, 64 * 1024, 128, },
-	{ "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, },
-	{ "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, },
+	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
+	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
+	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
+	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
+	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
 
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
 	 */
-	{ "s25sl004a", 0x010212, 0, 64 * 1024, 8, },
-	{ "s25sl008a", 0x010213, 0, 64 * 1024, 16, },
-	{ "s25sl016a", 0x010214, 0, 64 * 1024, 32, },
-	{ "s25sl032a", 0x010215, 0, 64 * 1024, 64, },
-	{ "s25sl064a", 0x010216, 0, 64 * 1024, 128, },
-	{ "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, },
-	{ "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, },
-	{ "s25fl129p0", 0x012018, 0x4d00, 256 * 1024, 64, },
-	{ "s25fl129p1", 0x012018, 0x4d01, 64 * 1024, 256, },
+	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
+	{ "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, 0) },
+	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
+	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
+	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
+	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
+	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
+	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 0) },
+	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 0) },
 
 	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
-	{ "sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K, },
-	{ "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, },
-	{ "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, },
-	{ "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, },
-	{ "sst25wf512",  0xbf2501, 0, 64 * 1024, 1, SECT_4K, },
-	{ "sst25wf010",  0xbf2502, 0, 64 * 1024, 2, SECT_4K, },
-	{ "sst25wf020",  0xbf2503, 0, 64 * 1024, 4, SECT_4K, },
-	{ "sst25wf040",  0xbf2504, 0, 64 * 1024, 8, SECT_4K, },
+	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K) },
+	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) },
+	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) },
+	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) },
+	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1, SECT_4K) },
+	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2, SECT_4K) },
+	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4, SECT_4K) },
+	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8, SECT_4K) },
 
 	/* ST Microelectronics -- newer production may have feature updates */
-	{ "m25p05",  0x202010,  0, 32 * 1024, 2, },
-	{ "m25p10",  0x202011,  0, 32 * 1024, 4, },
-	{ "m25p20",  0x202012,  0, 64 * 1024, 4, },
-	{ "m25p40",  0x202013,  0, 64 * 1024, 8, },
-	{ "m25p80",         0,  0, 64 * 1024, 16, },
-	{ "m25p16",  0x202015,  0, 64 * 1024, 32, },
-	{ "m25p32",  0x202016,  0, 64 * 1024, 64, },
-	{ "m25p64",  0x202017,  0, 64 * 1024, 128, },
-	{ "m25p128", 0x202018, 0, 256 * 1024, 64, },
+	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
+	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
+	{ "m25p20",  INFO(0x202012,  0,  64 * 1024,   4, 0) },
+	{ "m25p40",  INFO(0x202013,  0,  64 * 1024,   8, 0) },
+	{ "m25p80",  INFO(0x202014,  0,  64 * 1024,  16, 0) },
+	{ "m25p16",  INFO(0x202015,  0,  64 * 1024,  32, 0) },
+	{ "m25p32",  INFO(0x202016,  0,  64 * 1024,  64, 0) },
+	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
+	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
 
-	{ "m45pe10", 0x204011,  0, 64 * 1024, 2, },
-	{ "m45pe80", 0x204014,  0, 64 * 1024, 16, },
-	{ "m45pe16", 0x204015,  0, 64 * 1024, 32, },
+	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
+	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
+	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
 
-	{ "m25pe80", 0x208014,  0, 64 * 1024, 16, },
-	{ "m25pe16", 0x208015,  0, 64 * 1024, 32, SECT_4K, },
+	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
+	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
 	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
-	{ "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, },
-	{ "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, },
-	{ "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, },
-	{ "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, },
-	{ "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, },
-	{ "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, },
-	{ "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, },
-};
+	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
+	{ "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
+	{ "w25x40", INFO(0xef3013, 0, 64 * 1024,  8,  SECT_4K) },
+	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
+	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
+	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 
-static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
+	/* Catalyst / On Semiconductor -- non-JEDEC */
+	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1) },
+	{ "cat25c03", CAT25_INFO(  32, 8, 16, 2) },
+	{ "cat25c09", CAT25_INFO( 128, 8, 32, 2) },
+	{ "cat25c17", CAT25_INFO( 256, 8, 32, 2) },
+	{ "cat25128", CAT25_INFO(2048, 8, 64, 2) },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, m25p_ids);
+
+static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 {
 	int			tmp;
 	u8			code = OPCODE_RDID;
@@ -702,18 +730,24 @@
 	jedec = jedec << 8;
 	jedec |= id[2];
 
+	/*
+	 * Some chips (like Numonyx M25P80) have JEDEC and non-JEDEC variants,
+	 * which depend on technology process. Officially RDID command doesn't
+	 * exist for non-JEDEC chips, but for compatibility they return ID 0.
+	 */
+	if (jedec == 0)
+		return NULL;
+
 	ext_jedec = id[3] << 8 | id[4];
 
-	for (tmp = 0, info = m25p_data;
-			tmp < ARRAY_SIZE(m25p_data);
-			tmp++, info++) {
+	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
+		info = (void *)m25p_ids[tmp].driver_data;
 		if (info->jedec_id == jedec) {
 			if (info->ext_id != 0 && info->ext_id != ext_jedec)
 				continue;
-			return info;
+			return &m25p_ids[tmp];
 		}
 	}
-	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
 	return NULL;
 }
 
@@ -725,6 +759,7 @@
  */
 static int __devinit m25p_probe(struct spi_device *spi)
 {
+	const struct spi_device_id	*id = spi_get_device_id(spi);
 	struct flash_platform_data	*data;
 	struct m25p			*flash;
 	struct flash_info		*info;
@@ -737,50 +772,65 @@
 	 */
 	data = spi->dev.platform_data;
 	if (data && data->type) {
-		for (i = 0, info = m25p_data;
-				i < ARRAY_SIZE(m25p_data);
-				i++, info++) {
-			if (strcmp(data->type, info->name) == 0)
-				break;
+		const struct spi_device_id *plat_id;
+
+		for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
+			plat_id = &m25p_ids[i];
+			if (strcmp(data->type, plat_id->name))
+				continue;
+			break;
 		}
 
-		/* unrecognized chip? */
-		if (i == ARRAY_SIZE(m25p_data)) {
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
-					dev_name(&spi->dev), data->type);
-			info = NULL;
+		if (plat_id)
+			id = plat_id;
+		else
+			dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
+	}
 
-		/* recognized; is that chip really what's there? */
-		} else if (info->jedec_id) {
-			struct flash_info	*chip = jedec_probe(spi);
+	info = (void *)id->driver_data;
 
-			if (!chip || chip != info) {
-				dev_warn(&spi->dev, "found %s, expected %s\n",
-						chip ? chip->name : "UNKNOWN",
-						info->name);
-				info = NULL;
-			}
+	if (info->jedec_id) {
+		const struct spi_device_id *jid;
+
+		jid = jedec_probe(spi);
+		if (!jid) {
+			dev_info(&spi->dev, "non-JEDEC variant of %s\n",
+				 id->name);
+		} else if (jid != id) {
+			/*
+			 * JEDEC knows better, so overwrite platform ID. We
+			 * can't trust partitions any longer, but we'll let
+			 * mtd apply them anyway, since some partitions may be
+			 * marked read-only, and we don't want to lose that
+			 * information, even if it's not 100% accurate.
+			 */
+			dev_warn(&spi->dev, "found %s, expected %s\n",
+				 jid->name, id->name);
+			id = jid;
+			info = (void *)jid->driver_data;
 		}
-	} else
-		info = jedec_probe(spi);
-
-	if (!info)
-		return -ENODEV;
+	}
 
 	flash = kzalloc(sizeof *flash, GFP_KERNEL);
 	if (!flash)
 		return -ENOMEM;
+	flash->command = kmalloc(MAX_CMD_SIZE + FAST_READ_DUMMY_BYTE, GFP_KERNEL);
+	if (!flash->command) {
+		kfree(flash);
+		return -ENOMEM;
+	}
 
 	flash->spi = spi;
 	mutex_init(&flash->lock);
 	dev_set_drvdata(&spi->dev, flash);
 
 	/*
-	 * Atmel serial flash tend to power up
-	 * with the software protection bits set
+	 * Atmel and SST serial flash tend to power
+	 * up with the software protection bits set
 	 */
 
-	if (info->jedec_id >> 16 == 0x1f) {
+	if (info->jedec_id >> 16 == 0x1f ||
+	    info->jedec_id >> 16 == 0xbf) {
 		write_enable(flash);
 		write_sr(flash, 0);
 	}
@@ -812,9 +862,14 @@
 		flash->mtd.erasesize = info->sector_size;
 	}
 
-	flash->mtd.dev.parent = &spi->dev;
+	if (info->flags & M25P_NO_ERASE)
+		flash->mtd.flags |= MTD_NO_ERASE;
 
-	dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
+	flash->mtd.dev.parent = &spi->dev;
+	flash->page_size = info->page_size;
+	flash->addr_width = info->addr_width;
+
+	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)flash->mtd.size >> 10);
 
 	DEBUG(MTD_DEBUG_LEVEL2,
@@ -888,8 +943,10 @@
 		status = del_mtd_partitions(&flash->mtd);
 	else
 		status = del_mtd_device(&flash->mtd);
-	if (status == 0)
+	if (status == 0) {
+		kfree(flash->command);
 		kfree(flash);
+	}
 	return 0;
 }
 
@@ -900,6 +957,7 @@
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
 	},
+	.id_table	= m25p_ids,
 	.probe	= m25p_probe,
 	.remove	= __devexit_p(m25p_remove),
 
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 93e3627..1981740 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -636,6 +636,7 @@
 	struct mtd_info			*device;
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
+	int				err = 0;
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
@@ -693,13 +694,23 @@
 
 		if (nr_parts > 0) {
 			priv->partitioned = 1;
-			return add_mtd_partitions(device, parts, nr_parts);
+			err = add_mtd_partitions(device, parts, nr_parts);
+			goto out;
 		}
 	} else if (pdata && pdata->nr_parts)
 		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
 				pdata->nr_parts, device->name);
 
-	return add_mtd_device(device) == 1 ? -ENODEV : 0;
+	if (add_mtd_device(device) == 1)
+		err = -ENODEV;
+
+out:
+	if (!err)
+		return 0;
+
+	dev_set_drvdata(&spi->dev, NULL);
+	kfree(priv);
+	return err;
 }
 
 static inline int __devinit
@@ -932,8 +943,10 @@
 		status = del_mtd_partitions(&flash->mtd);
 	else
 		status = del_mtd_device(&flash->mtd);
-	if (status == 0)
+	if (status == 0) {
+		dev_set_drvdata(&spi->dev, NULL);
 		kfree(flash);
+	}
 	return status;
 }
 
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 847e214a..4c364d4 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -359,12 +359,6 @@
 	  the SA1100 and SA1110, including the Assabet and the Compaq iPAQ.
 	  If you have such a board, say 'Y'.
 
-config MTD_IPAQ
-	tristate "CFI Flash device mapped on Compaq/HP iPAQ"
-	depends on IPAQ_HANDHELD && MTD_CFI
-	help
-	  This provides a driver for the on-board flash of the iPAQ.
-
 config MTD_DC21285
 	tristate "CFI Flash device mapped on DC21285 Footbridge"
 	depends on MTD_CFI && ARCH_FOOTBRIDGE && MTD_COMPLEX_MAPPINGS
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index ae2f6db..ce31521 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -24,12 +24,12 @@
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
+obj-$(CONFIG_MTD_PISMO)		+= pismo.o
 obj-$(CONFIG_MTD_PMC_MSP_EVM)   += pmcmsp-flash.o
 obj-$(CONFIG_MTD_PCMCIA)	+= pcmciamtd.o
 obj-$(CONFIG_MTD_RPXLITE)	+= rpxlite.o
 obj-$(CONFIG_MTD_TQM8XXL)	+= tqm8xxl.o
 obj-$(CONFIG_MTD_SA1100)	+= sa1100-flash.o
-obj-$(CONFIG_MTD_IPAQ)		+= ipaq-flash.o
 obj-$(CONFIG_MTD_SBC_GXX)	+= sbc_gxx.o
 obj-$(CONFIG_MTD_SC520CDP)	+= sc520cdp.o
 obj-$(CONFIG_MTD_NETSC520)	+= netsc520.o
diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c
deleted file mode 100644
index 76708e7..0000000
--- a/drivers/mtd/maps/ipaq-flash.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Flash memory access on iPAQ Handhelds (either SA1100 or PXA250 based)
- *
- * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
- * (C) 2002 Hewlett-Packard Company <jamey.hicks@hp.com>
- * (C) 2003 Christian Pellegrin <chri@ascensit.com>, <chri@infis.univ.ts.it>: concatenation of multiple flashes
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/page.h>
-#include <asm/mach-types.h>
-#include <asm/system.h>
-#include <asm/errno.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#ifdef CONFIG_MTD_CONCAT
-#include <linux/mtd/concat.h>
-#endif
-
-#include <mach/hardware.h>
-#include <mach/h3600.h>
-#include <asm/io.h>
-
-
-#ifndef CONFIG_IPAQ_HANDHELD
-#error This is for iPAQ Handhelds only
-#endif
-#ifdef CONFIG_SA1100_JORNADA56X
-
-static void jornada56x_set_vpp(struct map_info *map, int vpp)
-{
-	if (vpp)
-		GPSR = GPIO_GPIO26;
-	else
-		GPCR = GPIO_GPIO26;
-	GPDR |= GPIO_GPIO26;
-}
-
-#endif
-
-#ifdef CONFIG_SA1100_JORNADA720
-
-static void jornada720_set_vpp(struct map_info *map, int vpp)
-{
-	if (vpp)
-		PPSR |= 0x80;
-	else
-		PPSR &= ~0x80;
-	PPDR |= 0x80;
-}
-
-#endif
-
-#define MAX_IPAQ_CS 2		/* Number of CS we are going to test */
-
-#define IPAQ_MAP_INIT(X) \
-	{ \
-		name:		"IPAQ flash " X, \
-	}
-
-
-static struct map_info ipaq_map[MAX_IPAQ_CS] = {
-	IPAQ_MAP_INIT("bank 1"),
-	IPAQ_MAP_INIT("bank 2")
-};
-
-static struct mtd_info *my_sub_mtd[MAX_IPAQ_CS] = {
-	NULL,
-	NULL
-};
-
-/*
- * Here are partition information for all known IPAQ-based devices.
- * See include/linux/mtd/partitions.h for definition of the mtd_partition
- * structure.
- *
- * The *_max_flash_size is the maximum possible mapped flash size which
- * is not necessarily the actual flash size.  It must be no more than
- * the value specified in the "struct map_desc *_io_desc" mapping
- * definition for the corresponding machine.
- *
- * Please keep these in alphabetical order, and formatted as per existing
- * entries.  Thanks.
- */
-
-#ifdef CONFIG_IPAQ_HANDHELD
-static unsigned long h3xxx_max_flash_size = 0x04000000;
-static struct mtd_partition h3xxx_partitions[] = {
-	{
-		name:		"H3XXX boot firmware",
-#ifndef CONFIG_LAB
-		size:		0x00040000,
-#else
-		size:		0x00080000,
-#endif
-		offset:		0,
-#ifndef CONFIG_LAB
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-#endif
-	},
-	{
-		name:		"H3XXX root jffs2",
-#ifndef CONFIG_LAB
-		size:		0x2000000 - 2*0x40000, /* Warning, this is fixed later */
-		offset:		0x00040000,
-#else
-		size:		0x2000000 - 0x40000 - 0x80000, /* Warning, this is fixed later */
-		offset:		0x00080000,
-#endif
-	},
-	{
-		name:		"asset",
-		size:		0x40000,
-		offset:		0x2000000 - 0x40000, /* Warning, this is fixed later */
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}
-};
-
-#ifndef CONFIG_MTD_CONCAT
-static struct mtd_partition h3xxx_partitions_bank2[] = {
-	/* this is used only on 2 CS machines when concat is not present */
-	{
-		name:		"second H3XXX root jffs2",
-		size:		0x1000000 - 0x40000, /* Warning, this is fixed later */
-		offset:		0x00000000,
-	},
-	{
-		name:		"second asset",
-		size:		0x40000,
-		offset:		0x1000000 - 0x40000, /* Warning, this is fixed later */
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}
-};
-#endif
-
-static DEFINE_SPINLOCK(ipaq_vpp_lock);
-
-static void h3xxx_set_vpp(struct map_info *map, int vpp)
-{
-	static int nest = 0;
-
-	spin_lock(&ipaq_vpp_lock);
-	if (vpp)
-		nest++;
-	else
-		nest--;
-	if (nest)
-		assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 1);
-	else
-		assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, 0);
-	spin_unlock(&ipaq_vpp_lock);
-}
-
-#endif
-
-#if defined(CONFIG_SA1100_JORNADA56X) || defined(CONFIG_SA1100_JORNADA720)
-static unsigned long jornada_max_flash_size = 0x02000000;
-static struct mtd_partition jornada_partitions[] = {
-	{
-		name:		"Jornada boot firmware",
-		size:		0x00040000,
-		offset:		0,
-		mask_flags:	MTD_WRITEABLE,  /* force read-only */
-	}, {
-		name:		"Jornada root jffs2",
-		size:		MTDPART_SIZ_FULL,
-		offset:		0x00040000,
-	}
-};
-#endif
-
-
-static struct mtd_partition *parsed_parts;
-static struct mtd_info *mymtd;
-
-static unsigned long cs_phys[] = {
-#ifdef CONFIG_ARCH_SA1100
-	SA1100_CS0_PHYS,
-	SA1100_CS1_PHYS,
-	SA1100_CS2_PHYS,
-	SA1100_CS3_PHYS,
-	SA1100_CS4_PHYS,
-	SA1100_CS5_PHYS,
-#else
-	PXA_CS0_PHYS,
-	PXA_CS1_PHYS,
-	PXA_CS2_PHYS,
-	PXA_CS3_PHYS,
-	PXA_CS4_PHYS,
-	PXA_CS5_PHYS,
-#endif
-};
-
-static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
-
-static int __init h1900_special_case(void);
-
-static int __init ipaq_mtd_init(void)
-{
-	struct mtd_partition *parts = NULL;
-	int nb_parts = 0;
-	int parsed_nr_parts = 0;
-	const char *part_type;
-	int i; /* used when we have >1 flash chips */
-	unsigned long tot_flashsize = 0; /* used when we have >1 flash chips */
-
-	/* Default flash bankwidth */
-	// ipaq_map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
-
-	if (machine_is_h1900())
-	{
-		/* For our intents, the h1900 is not a real iPAQ, so we special-case it. */
-		return h1900_special_case();
-	}
-
-	if (machine_is_h3100() || machine_is_h1900())
-		for(i=0; i<MAX_IPAQ_CS; i++)
-			ipaq_map[i].bankwidth = 2;
-	else
-		for(i=0; i<MAX_IPAQ_CS; i++)
-			ipaq_map[i].bankwidth = 4;
-
-	/*
-	 * Static partition definition selection
-	 */
-	part_type = "static";
-
-	simple_map_init(&ipaq_map[0]);
-	simple_map_init(&ipaq_map[1]);
-
-#ifdef CONFIG_IPAQ_HANDHELD
-	if (machine_is_ipaq()) {
-		parts = h3xxx_partitions;
-		nb_parts = ARRAY_SIZE(h3xxx_partitions);
-		for(i=0; i<MAX_IPAQ_CS; i++) {
-			ipaq_map[i].size = h3xxx_max_flash_size;
-			ipaq_map[i].set_vpp = h3xxx_set_vpp;
-			ipaq_map[i].phys = cs_phys[i];
-			ipaq_map[i].virt = ioremap(cs_phys[i], 0x04000000);
-			if (machine_is_h3100 () || machine_is_h1900())
-				ipaq_map[i].bankwidth = 2;
-		}
-		if (machine_is_h3600()) {
-			/* No asset partition here */
-			h3xxx_partitions[1].size += 0x40000;
-			nb_parts--;
-		}
-	}
-#endif
-#ifdef CONFIG_ARCH_H5400
-	if (machine_is_h5400()) {
-		ipaq_map[0].size = 0x02000000;
-		ipaq_map[1].size = 0x02000000;
-		ipaq_map[1].phys = 0x02000000;
-		ipaq_map[1].virt = ipaq_map[0].virt + 0x02000000;
-	}
-#endif
-#ifdef CONFIG_ARCH_H1900
-	if (machine_is_h1900()) {
-		ipaq_map[0].size = 0x00400000;
-		ipaq_map[1].size = 0x02000000;
-		ipaq_map[1].phys = 0x00080000;
-		ipaq_map[1].virt = ipaq_map[0].virt + 0x00080000;
-	}
-#endif
-
-#ifdef CONFIG_SA1100_JORNADA56X
-	if (machine_is_jornada56x()) {
-		parts = jornada_partitions;
-		nb_parts = ARRAY_SIZE(jornada_partitions);
-		ipaq_map[0].size = jornada_max_flash_size;
-		ipaq_map[0].set_vpp = jornada56x_set_vpp;
-		ipaq_map[0].virt = (__u32)ioremap(0x0, 0x04000000);
-	}
-#endif
-#ifdef CONFIG_SA1100_JORNADA720
-	if (machine_is_jornada720()) {
-		parts = jornada_partitions;
-		nb_parts = ARRAY_SIZE(jornada_partitions);
-		ipaq_map[0].size = jornada_max_flash_size;
-		ipaq_map[0].set_vpp = jornada720_set_vpp;
-	}
-#endif
-
-
-	if (machine_is_ipaq()) { /* for iPAQs only */
-		for(i=0; i<MAX_IPAQ_CS; i++) {
-			printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with CFI.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
-			my_sub_mtd[i] = do_map_probe("cfi_probe", &ipaq_map[i]);
-			if (!my_sub_mtd[i]) {
-				printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[i].bankwidth*8, ipaq_map[i].virt);
-				my_sub_mtd[i] = do_map_probe("jedec_probe", &ipaq_map[i]);
-			}
-			if (!my_sub_mtd[i]) {
-				printk(KERN_NOTICE "iPAQ flash: failed to find flash.\n");
-				if (i)
-					break;
-				else
-					return -ENXIO;
-			} else
-				printk(KERN_NOTICE "iPAQ flash: found %d bytes\n", my_sub_mtd[i]->size);
-
-			/* do we really need this debugging? --joshua 20030703 */
-			// printk("my_sub_mtd[%d]=%p\n", i, my_sub_mtd[i]);
-			my_sub_mtd[i]->owner = THIS_MODULE;
-			tot_flashsize += my_sub_mtd[i]->size;
-		}
-#ifdef CONFIG_MTD_CONCAT
-		/* fix the asset location */
-#	ifdef CONFIG_LAB
-		h3xxx_partitions[1].size = tot_flashsize - 0x40000 - 0x80000 /* extra big boot block */;
-#	else
-		h3xxx_partitions[1].size = tot_flashsize - 2 * 0x40000;
-#	endif
-		h3xxx_partitions[2].offset = tot_flashsize - 0x40000;
-		/* and concat the devices */
-		mymtd = mtd_concat_create(&my_sub_mtd[0], i,
-					  "ipaq");
-		if (!mymtd) {
-			printk("Cannot create iPAQ concat device\n");
-			return -ENXIO;
-		}
-#else
-		mymtd = my_sub_mtd[0];
-
-		/*
-		 *In the very near future, command line partition parsing
-		 * will use the device name as 'mtd-id' instead of a value
-		 * passed to the parse_cmdline_partitions() routine. Since
-		 * the bootldr says 'ipaq', make sure it continues to work.
-		 */
-		mymtd->name = "ipaq";
-
-		if ((machine_is_h3600())) {
-#	ifdef CONFIG_LAB
-			h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x80000;
-#	else
-			h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000;
-#	endif
-			nb_parts = 2;
-		} else {
-#	ifdef CONFIG_LAB
-			h3xxx_partitions[1].size = my_sub_mtd[0]->size - 0x40000 - 0x80000; /* extra big boot block */
-#	else
-			h3xxx_partitions[1].size = my_sub_mtd[0]->size - 2*0x40000;
-#	endif
-			h3xxx_partitions[2].offset = my_sub_mtd[0]->size - 0x40000;
-		}
-
-		if (my_sub_mtd[1]) {
-#	ifdef CONFIG_LAB
-			h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x80000;
-#	else
-			h3xxx_partitions_bank2[0].size = my_sub_mtd[1]->size - 0x40000;
-#	endif
-			h3xxx_partitions_bank2[1].offset = my_sub_mtd[1]->size - 0x40000;
-		}
-#endif
-	}
-	else {
-		/*
-		 * Now let's probe for the actual flash.  Do it here since
-		 * specific machine settings might have been set above.
-		 */
-		printk(KERN_NOTICE "IPAQ flash: probing %d-bit flash bus, window=%lx\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
-		mymtd = do_map_probe("cfi_probe", &ipaq_map[0]);
-		if (!mymtd)
-			return -ENXIO;
-		mymtd->owner = THIS_MODULE;
-	}
-
-
-	/*
-	 * Dynamic partition selection stuff (might override the static ones)
-	 */
-
-	 i = parse_mtd_partitions(mymtd, part_probes, &parsed_parts, 0);
-
-	 if (i > 0) {
-		 nb_parts = parsed_nr_parts = i;
-		 parts = parsed_parts;
-		 part_type = "dynamic";
-	 }
-
-	 if (!parts) {
-		 printk(KERN_NOTICE "IPAQ flash: no partition info available, registering whole flash at once\n");
-		 add_mtd_device(mymtd);
-#ifndef CONFIG_MTD_CONCAT
-		 if (my_sub_mtd[1])
-			 add_mtd_device(my_sub_mtd[1]);
-#endif
-	 } else {
-		 printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-		 add_mtd_partitions(mymtd, parts, nb_parts);
-#ifndef CONFIG_MTD_CONCAT
-		 if (my_sub_mtd[1])
-			 add_mtd_partitions(my_sub_mtd[1], h3xxx_partitions_bank2, ARRAY_SIZE(h3xxx_partitions_bank2));
-#endif
-	 }
-
-	 return 0;
-}
-
-static void __exit ipaq_mtd_cleanup(void)
-{
-	int i;
-
-	if (mymtd) {
-		del_mtd_partitions(mymtd);
-#ifndef CONFIG_MTD_CONCAT
-		if (my_sub_mtd[1])
-			del_mtd_partitions(my_sub_mtd[1]);
-#endif
-		map_destroy(mymtd);
-#ifdef CONFIG_MTD_CONCAT
-		for(i=0; i<MAX_IPAQ_CS; i++)
-#else
-			for(i=1; i<MAX_IPAQ_CS; i++)
-#endif
-			{
-				if (my_sub_mtd[i])
-					map_destroy(my_sub_mtd[i]);
-			}
-		kfree(parsed_parts);
-	}
-}
-
-static int __init h1900_special_case(void)
-{
-	/* The iPAQ h1900 is a special case - it has weird ROM. */
-	simple_map_init(&ipaq_map[0]);
-	ipaq_map[0].size = 0x80000;
-	ipaq_map[0].set_vpp = h3xxx_set_vpp;
-	ipaq_map[0].phys = 0x0;
-	ipaq_map[0].virt = ioremap(0x0, 0x04000000);
-	ipaq_map[0].bankwidth = 2;
-
-	printk(KERN_NOTICE "iPAQ flash: probing %d-bit flash bus, window=%lx with JEDEC.\n", ipaq_map[0].bankwidth*8, ipaq_map[0].virt);
-	mymtd = do_map_probe("jedec_probe", &ipaq_map[0]);
-	if (!mymtd)
-		return -ENODEV;
-	add_mtd_device(mymtd);
-	printk(KERN_NOTICE "iPAQ flash: registered h1910 flash\n");
-
-	return 0;
-}
-
-module_init(ipaq_mtd_init);
-module_exit(ipaq_mtd_cleanup);
-
-MODULE_AUTHOR("Jamey Hicks");
-MODULE_DESCRIPTION("IPAQ CFI map driver");
-MODULE_LICENSE("MIT");
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 7214b87..7b05152 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -210,7 +210,7 @@
 	 * not attempt to do a direct access on us.
 	 */
 	info->map.phys = NO_XIP;
-	info->map.size = dev->resource->end - dev->resource->start + 1;
+	info->map.size = resource_size(dev->resource);
 
 	/*
 	 * We only support 16-bit accesses for now. If and when
@@ -224,7 +224,7 @@
 	info->map.copy_from = ixp4xx_copy_from,
 
 	info->res = request_mem_region(dev->resource->start,
-			dev->resource->end - dev->resource->start + 1,
+			resource_size(dev->resource),
 			"IXP4XXFlash");
 	if (!info->res) {
 		printk(KERN_ERR "IXP4XXFlash: Could not reserve memory region\n");
@@ -233,7 +233,7 @@
 	}
 
 	info->map.virt = ioremap(dev->resource->start,
-				 dev->resource->end - dev->resource->start + 1);
+				 resource_size(dev->resource));
 	if (!info->map.virt) {
 		printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
 		err = -EIO;
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 380648e..d9603f7 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -48,23 +48,22 @@
 
 	if (info->cmtd) {
 #ifdef CONFIG_MTD_PARTITIONS
-		if (info->nr_parts || physmap_data->nr_parts)
+		if (info->nr_parts || physmap_data->nr_parts) {
 			del_mtd_partitions(info->cmtd);
-		else
+
+			if (info->nr_parts)
+				kfree(info->parts);
+		} else {
 			del_mtd_device(info->cmtd);
+		}
 #else
 		del_mtd_device(info->cmtd);
 #endif
-	}
-#ifdef CONFIG_MTD_PARTITIONS
-	if (info->nr_parts)
-		kfree(info->parts);
-#endif
-
 #ifdef CONFIG_MTD_CONCAT
-	if (info->cmtd != info->mtd[0])
-		mtd_concat_destroy(info->cmtd);
+		if (info->cmtd != info->mtd[0])
+			mtd_concat_destroy(info->cmtd);
 #endif
+	}
 
 	for (i = 0; i < MAX_RESOURCES; i++) {
 		if (info->mtd[i] != NULL)
@@ -130,7 +129,7 @@
 						 info->map[i].size);
 		if (info->map[i].virt == NULL) {
 			dev_err(&dev->dev, "Failed to ioremap flash region\n");
-			err = EIO;
+			err = -EIO;
 			goto err_out;
 		}
 
diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index 74fa075..b13f641 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -20,14 +20,23 @@
 
 #include <asm/io.h>
 #include <mach/hardware.h>
-#include <asm/cacheflush.h>
 
 #include <asm/mach/flash.h>
 
+#define CACHELINESIZE	32
+
 static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
 				      ssize_t len)
 {
-	flush_ioremap_region(map->phys, map->cached, from, len);
+	unsigned long start = (unsigned long)map->cached + from;
+	unsigned long end = start + len;
+
+	start &= ~(CACHELINESIZE - 1);
+	while (start < end) {
+		/* invalidate D cache line */
+		asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start));
+		start += CACHELINESIZE;
+	}
 }
 
 struct pxa2xx_flash_info {
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index d7a4757..f3af87e 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -248,7 +248,7 @@
 		plat->exit();
 }
 
-static struct sa_info *__init
+static struct sa_info *__devinit
 sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *plat)
 {
 	struct sa_info *info;
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 1f73297..82afad0 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -612,16 +612,15 @@
 
 	test_flash_data = be32_to_cpu(mdev->devinfo.function);
 	/* Need to count how many bits are set - to find out which
-	 * function_data element has details of the memory card:
-	 * using Brian Kernighan's/Peter Wegner's method */
-	for (c = 0; test_flash_data; c++)
-		test_flash_data &= test_flash_data - 1;
+	 * function_data element has details of the memory card
+	 */
+	c = hweight_long(test_flash_data);
 
 	basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
 
 	card = kmalloc(sizeof(struct memcard), GFP_KERNEL);
 	if (!card) {
-		error = ENOMEM;
+		error = -ENOMEM;
 		goto fail_nomem;
 	}
 
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 64e2b37..c82e09b 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -84,9 +84,6 @@
 	struct request_queue *rq = tr->blkcore_priv->rq;
 	struct request *req = NULL;
 
-	/* we might get involved when memory gets low, so use PF_MEMALLOC */
-	current->flags |= PF_MEMALLOC;
-
 	spin_lock_irq(rq->queue_lock);
 
 	while (!kthread_should_stop()) {
@@ -381,7 +378,7 @@
 	tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr,
 			"%sd", tr->name);
 	if (IS_ERR(tr->blkcore_priv->thread)) {
-		int ret = PTR_ERR(tr->blkcore_priv->thread);
+		ret = PTR_ERR(tr->blkcore_priv->thread);
 		blk_cleanup_queue(tr->blkcore_priv->rq);
 		unregister_blkdev(tr->major, tr->name);
 		kfree(tr->blkcore_priv);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 467a4f1..c356c0a 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -447,7 +447,7 @@
 		for (i=0; i< MAX_MTD_DEVICES; i++)
 			if (mtd_table[i] == mtd)
 				ret = mtd_table[i];
-	} else if (num < MAX_MTD_DEVICES) {
+	} else if (num >= 0 && num < MAX_MTD_DEVICES) {
 		ret = mtd_table[num];
 		if (mtd && mtd != ret)
 			ret = NULL;
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 1060337..a714ec4 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -29,14 +29,34 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/delay.h>
-#include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
+#include <linux/kmsg_dump.h>
+
+/* Maximum MTD partition size */
+#define MTDOOPS_MAX_MTD_SIZE (8 * 1024 * 1024)
 
 #define MTDOOPS_KERNMSG_MAGIC 0x5d005d00
-#define OOPS_PAGE_SIZE 4096
+#define MTDOOPS_HEADER_SIZE   8
+
+static unsigned long record_size = 4096;
+module_param(record_size, ulong, 0400);
+MODULE_PARM_DESC(record_size,
+		"record size for MTD OOPS pages in bytes (default 4096)");
+
+static char mtddev[80];
+module_param_string(mtddev, mtddev, 80, 0400);
+MODULE_PARM_DESC(mtddev,
+		"name or index number of the MTD device to use");
+
+static int dump_oops = 1;
+module_param(dump_oops, int, 0600);
+MODULE_PARM_DESC(dump_oops,
+		"set to 1 to dump oopses, 0 to only dump panics (default 1)");
 
 static struct mtdoops_context {
+	struct kmsg_dumper dump;
+
 	int mtd_index;
 	struct work_struct work_erase;
 	struct work_struct work_write;
@@ -44,28 +64,43 @@
 	int oops_pages;
 	int nextpage;
 	int nextcount;
-	char *name;
+	unsigned long *oops_page_used;
 
 	void *oops_buf;
-
-	/* writecount and disabling ready are spin lock protected */
-	spinlock_t writecount_lock;
-	int ready;
-	int writecount;
 } oops_cxt;
 
+static void mark_page_used(struct mtdoops_context *cxt, int page)
+{
+	set_bit(page, cxt->oops_page_used);
+}
+
+static void mark_page_unused(struct mtdoops_context *cxt, int page)
+{
+	clear_bit(page, cxt->oops_page_used);
+}
+
+static int page_is_used(struct mtdoops_context *cxt, int page)
+{
+	return test_bit(page, cxt->oops_page_used);
+}
+
 static void mtdoops_erase_callback(struct erase_info *done)
 {
 	wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
 	wake_up(wait_q);
 }
 
-static int mtdoops_erase_block(struct mtd_info *mtd, int offset)
+static int mtdoops_erase_block(struct mtdoops_context *cxt, int offset)
 {
+	struct mtd_info *mtd = cxt->mtd;
+	u32 start_page_offset = mtd_div_by_eb(offset, mtd) * mtd->erasesize;
+	u32 start_page = start_page_offset / record_size;
+	u32 erase_pages = mtd->erasesize / record_size;
 	struct erase_info erase;
 	DECLARE_WAITQUEUE(wait, current);
 	wait_queue_head_t wait_q;
 	int ret;
+	int page;
 
 	init_waitqueue_head(&wait_q);
 	erase.mtd = mtd;
@@ -81,25 +116,24 @@
 	if (ret) {
 		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&wait_q, &wait);
-		printk (KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] "
-				     "on \"%s\" failed\n",
-			(unsigned long long)erase.addr, (unsigned long long)erase.len, mtd->name);
+		printk(KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] on \"%s\" failed\n",
+		       (unsigned long long)erase.addr,
+		       (unsigned long long)erase.len, mtddev);
 		return ret;
 	}
 
 	schedule();  /* Wait for erase to finish. */
 	remove_wait_queue(&wait_q, &wait);
 
+	/* Mark pages as unused */
+	for (page = start_page; page < start_page + erase_pages; page++)
+		mark_page_unused(cxt, page);
+
 	return 0;
 }
 
 static void mtdoops_inc_counter(struct mtdoops_context *cxt)
 {
-	struct mtd_info *mtd = cxt->mtd;
-	size_t retlen;
-	u32 count;
-	int ret;
-
 	cxt->nextpage++;
 	if (cxt->nextpage >= cxt->oops_pages)
 		cxt->nextpage = 0;
@@ -107,25 +141,13 @@
 	if (cxt->nextcount == 0xffffffff)
 		cxt->nextcount = 0;
 
-	ret = mtd->read(mtd, cxt->nextpage * OOPS_PAGE_SIZE, 4,
-			&retlen, (u_char *) &count);
-	if ((retlen != 4) || ((ret < 0) && (ret != -EUCLEAN))) {
-		printk(KERN_ERR "mtdoops: Read failure at %d (%td of 4 read)"
-				", err %d.\n", cxt->nextpage * OOPS_PAGE_SIZE,
-				retlen, ret);
+	if (page_is_used(cxt, cxt->nextpage)) {
 		schedule_work(&cxt->work_erase);
 		return;
 	}
 
-	/* See if we need to erase the next block */
-	if (count != 0xffffffff) {
-		schedule_work(&cxt->work_erase);
-		return;
-	}
-
-	printk(KERN_DEBUG "mtdoops: Ready %d, %d (no erase)\n",
-			cxt->nextpage, cxt->nextcount);
-	cxt->ready = 1;
+	printk(KERN_DEBUG "mtdoops: ready %d, %d (no erase)\n",
+	       cxt->nextpage, cxt->nextcount);
 }
 
 /* Scheduled work - when we can't proceed without erasing a block */
@@ -140,47 +162,47 @@
 	if (!mtd)
 		return;
 
-	mod = (cxt->nextpage * OOPS_PAGE_SIZE) % mtd->erasesize;
+	mod = (cxt->nextpage * record_size) % mtd->erasesize;
 	if (mod != 0) {
-		cxt->nextpage = cxt->nextpage + ((mtd->erasesize - mod) / OOPS_PAGE_SIZE);
+		cxt->nextpage = cxt->nextpage + ((mtd->erasesize - mod) / record_size);
 		if (cxt->nextpage >= cxt->oops_pages)
 			cxt->nextpage = 0;
 	}
 
 	while (mtd->block_isbad) {
-		ret = mtd->block_isbad(mtd, cxt->nextpage * OOPS_PAGE_SIZE);
+		ret = mtd->block_isbad(mtd, cxt->nextpage * record_size);
 		if (!ret)
 			break;
 		if (ret < 0) {
-			printk(KERN_ERR "mtdoops: block_isbad failed, aborting.\n");
+			printk(KERN_ERR "mtdoops: block_isbad failed, aborting\n");
 			return;
 		}
 badblock:
-		printk(KERN_WARNING "mtdoops: Bad block at %08x\n",
-				cxt->nextpage * OOPS_PAGE_SIZE);
+		printk(KERN_WARNING "mtdoops: bad block at %08lx\n",
+		       cxt->nextpage * record_size);
 		i++;
-		cxt->nextpage = cxt->nextpage + (mtd->erasesize / OOPS_PAGE_SIZE);
+		cxt->nextpage = cxt->nextpage + (mtd->erasesize / record_size);
 		if (cxt->nextpage >= cxt->oops_pages)
 			cxt->nextpage = 0;
-		if (i == (cxt->oops_pages / (mtd->erasesize / OOPS_PAGE_SIZE))) {
-			printk(KERN_ERR "mtdoops: All blocks bad!\n");
+		if (i == cxt->oops_pages / (mtd->erasesize / record_size)) {
+			printk(KERN_ERR "mtdoops: all blocks bad!\n");
 			return;
 		}
 	}
 
 	for (j = 0, ret = -1; (j < 3) && (ret < 0); j++)
-		ret = mtdoops_erase_block(mtd, cxt->nextpage * OOPS_PAGE_SIZE);
+		ret = mtdoops_erase_block(cxt, cxt->nextpage * record_size);
 
 	if (ret >= 0) {
-		printk(KERN_DEBUG "mtdoops: Ready %d, %d \n", cxt->nextpage, cxt->nextcount);
-		cxt->ready = 1;
+		printk(KERN_DEBUG "mtdoops: ready %d, %d\n",
+		       cxt->nextpage, cxt->nextcount);
 		return;
 	}
 
-	if (mtd->block_markbad && (ret == -EIO)) {
-		ret = mtd->block_markbad(mtd, cxt->nextpage * OOPS_PAGE_SIZE);
+	if (mtd->block_markbad && ret == -EIO) {
+		ret = mtd->block_markbad(mtd, cxt->nextpage * record_size);
 		if (ret < 0) {
-			printk(KERN_ERR "mtdoops: block_markbad failed, aborting.\n");
+			printk(KERN_ERR "mtdoops: block_markbad failed, aborting\n");
 			return;
 		}
 	}
@@ -191,36 +213,37 @@
 {
 	struct mtd_info *mtd = cxt->mtd;
 	size_t retlen;
+	u32 *hdr;
 	int ret;
 
-	if (cxt->writecount < OOPS_PAGE_SIZE)
-		memset(cxt->oops_buf + cxt->writecount, 0xff,
-					OOPS_PAGE_SIZE - cxt->writecount);
+	/* Add mtdoops header to the buffer */
+	hdr = cxt->oops_buf;
+	hdr[0] = cxt->nextcount;
+	hdr[1] = MTDOOPS_KERNMSG_MAGIC;
 
 	if (panic)
-		ret = mtd->panic_write(mtd, cxt->nextpage * OOPS_PAGE_SIZE,
-					OOPS_PAGE_SIZE, &retlen, cxt->oops_buf);
+		ret = mtd->panic_write(mtd, cxt->nextpage * record_size,
+					record_size, &retlen, cxt->oops_buf);
 	else
-		ret = mtd->write(mtd, cxt->nextpage * OOPS_PAGE_SIZE,
-					OOPS_PAGE_SIZE, &retlen, cxt->oops_buf);
+		ret = mtd->write(mtd, cxt->nextpage * record_size,
+					record_size, &retlen, cxt->oops_buf);
 
-	cxt->writecount = 0;
-
-	if ((retlen != OOPS_PAGE_SIZE) || (ret < 0))
-		printk(KERN_ERR "mtdoops: Write failure at %d (%td of %d written), err %d.\n",
-			cxt->nextpage * OOPS_PAGE_SIZE, retlen,	OOPS_PAGE_SIZE, ret);
+	if (retlen != record_size || ret < 0)
+		printk(KERN_ERR "mtdoops: write failure at %ld (%td of %ld written), error %d\n",
+		       cxt->nextpage * record_size, retlen, record_size, ret);
+	mark_page_used(cxt, cxt->nextpage);
+	memset(cxt->oops_buf, 0xff, record_size);
 
 	mtdoops_inc_counter(cxt);
 }
 
-
 static void mtdoops_workfunc_write(struct work_struct *work)
 {
 	struct mtdoops_context *cxt =
 			container_of(work, struct mtdoops_context, work_write);
 
 	mtdoops_write(cxt, 0);
-}					
+}
 
 static void find_next_position(struct mtdoops_context *cxt)
 {
@@ -230,28 +253,33 @@
 	size_t retlen;
 
 	for (page = 0; page < cxt->oops_pages; page++) {
-		ret = mtd->read(mtd, page * OOPS_PAGE_SIZE, 8, &retlen, (u_char *) &count[0]);
-		if ((retlen != 8) || ((ret < 0) && (ret != -EUCLEAN))) {
-			printk(KERN_ERR "mtdoops: Read failure at %d (%td of 8 read)"
-				", err %d.\n", page * OOPS_PAGE_SIZE, retlen, ret);
+		/* Assume the page is used */
+		mark_page_used(cxt, page);
+		ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
+				&retlen, (u_char *) &count[0]);
+		if (retlen != MTDOOPS_HEADER_SIZE ||
+				(ret < 0 && ret != -EUCLEAN)) {
+			printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
+			       page * record_size, retlen,
+			       MTDOOPS_HEADER_SIZE, ret);
 			continue;
 		}
 
-		if (count[1] != MTDOOPS_KERNMSG_MAGIC)
-			continue;
+		if (count[0] == 0xffffffff && count[1] == 0xffffffff)
+			mark_page_unused(cxt, page);
 		if (count[0] == 0xffffffff)
 			continue;
 		if (maxcount == 0xffffffff) {
 			maxcount = count[0];
 			maxpos = page;
-		} else if ((count[0] < 0x40000000) && (maxcount > 0xc0000000)) {
+		} else if (count[0] < 0x40000000 && maxcount > 0xc0000000) {
 			maxcount = count[0];
 			maxpos = page;
-		} else if ((count[0] > maxcount) && (count[0] < 0xc0000000)) {
+		} else if (count[0] > maxcount && count[0] < 0xc0000000) {
 			maxcount = count[0];
 			maxpos = page;
-		} else if ((count[0] > maxcount) && (count[0] > 0xc0000000)
-					&& (maxcount > 0x80000000)) {
+		} else if (count[0] > maxcount && count[0] > 0xc0000000
+					&& maxcount > 0x80000000) {
 			maxcount = count[0];
 			maxpos = page;
 		}
@@ -269,37 +297,91 @@
 	mtdoops_inc_counter(cxt);
 }
 
+static void mtdoops_do_dump(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
+		const char *s2, unsigned long l2)
+{
+	struct mtdoops_context *cxt = container_of(dumper,
+			struct mtdoops_context, dump);
+	unsigned long s1_start, s2_start;
+	unsigned long l1_cpy, l2_cpy;
+	char *dst;
+
+	/* Only dump oopses if dump_oops is set */
+	if (reason == KMSG_DUMP_OOPS && !dump_oops)
+		return;
+
+	dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */
+	l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE);
+	l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy);
+
+	s2_start = l2 - l2_cpy;
+	s1_start = l1 - l1_cpy;
+
+	memcpy(dst, s1 + s1_start, l1_cpy);
+	memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
+
+	/* Panics must be written immediately */
+	if (reason == KMSG_DUMP_PANIC) {
+		if (!cxt->mtd->panic_write)
+			printk(KERN_ERR "mtdoops: Cannot write from panic without panic_write\n");
+		else
+			mtdoops_write(cxt, 1);
+		return;
+	}
+
+	/* For other cases, schedule work to write it "nicely" */
+	schedule_work(&cxt->work_write);
+}
 
 static void mtdoops_notify_add(struct mtd_info *mtd)
 {
 	struct mtdoops_context *cxt = &oops_cxt;
+	u64 mtdoops_pages = div_u64(mtd->size, record_size);
+	int err;
 
-	if (cxt->name && !strcmp(mtd->name, cxt->name))
+	if (!strcmp(mtd->name, mtddev))
 		cxt->mtd_index = mtd->index;
 
-	if ((mtd->index != cxt->mtd_index) || cxt->mtd_index < 0)
+	if (mtd->index != cxt->mtd_index || cxt->mtd_index < 0)
 		return;
 
-	if (mtd->size < (mtd->erasesize * 2)) {
-		printk(KERN_ERR "MTD partition %d not big enough for mtdoops\n",
-				mtd->index);
+	if (mtd->size < mtd->erasesize * 2) {
+		printk(KERN_ERR "mtdoops: MTD partition %d not big enough for mtdoops\n",
+		       mtd->index);
+		return;
+	}
+	if (mtd->erasesize < record_size) {
+		printk(KERN_ERR "mtdoops: eraseblock size of MTD partition %d too small\n",
+		       mtd->index);
+		return;
+	}
+	if (mtd->size > MTDOOPS_MAX_MTD_SIZE) {
+		printk(KERN_ERR "mtdoops: mtd%d is too large (limit is %d MiB)\n",
+		       mtd->index, MTDOOPS_MAX_MTD_SIZE / 1024 / 1024);
 		return;
 	}
 
-	if (mtd->erasesize < OOPS_PAGE_SIZE) {
-		printk(KERN_ERR "Eraseblock size of MTD partition %d too small\n",
-				mtd->index);
+	/* oops_page_used is a bit field */
+	cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages,
+			BITS_PER_LONG));
+	if (!cxt->oops_page_used) {
+		printk(KERN_ERR "mtdoops: could not allocate page array\n");
+		return;
+	}
+
+	cxt->dump.dump = mtdoops_do_dump;
+	err = kmsg_dump_register(&cxt->dump);
+	if (err) {
+		printk(KERN_ERR "mtdoops: registering kmsg dumper failed, error %d\n", err);
+		vfree(cxt->oops_page_used);
+		cxt->oops_page_used = NULL;
 		return;
 	}
 
 	cxt->mtd = mtd;
-	if (mtd->size > INT_MAX)
-		cxt->oops_pages = INT_MAX / OOPS_PAGE_SIZE;
-	else
-		cxt->oops_pages = (int)mtd->size / OOPS_PAGE_SIZE;
-
+	cxt->oops_pages = (int)mtd->size / record_size;
 	find_next_position(cxt);
-
 	printk(KERN_INFO "mtdoops: Attached to MTD device %d\n", mtd->index);
 }
 
@@ -307,149 +389,78 @@
 {
 	struct mtdoops_context *cxt = &oops_cxt;
 
-	if ((mtd->index != cxt->mtd_index) || cxt->mtd_index < 0)
+	if (mtd->index != cxt->mtd_index || cxt->mtd_index < 0)
 		return;
 
+	if (kmsg_dump_unregister(&cxt->dump) < 0)
+		printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n");
+
 	cxt->mtd = NULL;
 	flush_scheduled_work();
 }
 
-static void mtdoops_console_sync(void)
-{
-	struct mtdoops_context *cxt = &oops_cxt;
-	struct mtd_info *mtd = cxt->mtd;
-	unsigned long flags;
-
-	if (!cxt->ready || !mtd || cxt->writecount == 0)
-		return;
-
-	/* 
-	 *  Once ready is 0 and we've held the lock no further writes to the 
-	 *  buffer will happen
-	 */
-	spin_lock_irqsave(&cxt->writecount_lock, flags);
-	if (!cxt->ready) {
-		spin_unlock_irqrestore(&cxt->writecount_lock, flags);
-		return;
-	}
-	cxt->ready = 0;
-	spin_unlock_irqrestore(&cxt->writecount_lock, flags);
-
-	if (mtd->panic_write && in_interrupt())
-		/* Interrupt context, we're going to panic so try and log */
-		mtdoops_write(cxt, 1);
-	else
-		schedule_work(&cxt->work_write);
-}
-
-static void
-mtdoops_console_write(struct console *co, const char *s, unsigned int count)
-{
-	struct mtdoops_context *cxt = co->data;
-	struct mtd_info *mtd = cxt->mtd;
-	unsigned long flags;
-
-	if (!oops_in_progress) {
-		mtdoops_console_sync();
-		return;
-	}
-
-	if (!cxt->ready || !mtd)
-		return;
-
-	/* Locking on writecount ensures sequential writes to the buffer */
-	spin_lock_irqsave(&cxt->writecount_lock, flags);
-
-	/* Check ready status didn't change whilst waiting for the lock */
-	if (!cxt->ready) {
-		spin_unlock_irqrestore(&cxt->writecount_lock, flags);
-		return;
-	}
-
-	if (cxt->writecount == 0) {
-		u32 *stamp = cxt->oops_buf;
-		*stamp++ = cxt->nextcount;
-		*stamp = MTDOOPS_KERNMSG_MAGIC;
-		cxt->writecount = 8;
-	}
-
-	if ((count + cxt->writecount) > OOPS_PAGE_SIZE)
-		count = OOPS_PAGE_SIZE - cxt->writecount;
-
-	memcpy(cxt->oops_buf + cxt->writecount, s, count);
-	cxt->writecount += count;
-
-	spin_unlock_irqrestore(&cxt->writecount_lock, flags);
-
-	if (cxt->writecount == OOPS_PAGE_SIZE)
-		mtdoops_console_sync();
-}
-
-static int __init mtdoops_console_setup(struct console *co, char *options)
-{
-	struct mtdoops_context *cxt = co->data;
-
-	if (cxt->mtd_index != -1 || cxt->name)
-		return -EBUSY;
-	if (options) {
-		cxt->name = kstrdup(options, GFP_KERNEL);
-		return 0;
-	}
-	if (co->index == -1)
-		return -EINVAL;
-
-	cxt->mtd_index = co->index;
-	return 0;
-}
 
 static struct mtd_notifier mtdoops_notifier = {
 	.add	= mtdoops_notify_add,
 	.remove	= mtdoops_notify_remove,
 };
 
-static struct console mtdoops_console = {
-	.name		= "ttyMTD",
-	.write		= mtdoops_console_write,
-	.setup		= mtdoops_console_setup,
-	.unblank	= mtdoops_console_sync,
-	.index		= -1,
-	.data		= &oops_cxt,
-};
-
-static int __init mtdoops_console_init(void)
+static int __init mtdoops_init(void)
 {
 	struct mtdoops_context *cxt = &oops_cxt;
+	int mtd_index;
+	char *endp;
 
+	if (strlen(mtddev) == 0) {
+		printk(KERN_ERR "mtdoops: mtd device (mtddev=name/number) must be supplied\n");
+		return -EINVAL;
+	}
+	if ((record_size & 4095) != 0) {
+		printk(KERN_ERR "mtdoops: record_size must be a multiple of 4096\n");
+		return -EINVAL;
+	}
+	if (record_size < 4096) {
+		printk(KERN_ERR "mtdoops: record_size must be over 4096 bytes\n");
+		return -EINVAL;
+	}
+
+	/* Setup the MTD device to use */
 	cxt->mtd_index = -1;
-	cxt->oops_buf = vmalloc(OOPS_PAGE_SIZE);
-	spin_lock_init(&cxt->writecount_lock);
+	mtd_index = simple_strtoul(mtddev, &endp, 0);
+	if (*endp == '\0')
+		cxt->mtd_index = mtd_index;
+	if (cxt->mtd_index > MAX_MTD_DEVICES) {
+		printk(KERN_ERR "mtdoops: invalid mtd device number (%u) given\n",
+				mtd_index);
+		return -EINVAL;
+	}
 
+	cxt->oops_buf = vmalloc(record_size);
 	if (!cxt->oops_buf) {
-		printk(KERN_ERR "Failed to allocate mtdoops buffer workspace\n");
+		printk(KERN_ERR "mtdoops: failed to allocate buffer workspace\n");
 		return -ENOMEM;
 	}
+	memset(cxt->oops_buf, 0xff, record_size);
 
 	INIT_WORK(&cxt->work_erase, mtdoops_workfunc_erase);
 	INIT_WORK(&cxt->work_write, mtdoops_workfunc_write);
 
-	register_console(&mtdoops_console);
 	register_mtd_user(&mtdoops_notifier);
 	return 0;
 }
 
-static void __exit mtdoops_console_exit(void)
+static void __exit mtdoops_exit(void)
 {
 	struct mtdoops_context *cxt = &oops_cxt;
 
 	unregister_mtd_user(&mtdoops_notifier);
-	unregister_console(&mtdoops_console);
-	kfree(cxt->name);
 	vfree(cxt->oops_buf);
+	vfree(cxt->oops_page_used);
 }
 
 
-subsys_initcall(mtdoops_console_init);
-module_exit(mtdoops_console_exit);
+module_init(mtdoops_init);
+module_exit(mtdoops_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 0e35e1a..677cd53 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -201,6 +201,22 @@
 	  when the is NAND chip selected or released, but will save
 	  approximately 5mA of power when there is nothing happening.
 
+config MTD_NAND_BCM_UMI
+	tristate "NAND Flash support for BCM Reference Boards"
+	depends on ARCH_BCMRING && MTD_NAND
+	help
+	  This enables the NAND flash controller on the BCM UMI block.
+
+	  No board specfic support is done by this driver, each board
+	  must advertise a platform_device for the driver to attach.
+
+config MTD_NAND_BCM_UMI_HWCS
+	bool "BCM UMI NAND Hardware CS"
+	depends on MTD_NAND_BCM_UMI
+	help
+	  Enable the use of the BCM UMI block's internal CS using NAND.
+	  This should only be used if you know the external NAND CS can toggle.
+
 config MTD_NAND_DISKONCHIP
 	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
@@ -275,14 +291,6 @@
 	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
 	depends on ARCH_PXA
 
-config MTD_NAND_BASLER_EXCITE
-	tristate  "Support for NAND Flash on Basler eXcite"
-	depends on BASLER_EXCITE
-	help
-          This enables the driver for the NAND flash device found on the
-          Basler eXcite Smart Camera. If built as a module, the driver
-          will be named excite_nandflash.
-
 config MTD_NAND_CAFE
 	tristate "NAND support for OLPC CAFÉ chip"
 	depends on PCI
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 6950d3d..1407bd1 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -27,7 +27,6 @@
 obj-$(CONFIG_MTD_NAND_GPIO)		+= gpio.o
 obj-$(CONFIG_MTD_NAND_OMAP2) 		+= omap2.o
 obj-$(CONFIG_MTD_NAND_CM_X270)		+= cmx270_nand.o
-obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)	+= excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PXA3xx)		+= pxa3xx_nand.o
 obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nand.o
 obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
@@ -42,5 +41,6 @@
 obj-$(CONFIG_MTD_NAND_TXX9NDFMC)	+= txx9ndfmc.o
 obj-$(CONFIG_MTD_NAND_W90P910)		+= w90p910_nand.o
 obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
+obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 6d96491..2d67732 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -372,15 +372,6 @@
 	return __alauda_read_page(mtd, from, ignore_buf, oob);
 }
 
-static int popcount8(u8 c)
-{
-	int ret = 0;
-
-	for ( ; c; c>>=1)
-		ret += c & 1;
-	return ret;
-}
-
 static int alauda_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	u8 oob[16];
@@ -391,7 +382,7 @@
 		return err;
 
 	/* A block is marked bad if two or more bits are zero */
-	return popcount8(oob[5]) >= 7 ? 0 : 1;
+	return hweight8(oob[5]) >= 7 ? 0 : 1;
 }
 
 static int alauda_bounce_read(struct mtd_info *mtd, loff_t from, size_t len,
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index f8e9975..524e6c9 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -192,7 +192,6 @@
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct atmel_nand_host *host = nand_chip->priv;
-	uint32_t *eccpos = nand_chip->ecc.layout->eccpos;
 	unsigned int ecc_value;
 
 	/* get the first 2 ECC bytes */
@@ -464,7 +463,7 @@
 	if (host->board->det_pin) {
 		if (gpio_get_value(host->board->det_pin)) {
 			printk(KERN_INFO "No SmartMedia card inserted.\n");
-			res = ENXIO;
+			res = -ENXIO;
 			goto err_no_card;
 		}
 	}
@@ -535,7 +534,7 @@
 
 	if ((!partitions) || (num_partitions == 0)) {
 		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
-		res = ENXIO;
+		res = -ENXIO;
 		goto err_no_partitions;
 	}
 
diff --git a/drivers/mtd/nand/bcm_umi_bch.c b/drivers/mtd/nand/bcm_umi_bch.c
new file mode 100644
index 0000000..a930666
--- /dev/null
+++ b/drivers/mtd/nand/bcm_umi_bch.c
@@ -0,0 +1,213 @@
+/*****************************************************************************
+* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/* ---- Include Files ---------------------------------------------------- */
+#include "nand_bcm_umi.h"
+
+/* ---- External Variable Declarations ----------------------------------- */
+/* ---- External Function Prototypes ------------------------------------- */
+/* ---- Public Variables ------------------------------------------------- */
+/* ---- Private Constants and Types -------------------------------------- */
+
+/* ---- Private Function Prototypes -------------------------------------- */
+static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
+	struct nand_chip *chip, uint8_t *buf, int page);
+static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
+	struct nand_chip *chip, const uint8_t *buf);
+
+/* ---- Private Variables ------------------------------------------------ */
+
+/*
+** nand_hw_eccoob
+** New oob placement block for use with hardware ecc generation.
+*/
+static struct nand_ecclayout nand_hw_eccoob_512 = {
+	/* Reserve 5 for BI indicator */
+	.oobfree = {
+#if (NAND_ECC_NUM_BYTES > 3)
+		    {.offset = 0, .length = 2}
+#else
+		    {.offset = 0, .length = 5},
+		    {.offset = 6, .length = 7}
+#endif
+		    }
+};
+
+/*
+** We treat the OOB for a 2K page as if it were 4 512 byte oobs,
+** except the BI is at byte 0.
+*/
+static struct nand_ecclayout nand_hw_eccoob_2048 = {
+	/* Reserve 0 as BI indicator */
+	.oobfree = {
+#if (NAND_ECC_NUM_BYTES > 10)
+		    {.offset = 1, .length = 2},
+#elif (NAND_ECC_NUM_BYTES > 7)
+		    {.offset = 1, .length = 5},
+		    {.offset = 16, .length = 6},
+		    {.offset = 32, .length = 6},
+		    {.offset = 48, .length = 6}
+#else
+		    {.offset = 1, .length = 8},
+		    {.offset = 16, .length = 9},
+		    {.offset = 32, .length = 9},
+		    {.offset = 48, .length = 9}
+#endif
+		    }
+};
+
+/* We treat the OOB for a 4K page as if it were 8 512 byte oobs,
+ * except the BI is at byte 0. */
+static struct nand_ecclayout nand_hw_eccoob_4096 = {
+	/* Reserve 0 as BI indicator */
+	.oobfree = {
+#if (NAND_ECC_NUM_BYTES > 10)
+		    {.offset = 1, .length = 2},
+		    {.offset = 16, .length = 3},
+		    {.offset = 32, .length = 3},
+		    {.offset = 48, .length = 3},
+		    {.offset = 64, .length = 3},
+		    {.offset = 80, .length = 3},
+		    {.offset = 96, .length = 3},
+		    {.offset = 112, .length = 3}
+#else
+		    {.offset = 1, .length = 5},
+		    {.offset = 16, .length = 6},
+		    {.offset = 32, .length = 6},
+		    {.offset = 48, .length = 6},
+		    {.offset = 64, .length = 6},
+		    {.offset = 80, .length = 6},
+		    {.offset = 96, .length = 6},
+		    {.offset = 112, .length = 6}
+#endif
+		    }
+};
+
+/* ---- Private Functions ------------------------------------------------ */
+/* ==== Public Functions ================================================= */
+
+/****************************************************************************
+*
+*  bcm_umi_bch_read_page_hwecc - hardware ecc based page read function
+*  @mtd:	mtd info structure
+*  @chip:	nand chip info structure
+*  @buf:	buffer to store read data
+*
+***************************************************************************/
+static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd,
+				       struct nand_chip *chip, uint8_t * buf,
+						 int page)
+{
+	int sectorIdx = 0;
+	int eccsize = chip->ecc.size;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *datap = buf;
+	uint8_t eccCalc[NAND_ECC_NUM_BYTES];
+	int sectorOobSize = mtd->oobsize / eccsteps;
+	int stat;
+
+	for (sectorIdx = 0; sectorIdx < eccsteps;
+			sectorIdx++, datap += eccsize) {
+		if (sectorIdx > 0) {
+			/* Seek to page location within sector */
+			chip->cmdfunc(mtd, NAND_CMD_RNDOUT, sectorIdx * eccsize,
+				      -1);
+		}
+
+		/* Enable hardware ECC before reading the buf */
+		nand_bcm_umi_bch_enable_read_hwecc();
+
+		/* Read in data */
+		bcm_umi_nand_read_buf(mtd, datap, eccsize);
+
+		/* Pause hardware ECC after reading the buf */
+		nand_bcm_umi_bch_pause_read_ecc_calc();
+
+		/* Read the OOB ECC */
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
+			      mtd->writesize + sectorIdx * sectorOobSize, -1);
+		nand_bcm_umi_bch_read_oobEcc(mtd->writesize, eccCalc,
+					     NAND_ECC_NUM_BYTES,
+					     chip->oob_poi +
+					     sectorIdx * sectorOobSize);
+
+		/* Correct any ECC detected errors */
+		stat =
+		    nand_bcm_umi_bch_correct_page(datap, eccCalc,
+						  NAND_ECC_NUM_BYTES);
+
+		/* Update Stats */
+		if (stat < 0) {
+#if defined(NAND_BCM_UMI_DEBUG)
+			printk(KERN_WARNING "%s uncorr_err sectorIdx=%d\n",
+			       __func__, sectorIdx);
+			printk(KERN_WARNING
+			       "%s data %02x %02x %02x %02x "
+					 "%02x %02x %02x %02x\n",
+			       __func__, datap[0], datap[1], datap[2], datap[3],
+			       datap[4], datap[5], datap[6], datap[7]);
+			printk(KERN_WARNING
+			       "%s ecc  %02x %02x %02x %02x "
+					 "%02x %02x %02x %02x %02x %02x "
+					 "%02x %02x %02x\n",
+			       __func__, eccCalc[0], eccCalc[1], eccCalc[2],
+			       eccCalc[3], eccCalc[4], eccCalc[5], eccCalc[6],
+			       eccCalc[7], eccCalc[8], eccCalc[9], eccCalc[10],
+			       eccCalc[11], eccCalc[12]);
+			BUG();
+#endif
+			mtd->ecc_stats.failed++;
+		} else {
+#if defined(NAND_BCM_UMI_DEBUG)
+			if (stat > 0) {
+				printk(KERN_INFO
+				       "%s %d correctable_errors detected\n",
+				       __func__, stat);
+			}
+#endif
+			mtd->ecc_stats.corrected += stat;
+		}
+	}
+	return 0;
+}
+
+/****************************************************************************
+*
+*  bcm_umi_bch_write_page_hwecc - hardware ecc based page write function
+*  @mtd:	mtd info structure
+*  @chip:	nand chip info structure
+*  @buf:	data buffer
+*
+***************************************************************************/
+static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd,
+	struct nand_chip *chip, const uint8_t *buf)
+{
+	int sectorIdx = 0;
+	int eccsize = chip->ecc.size;
+	int eccsteps = chip->ecc.steps;
+	const uint8_t *datap = buf;
+	uint8_t *oobp = chip->oob_poi;
+	int sectorOobSize = mtd->oobsize / eccsteps;
+
+	for (sectorIdx = 0; sectorIdx < eccsteps;
+	     sectorIdx++, datap += eccsize, oobp += sectorOobSize) {
+		/* Enable hardware ECC before writing the buf */
+		nand_bcm_umi_bch_enable_write_hwecc();
+		bcm_umi_nand_write_buf(mtd, datap, eccsize);
+		nand_bcm_umi_bch_write_oobEcc(mtd->writesize, oobp,
+					      NAND_ECC_NUM_BYTES);
+	}
+
+	bcm_umi_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
new file mode 100644
index 0000000..087bcd7
--- /dev/null
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -0,0 +1,581 @@
+/*****************************************************************************
+* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/* ---- Include Files ---------------------------------------------------- */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/mach-types.h>
+#include <asm/system.h>
+
+#include <mach/reg_nand.h>
+#include <mach/reg_umi.h>
+
+#include "nand_bcm_umi.h"
+
+#include <mach/memory_settings.h>
+
+#define USE_DMA 1
+#include <mach/dma.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+
+/* ---- External Variable Declarations ----------------------------------- */
+/* ---- External Function Prototypes ------------------------------------- */
+/* ---- Public Variables ------------------------------------------------- */
+/* ---- Private Constants and Types -------------------------------------- */
+static const __devinitconst char gBanner[] = KERN_INFO \
+	"BCM UMI MTD NAND Driver: 1.00\n";
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+#if NAND_ECC_BCH
+static uint8_t scan_ff_pattern[] = { 0xff };
+
+static struct nand_bbt_descr largepage_bbt = {
+	.options = 0,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern
+};
+#endif
+
+/*
+** Preallocate a buffer to avoid having to do this every dma operation.
+** This is the size of the preallocated coherent DMA buffer.
+*/
+#if USE_DMA
+#define DMA_MIN_BUFLEN	512
+#define DMA_MAX_BUFLEN	PAGE_SIZE
+#define USE_DIRECT_IO(len)	(((len) < DMA_MIN_BUFLEN) || \
+	((len) > DMA_MAX_BUFLEN))
+
+/*
+ * The current NAND data space goes from 0x80001900 to 0x80001FFF,
+ * which is only 0x700 = 1792 bytes long. This is too small for 2K, 4K page
+ * size NAND flash. Need to break the DMA down to multiple 1Ks.
+ *
+ * Need to make sure REG_NAND_DATA_PADDR + DMA_MAX_LEN < 0x80002000
+ */
+#define DMA_MAX_LEN             1024
+
+#else /* !USE_DMA */
+#define DMA_MIN_BUFLEN          0
+#define DMA_MAX_BUFLEN          0
+#define USE_DIRECT_IO(len)      1
+#endif
+/* ---- Private Function Prototypes -------------------------------------- */
+static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len);
+static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
+				   int len);
+
+/* ---- Private Variables ------------------------------------------------ */
+static struct mtd_info *board_mtd;
+static void __iomem *bcm_umi_io_base;
+static void *virtPtr;
+static dma_addr_t physPtr;
+static struct completion nand_comp;
+
+/* ---- Private Functions ------------------------------------------------ */
+#if NAND_ECC_BCH
+#include "bcm_umi_bch.c"
+#else
+#include "bcm_umi_hamming.c"
+#endif
+
+#if USE_DMA
+
+/* Handler called when the DMA finishes. */
+static void nand_dma_handler(DMA_Device_t dev, int reason, void *userData)
+{
+	complete(&nand_comp);
+}
+
+static int nand_dma_init(void)
+{
+	int rc;
+
+	rc = dma_set_device_handler(DMA_DEVICE_NAND_MEM_TO_MEM,
+		nand_dma_handler, NULL);
+	if (rc != 0) {
+		printk(KERN_ERR "dma_set_device_handler failed: %d\n", rc);
+		return rc;
+	}
+
+	virtPtr =
+	    dma_alloc_coherent(NULL, DMA_MAX_BUFLEN, &physPtr, GFP_KERNEL);
+	if (virtPtr == NULL) {
+		printk(KERN_ERR "NAND - Failed to allocate memory for DMA buffer\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void nand_dma_term(void)
+{
+	if (virtPtr != NULL)
+		dma_free_coherent(NULL, DMA_MAX_BUFLEN, virtPtr, physPtr);
+}
+
+static void nand_dma_read(void *buf, int len)
+{
+	int offset = 0;
+	int tmp_len = 0;
+	int len_left = len;
+	DMA_Handle_t hndl;
+
+	if (virtPtr == NULL)
+		panic("nand_dma_read: virtPtr == NULL\n");
+
+	if ((void *)physPtr == NULL)
+		panic("nand_dma_read: physPtr == NULL\n");
+
+	hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
+	if (hndl < 0) {
+		printk(KERN_ERR
+		       "nand_dma_read: unable to allocate dma channel: %d\n",
+		       (int)hndl);
+		panic("\n");
+	}
+
+	while (len_left > 0) {
+		if (len_left > DMA_MAX_LEN) {
+			tmp_len = DMA_MAX_LEN;
+			len_left -= DMA_MAX_LEN;
+		} else {
+			tmp_len = len_left;
+			len_left = 0;
+		}
+
+		init_completion(&nand_comp);
+		dma_transfer_mem_to_mem(hndl, REG_NAND_DATA_PADDR,
+					physPtr + offset, tmp_len);
+		wait_for_completion(&nand_comp);
+
+		offset += tmp_len;
+	}
+
+	dma_free_channel(hndl);
+
+	if (buf != NULL)
+		memcpy(buf, virtPtr, len);
+}
+
+static void nand_dma_write(const void *buf, int len)
+{
+	int offset = 0;
+	int tmp_len = 0;
+	int len_left = len;
+	DMA_Handle_t hndl;
+
+	if (buf == NULL)
+		panic("nand_dma_write: buf == NULL\n");
+
+	if (virtPtr == NULL)
+		panic("nand_dma_write: virtPtr == NULL\n");
+
+	if ((void *)physPtr == NULL)
+		panic("nand_dma_write: physPtr == NULL\n");
+
+	memcpy(virtPtr, buf, len);
+
+
+	hndl = dma_request_channel(DMA_DEVICE_NAND_MEM_TO_MEM);
+	if (hndl < 0) {
+		printk(KERN_ERR
+		       "nand_dma_write: unable to allocate dma channel: %d\n",
+		       (int)hndl);
+		panic("\n");
+	}
+
+	while (len_left > 0) {
+		if (len_left > DMA_MAX_LEN) {
+			tmp_len = DMA_MAX_LEN;
+			len_left -= DMA_MAX_LEN;
+		} else {
+			tmp_len = len_left;
+			len_left = 0;
+		}
+
+		init_completion(&nand_comp);
+		dma_transfer_mem_to_mem(hndl, physPtr + offset,
+					REG_NAND_DATA_PADDR, tmp_len);
+		wait_for_completion(&nand_comp);
+
+		offset += tmp_len;
+	}
+
+	dma_free_channel(hndl);
+}
+
+#endif
+
+static int nand_dev_ready(struct mtd_info *mtd)
+{
+	return nand_bcm_umi_dev_ready();
+}
+
+/****************************************************************************
+*
+*  bcm_umi_nand_inithw
+*
+*   This routine does the necessary hardware (board-specific)
+*   initializations.  This includes setting up the timings, etc.
+*
+***************************************************************************/
+int bcm_umi_nand_inithw(void)
+{
+	/* Configure nand timing parameters */
+	REG_UMI_NAND_TCR &= ~0x7ffff;
+	REG_UMI_NAND_TCR |= HW_CFG_NAND_TCR;
+
+#if !defined(CONFIG_MTD_NAND_BCM_UMI_HWCS)
+	/* enable software control of CS */
+	REG_UMI_NAND_TCR |= REG_UMI_NAND_TCR_CS_SWCTRL;
+#endif
+
+	/* keep NAND chip select asserted */
+	REG_UMI_NAND_RCSR |= REG_UMI_NAND_RCSR_CS_ASSERTED;
+
+	REG_UMI_NAND_TCR &= ~REG_UMI_NAND_TCR_WORD16;
+	/* enable writes to flash */
+	REG_UMI_MMD_ICR |= REG_UMI_MMD_ICR_FLASH_WP;
+
+	writel(NAND_CMD_RESET, bcm_umi_io_base + REG_NAND_CMD_OFFSET);
+	nand_bcm_umi_wait_till_ready();
+
+#if NAND_ECC_BCH
+	nand_bcm_umi_bch_config_ecc(NAND_ECC_NUM_BYTES);
+#endif
+
+	return 0;
+}
+
+/* Used to turn latch the proper register for access. */
+static void bcm_umi_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+				   unsigned int ctrl)
+{
+	/* send command to hardware */
+	struct nand_chip *chip = mtd->priv;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		if (ctrl & NAND_CLE) {
+			chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_CMD_OFFSET;
+			goto CMD;
+		}
+		if (ctrl & NAND_ALE) {
+			chip->IO_ADDR_W =
+			    bcm_umi_io_base + REG_NAND_ADDR_OFFSET;
+			goto CMD;
+		}
+		chip->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
+	}
+
+CMD:
+	/* Send command to chip directly */
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
+}
+
+static void bcm_umi_nand_write_buf(struct mtd_info *mtd, const u_char * buf,
+				   int len)
+{
+	if (USE_DIRECT_IO(len)) {
+		/* Do it the old way if the buffer is small or too large.
+		 * Probably quicker than starting and checking dma. */
+		int i;
+		struct nand_chip *this = mtd->priv;
+
+		for (i = 0; i < len; i++)
+			writeb(buf[i], this->IO_ADDR_W);
+	}
+#if USE_DMA
+	else
+		nand_dma_write(buf, len);
+#endif
+}
+
+static void bcm_umi_nand_read_buf(struct mtd_info *mtd, u_char * buf, int len)
+{
+	if (USE_DIRECT_IO(len)) {
+		int i;
+		struct nand_chip *this = mtd->priv;
+
+		for (i = 0; i < len; i++)
+			buf[i] = readb(this->IO_ADDR_R);
+	}
+#if USE_DMA
+	else
+		nand_dma_read(buf, len);
+#endif
+}
+
+static uint8_t readbackbuf[NAND_MAX_PAGESIZE];
+static int bcm_umi_nand_verify_buf(struct mtd_info *mtd, const u_char * buf,
+				   int len)
+{
+	/*
+	 * Try to readback page with ECC correction. This is necessary
+	 * for MLC parts which may have permanently stuck bits.
+	 */
+	struct nand_chip *chip = mtd->priv;
+	int ret = chip->ecc.read_page(mtd, chip, readbackbuf, 0);
+	if (ret < 0)
+		return -EFAULT;
+	else {
+		if (memcmp(readbackbuf, buf, len) == 0)
+			return 0;
+
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
+{
+	struct nand_chip *this;
+	struct resource *r;
+	int err = 0;
+
+	printk(gBanner);
+
+	/* Allocate memory for MTD device structure and private data */
+	board_mtd =
+	    kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
+		    GFP_KERNEL);
+	if (!board_mtd) {
+		printk(KERN_WARNING
+		       "Unable to allocate NAND MTD device structure.\n");
+		return -ENOMEM;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!r)
+		return -ENXIO;
+
+	/* map physical adress */
+	bcm_umi_io_base = ioremap(r->start, r->end - r->start + 1);
+
+	if (!bcm_umi_io_base) {
+		printk(KERN_ERR "ioremap to access BCM UMI NAND chip failed\n");
+		kfree(board_mtd);
+		return -EIO;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *)(&board_mtd[1]);
+
+	/* Initialize structures */
+	memset((char *)board_mtd, 0, sizeof(struct mtd_info));
+	memset((char *)this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	board_mtd->priv = this;
+
+	/* Initialize the NAND hardware.  */
+	if (bcm_umi_nand_inithw() < 0) {
+		printk(KERN_ERR "BCM UMI NAND chip could not be initialized\n");
+		iounmap(bcm_umi_io_base);
+		kfree(board_mtd);
+		return -EIO;
+	}
+
+	/* Set address of NAND IO lines */
+	this->IO_ADDR_W = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
+	this->IO_ADDR_R = bcm_umi_io_base + REG_NAND_DATA8_OFFSET;
+
+	/* Set command delay time, see datasheet for correct value */
+	this->chip_delay = 0;
+	/* Assign the device ready function, if available */
+	this->dev_ready = nand_dev_ready;
+	this->options = 0;
+
+	this->write_buf = bcm_umi_nand_write_buf;
+	this->read_buf = bcm_umi_nand_read_buf;
+	this->verify_buf = bcm_umi_nand_verify_buf;
+
+	this->cmd_ctrl = bcm_umi_nand_hwcontrol;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 512;
+	this->ecc.bytes = NAND_ECC_NUM_BYTES;
+#if NAND_ECC_BCH
+	this->ecc.read_page = bcm_umi_bch_read_page_hwecc;
+	this->ecc.write_page = bcm_umi_bch_write_page_hwecc;
+#else
+	this->ecc.correct = nand_correct_data512;
+	this->ecc.calculate = bcm_umi_hamming_get_hw_ecc;
+	this->ecc.hwctl = bcm_umi_hamming_enable_hwecc;
+#endif
+
+#if USE_DMA
+	err = nand_dma_init();
+	if (err != 0)
+		return err;
+#endif
+
+	/* Figure out the size of the device that we have.
+	 * We need to do this to figure out which ECC
+	 * layout we'll be using.
+	 */
+
+	err = nand_scan_ident(board_mtd, 1);
+	if (err) {
+		printk(KERN_ERR "nand_scan failed: %d\n", err);
+		iounmap(bcm_umi_io_base);
+		kfree(board_mtd);
+		return err;
+	}
+
+	/* Now that we know the nand size, we can setup the ECC layout */
+
+	switch (board_mtd->writesize) {	/* writesize is the pagesize */
+	case 4096:
+		this->ecc.layout = &nand_hw_eccoob_4096;
+		break;
+	case 2048:
+		this->ecc.layout = &nand_hw_eccoob_2048;
+		break;
+	case 512:
+		this->ecc.layout = &nand_hw_eccoob_512;
+		break;
+	default:
+		{
+			printk(KERN_ERR "NAND - Unrecognized pagesize: %d\n",
+					 board_mtd->writesize);
+			return -EINVAL;
+		}
+	}
+
+#if NAND_ECC_BCH
+	if (board_mtd->writesize > 512) {
+		if (this->options & NAND_USE_FLASH_BBT)
+			largepage_bbt.options = NAND_BBT_SCAN2NDPAGE;
+		this->badblock_pattern = &largepage_bbt;
+	}
+#endif
+
+	/* Now finish off the scan, now that ecc.layout has been initialized. */
+
+	err = nand_scan_tail(board_mtd);
+	if (err) {
+		printk(KERN_ERR "nand_scan failed: %d\n", err);
+		iounmap(bcm_umi_io_base);
+		kfree(board_mtd);
+		return err;
+	}
+
+	/* Register the partitions */
+	{
+		int nr_partitions;
+		struct mtd_partition *partition_info;
+
+		board_mtd->name = "bcm_umi-nand";
+		nr_partitions =
+		    parse_mtd_partitions(board_mtd, part_probes,
+					 &partition_info, 0);
+
+		if (nr_partitions <= 0) {
+			printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
+			       nr_partitions);
+			iounmap(bcm_umi_io_base);
+			kfree(board_mtd);
+			return -EIO;
+		}
+		add_mtd_partitions(board_mtd, partition_info, nr_partitions);
+	}
+
+	/* Return happy */
+	return 0;
+}
+
+static int bcm_umi_nand_remove(struct platform_device *pdev)
+{
+#if USE_DMA
+	nand_dma_term();
+#endif
+
+	/* Release resources, unregister device */
+	nand_release(board_mtd);
+
+	/* unmap physical adress */
+	iounmap(bcm_umi_io_base);
+
+	/* Free the MTD device structure */
+	kfree(board_mtd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bcm_umi_nand_suspend(struct platform_device *pdev,
+				pm_message_t state)
+{
+	printk(KERN_ERR "MTD NAND suspend is being called\n");
+	return 0;
+}
+
+static int bcm_umi_nand_resume(struct platform_device *pdev)
+{
+	printk(KERN_ERR "MTD NAND resume is being called\n");
+	return 0;
+}
+#else
+#define bcm_umi_nand_suspend   NULL
+#define bcm_umi_nand_resume    NULL
+#endif
+
+static struct platform_driver nand_driver = {
+	.driver = {
+		   .name = "bcm-nand",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = bcm_umi_nand_probe,
+	.remove = bcm_umi_nand_remove,
+	.suspend = bcm_umi_nand_suspend,
+	.resume = bcm_umi_nand_resume,
+};
+
+static int __init nand_init(void)
+{
+	return platform_driver_register(&nand_driver);
+}
+
+static void __exit nand_exit(void)
+{
+	platform_driver_unregister(&nand_driver);
+}
+
+module_init(nand_init);
+module_exit(nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("BCM UMI MTD NAND driver");
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index f13f5b9..fe3eba8 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -591,6 +591,8 @@
 
 	/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
 	info->chip.options	= pdata->options;
+	info->chip.bbt_td	= pdata->bbt_td;
+	info->chip.bbt_md	= pdata->bbt_md;
 
 	info->ioaddr		= (uint32_t __force) vaddr;
 
@@ -599,7 +601,7 @@
 	info->mask_chipsel	= pdata->mask_chipsel;
 
 	/* use nandboot-capable ALE/CLE masks by default */
-	info->mask_ale		= pdata->mask_cle ? : MASK_ALE;
+	info->mask_ale		= pdata->mask_ale ? : MASK_ALE;
 	info->mask_cle		= pdata->mask_cle ? : MASK_CLE;
 
 	/* Set address of hardware control function */
diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c
deleted file mode 100644
index 72446fb..0000000
--- a/drivers/mtd/nand/excite_nandflash.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-*  Copyright (C) 2005 - 2007 by Basler Vision Technologies AG
-*  Author: Thomas Koeller <thomas.koeller.qbaslerweb.com>
-*  Original code by Thies Moeller <thies.moeller@baslerweb.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/rm9k-ocd.h>
-
-#include <excite_nandflash.h>
-
-#define EXCITE_NANDFLASH_VERSION "0.1"
-
-/* I/O register offsets */
-#define EXCITE_NANDFLASH_DATA_BYTE   0x00
-#define EXCITE_NANDFLASH_STATUS_BYTE 0x0c
-#define EXCITE_NANDFLASH_ADDR_BYTE   0x10
-#define EXCITE_NANDFLASH_CMD_BYTE    0x14
-
-/* prefix for debug output */
-static const char module_id[] = "excite_nandflash";
-
-/*
- * partition definition
- */
-static const struct mtd_partition partition_info[] = {
-	{
-		.name = "eXcite RootFS",
-		.offset = 0,
-		.size = MTDPART_SIZ_FULL
-	}
-};
-
-static inline const struct resource *
-excite_nand_get_resource(struct platform_device *d, unsigned long flags,
-			 const char *basename)
-{
-	char buf[80];
-
-	if (snprintf(buf, sizeof buf, "%s_%u", basename, d->id) >= sizeof buf)
-		return NULL;
-	return platform_get_resource_byname(d, flags, buf);
-}
-
-static inline void __iomem *
-excite_nand_map_regs(struct platform_device *d, const char *basename)
-{
-	void *result = NULL;
-	const struct resource *const r =
-	    excite_nand_get_resource(d, IORESOURCE_MEM, basename);
-
-	if (r)
-		result = ioremap_nocache(r->start, r->end + 1 - r->start);
-	return result;
-}
-
-/* controller and mtd information */
-struct excite_nand_drvdata {
-	struct mtd_info board_mtd;
-	struct nand_chip board_chip;
-	void __iomem *regs;
-	void __iomem *tgt;
-};
-
-/* Control function */
-static void excite_nand_control(struct mtd_info *mtd, int cmd,
-				       unsigned int ctrl)
-{
-	struct excite_nand_drvdata * const d =
-	    container_of(mtd, struct excite_nand_drvdata, board_mtd);
-
-	switch (ctrl) {
-	case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
-		d->tgt = d->regs + EXCITE_NANDFLASH_CMD_BYTE;
-		break;
-	case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
-		d->tgt = d->regs + EXCITE_NANDFLASH_ADDR_BYTE;
-		break;
-	case NAND_CTRL_CHANGE | NAND_NCE:
-		d->tgt = d->regs + EXCITE_NANDFLASH_DATA_BYTE;
-		break;
-	}
-
-	if (cmd != NAND_CMD_NONE)
-		__raw_writeb(cmd, d->tgt);
-}
-
-/* Return 0 if flash is busy, 1 if ready */
-static int excite_nand_devready(struct mtd_info *mtd)
-{
-	struct excite_nand_drvdata * const drvdata =
-	    container_of(mtd, struct excite_nand_drvdata, board_mtd);
-
-	return __raw_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS_BYTE);
-}
-
-/*
- * Called by device layer to remove the driver.
- * The binding to the mtd and all allocated
- * resources are released.
- */
-static int __exit excite_nand_remove(struct platform_device *dev)
-{
-	struct excite_nand_drvdata * const this = platform_get_drvdata(dev);
-
-	platform_set_drvdata(dev, NULL);
-
-	if (unlikely(!this)) {
-		printk(KERN_ERR "%s: called %s without private data!!",
-		       module_id, __func__);
-		return -EINVAL;
-	}
-
-	/* first thing we need to do is release our mtd
-	 * then go through freeing the resource used
-	 */
-	nand_release(&this->board_mtd);
-
-	/* free the common resources */
-	iounmap(this->regs);
-	kfree(this);
-
-	DEBUG(MTD_DEBUG_LEVEL1, "%s: removed\n", module_id);
-	return 0;
-}
-
-/*
- * Called by device layer when it finds a device matching
- * one our driver can handle. This code checks to see if
- * it can allocate all necessary resources then calls the
- * nand layer to look for devices.
-*/
-static int __init excite_nand_probe(struct platform_device *pdev)
-{
-	struct excite_nand_drvdata *drvdata;	/* private driver data */
-	struct nand_chip *board_chip;	/* private flash chip data */
-	struct mtd_info *board_mtd;	/* mtd info for this board */
-	int scan_res;
-
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (unlikely(!drvdata)) {
-		printk(KERN_ERR "%s: no memory for drvdata\n",
-		       module_id);
-		return -ENOMEM;
-	}
-
-	/* bind private data into driver */
-	platform_set_drvdata(pdev, drvdata);
-
-	/* allocate and map the resource */
-	drvdata->regs =
-		excite_nand_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
-
-	if (unlikely(!drvdata->regs)) {
-		printk(KERN_ERR "%s: cannot reserve register region\n",
-		       module_id);
-		kfree(drvdata);
-		return -ENXIO;
-	}
-	
-	drvdata->tgt = drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
-
-	/* initialise our chip */
-	board_chip = &drvdata->board_chip;
-	board_chip->IO_ADDR_R = board_chip->IO_ADDR_W =
-		drvdata->regs + EXCITE_NANDFLASH_DATA_BYTE;
-	board_chip->cmd_ctrl = excite_nand_control;
-	board_chip->dev_ready = excite_nand_devready;
-	board_chip->chip_delay = 25;
-	board_chip->ecc.mode = NAND_ECC_SOFT;
-
-	/* link chip to mtd */
-	board_mtd = &drvdata->board_mtd;
-	board_mtd->priv = board_chip;
-
-	DEBUG(MTD_DEBUG_LEVEL2, "%s: device scan\n", module_id);
-	scan_res = nand_scan(&drvdata->board_mtd, 1);
-
-	if (likely(!scan_res)) {
-		DEBUG(MTD_DEBUG_LEVEL2, "%s: register partitions\n", module_id);
-		add_mtd_partitions(&drvdata->board_mtd, partition_info,
-				   ARRAY_SIZE(partition_info));
-	} else {
-		iounmap(drvdata->regs);
-		kfree(drvdata);
-		printk(KERN_ERR "%s: device scan failed\n", module_id);
-		return -EIO;
-	}
-	return 0;
-}
-
-static struct platform_driver excite_nand_driver = {
-	.driver = {
-		.name = "excite_nand",
-		.owner		= THIS_MODULE,
-	},
-	.probe = excite_nand_probe,
-	.remove = __devexit_p(excite_nand_remove)
-};
-
-static int __init excite_nand_init(void)
-{
-	pr_info("Basler eXcite nand flash driver Version "
-		EXCITE_NANDFLASH_VERSION "\n");
-	return platform_driver_register(&excite_nand_driver);
-}
-
-static void __exit excite_nand_exit(void)
-{
-	platform_driver_unregister(&excite_nand_driver);
-}
-
-module_init(excite_nand_init);
-module_exit(excite_nand_exit);
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(EXCITE_NANDFLASH_VERSION)
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index ddd37d2..ae30fb6 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -237,12 +237,15 @@
 
 	ctrl->use_mdr = 0;
 
-	dev_vdbg(ctrl->dev,
-	         "fsl_elbc_run_command: stat=%08x mdr=%08x fmr=%08x\n",
-	         ctrl->status, ctrl->mdr, in_be32(&lbc->fmr));
+	if (ctrl->status != LTESR_CC) {
+		dev_info(ctrl->dev,
+		         "command failed: fir %x fcr %x status %x mdr %x\n",
+		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
+		         ctrl->status, ctrl->mdr);
+		return -EIO;
+	}
 
-	/* returns 0 on success otherwise non-zero) */
-	return ctrl->status == LTESR_CC ? 0 : -EIO;
+	return 0;
 }
 
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
@@ -253,17 +256,17 @@
 
 	if (priv->page_size) {
 		out_be32(&lbc->fir,
-		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
-		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+		         (FIR_OP_CM1 << FIR_OP3_SHIFT) |
 		         (FIR_OP_RBW << FIR_OP4_SHIFT));
 
 		out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
 		                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
 	} else {
 		out_be32(&lbc->fir,
-		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
 		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
 		         (FIR_OP_RBW << FIR_OP3_SHIFT));
@@ -332,7 +335,7 @@
 	case NAND_CMD_READID:
 		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
 
-		out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
 		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
 		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
@@ -359,16 +362,20 @@
 		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
 
 		out_be32(&lbc->fir,
-		         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		         (FIR_OP_PA  << FIR_OP1_SHIFT) |
-		         (FIR_OP_CM1 << FIR_OP2_SHIFT));
+		         (FIR_OP_CM2 << FIR_OP2_SHIFT) |
+		         (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+		         (FIR_OP_RS  << FIR_OP4_SHIFT));
 
 		out_be32(&lbc->fcr,
 		         (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
-		         (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+		         (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
+		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
 
 		out_be32(&lbc->fbcr, 0);
 		ctrl->read_bytes = 0;
+		ctrl->use_mdr = 1;
 
 		fsl_elbc_run_command(mtd);
 		return;
@@ -383,40 +390,41 @@
 
 		ctrl->column = column;
 		ctrl->oob = 0;
+		ctrl->use_mdr = 1;
+
+		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
+		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
+		      (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
 
 		if (priv->page_size) {
-			fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) |
-			      (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
-
 			out_be32(&lbc->fir,
-			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+			         (FIR_OP_CM2 << FIR_OP0_SHIFT) |
 			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
 			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
 			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
-			         (FIR_OP_CW1 << FIR_OP4_SHIFT));
+			         (FIR_OP_CM3 << FIR_OP4_SHIFT) |
+			         (FIR_OP_CW1 << FIR_OP5_SHIFT) |
+			         (FIR_OP_RS  << FIR_OP6_SHIFT));
 		} else {
-			fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
-			      (NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
-
 			out_be32(&lbc->fir,
-			         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+			         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 			         (FIR_OP_CM2 << FIR_OP1_SHIFT) |
 			         (FIR_OP_CA  << FIR_OP2_SHIFT) |
 			         (FIR_OP_PA  << FIR_OP3_SHIFT) |
 			         (FIR_OP_WB  << FIR_OP4_SHIFT) |
-			         (FIR_OP_CW1 << FIR_OP5_SHIFT));
+			         (FIR_OP_CM3 << FIR_OP5_SHIFT) |
+			         (FIR_OP_CW1 << FIR_OP6_SHIFT) |
+			         (FIR_OP_RS  << FIR_OP7_SHIFT));
 
 			if (column >= mtd->writesize) {
 				/* OOB area --> READOOB */
 				column -= mtd->writesize;
 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
 				ctrl->oob = 1;
-			} else if (column < 256) {
+			} else {
+				WARN_ON(column != 0);
 				/* First 256 bytes --> READ0 */
 				fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
-			} else {
-				/* Second 256 bytes --> READ1 */
-				fcr |= NAND_CMD_READ1 << FCR_CMD0_SHIFT;
 			}
 		}
 
@@ -628,22 +636,6 @@
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
-	if (ctrl->status != LTESR_CC)
-		return NAND_STATUS_FAIL;
-
-	/* Use READ_STATUS command, but wait for the device to be ready */
-	ctrl->use_mdr = 0;
-	out_be32(&lbc->fir,
-	         (FIR_OP_CW0 << FIR_OP0_SHIFT) |
-	         (FIR_OP_RBW << FIR_OP1_SHIFT));
-	out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
-	out_be32(&lbc->fbcr, 1);
-	set_addr(mtd, 0, 0, 0);
-	ctrl->read_bytes = 1;
-
-	fsl_elbc_run_command(mtd);
 
 	if (ctrl->status != LTESR_CC)
 		return NAND_STATUS_FAIL;
@@ -651,8 +643,7 @@
 	/* The chip always seems to report that it is
 	 * write-protected, even when it is not.
 	 */
-	setbits8(ctrl->addr, NAND_STATUS_WP);
-	return fsl_elbc_read_byte(mtd);
+	return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
@@ -946,6 +937,13 @@
 {
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
+	/*
+	 * NAND transactions can tie up the bus for a long time, so set the
+	 * bus timeout to max by clearing LBCR[BMT] (highest base counter
+	 * value) and setting LBCR[BMTPS] to the highest prescaler value.
+	 */
+	clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
+
 	/* clear event registers */
 	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
 	out_be32(&lbc->lteatr, 0);
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index d120cd8..071a60c 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -112,7 +112,7 @@
 
 	if (mchip_nr == -1) {
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
-	} else if (mchip_nr >= 0) {
+	} else if (mchip_nr >= 0 && mchip_nr < NAND_MAX_CHIPS) {
 		fun->mchip_number = mchip_nr;
 		chip->IO_ADDR_R = fun->io_base + fun->mchip_offsets[mchip_nr];
 		chip->IO_ADDR_W = chip->IO_ADDR_R;
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 65b26d5..45dec57 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -33,9 +33,13 @@
 
 #include <asm/mach/flash.h>
 #include <mach/mxc_nand.h>
+#include <mach/hardware.h>
 
 #define DRIVER_NAME "mxc_nand"
 
+#define nfc_is_v21()		(cpu_is_mx25() || cpu_is_mx35())
+#define nfc_is_v1()		(cpu_is_mx31() || cpu_is_mx27())
+
 /* Addresses for NFC registers */
 #define NFC_BUF_SIZE		0xE00
 #define NFC_BUF_ADDR		0xE04
@@ -46,24 +50,14 @@
 #define NFC_RSLTMAIN_AREA	0xE0E
 #define NFC_RSLTSPARE_AREA	0xE10
 #define NFC_WRPROT		0xE12
-#define NFC_UNLOCKSTART_BLKADDR	0xE14
-#define NFC_UNLOCKEND_BLKADDR	0xE16
+#define NFC_V1_UNLOCKSTART_BLKADDR	0xe14
+#define NFC_V1_UNLOCKEND_BLKADDR	0xe16
+#define NFC_V21_UNLOCKSTART_BLKADDR	0xe20
+#define NFC_V21_UNLOCKEND_BLKADDR	0xe22
 #define NFC_NF_WRPRST		0xE18
 #define NFC_CONFIG1		0xE1A
 #define NFC_CONFIG2		0xE1C
 
-/* Addresses for NFC RAM BUFFER Main area 0 */
-#define MAIN_AREA0		0x000
-#define MAIN_AREA1		0x200
-#define MAIN_AREA2		0x400
-#define MAIN_AREA3		0x600
-
-/* Addresses for NFC SPARE BUFFER Spare area 0 */
-#define SPARE_AREA0		0x800
-#define SPARE_AREA1		0x810
-#define SPARE_AREA2		0x820
-#define SPARE_AREA3		0x830
-
 /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
  * for Command operation */
 #define NFC_CMD            0x1
@@ -106,48 +100,66 @@
 	struct mtd_partition	*parts;
 	struct device		*dev;
 
+	void			*spare0;
+	void			*main_area0;
+	void			*main_area1;
+
+	void __iomem		*base;
 	void __iomem		*regs;
-	int			spare_only;
 	int			status_request;
-	int			pagesize_2k;
-	uint16_t		col_addr;
 	struct clk		*clk;
 	int			clk_act;
 	int			irq;
 
 	wait_queue_head_t	irq_waitq;
+
+	uint8_t			*data_buf;
+	unsigned int		buf_start;
+	int			spare_len;
 };
 
-/* Define delays in microsec for NAND device operations */
-#define TROP_US_DELAY   2000
-/* Macros to get byte and bit positions of ECC */
-#define COLPOS(x)  ((x) >> 3)
-#define BITPOS(x) ((x) & 0xf)
-
-/* Define single bit Error positions in Main & Spare area */
-#define MAIN_SINGLEBIT_ERROR 0x4
-#define SPARE_SINGLEBIT_ERROR 0x1
-
 /* OOB placement block for use with hardware ecc generation */
-static struct nand_ecclayout nand_hw_eccoob_8 = {
+static struct nand_ecclayout nandv1_hw_eccoob_smallpage = {
 	.eccbytes = 5,
 	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 5}, {11, 5}, }
+	.oobfree = {{0, 5}, {12, 4}, }
 };
 
-static struct nand_ecclayout nand_hw_eccoob_16 = {
-	.eccbytes = 5,
-	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 5}, {11, 5}, }
-};
-
-static struct nand_ecclayout nand_hw_eccoob_64 = {
+static struct nand_ecclayout nandv1_hw_eccoob_largepage = {
 	.eccbytes = 20,
 	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
 		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
 	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
 };
 
+/* OOB description for 512 byte pages with 16 byte OOB */
+static struct nand_ecclayout nandv2_hw_eccoob_smallpage = {
+	.eccbytes = 1 * 9,
+	.eccpos = {
+		 7,  8,  9, 10, 11, 12, 13, 14, 15
+	},
+	.oobfree = {
+		{.offset = 0, .length = 5}
+	}
+};
+
+/* OOB description for 2048 byte pages with 64 byte OOB */
+static struct nand_ecclayout nandv2_hw_eccoob_largepage = {
+	.eccbytes = 4 * 9,
+	.eccpos = {
+		 7,  8,  9, 10, 11, 12, 13, 14, 15,
+		23, 24, 25, 26, 27, 28, 29, 30, 31,
+		39, 40, 41, 42, 43, 44, 45, 46, 47,
+		55, 56, 57, 58, 59, 60, 61, 62, 63
+	},
+	.oobfree = {
+		{.offset = 2, .length = 4},
+		{.offset = 16, .length = 7},
+		{.offset = 32, .length = 7},
+		{.offset = 48, .length = 7}
+	}
+};
+
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
 #endif
@@ -170,10 +182,10 @@
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
-static void wait_op_done(struct mxc_nand_host *host, int max_retries,
-				uint16_t param, int useirq)
+static void wait_op_done(struct mxc_nand_host *host, int useirq)
 {
 	uint32_t tmp;
+	int max_retries = 2000;
 
 	if (useirq) {
 		if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
@@ -200,8 +212,8 @@
 			udelay(1);
 		}
 		if (max_retries < 0)
-			DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
-			      __func__, param);
+			DEBUG(MTD_DEBUG_LEVEL0, "%s: INT not set\n",
+			      __func__);
 	}
 }
 
@@ -215,7 +227,7 @@
 	writew(NFC_CMD, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, cmd, useirq);
+	wait_op_done(host, useirq);
 }
 
 /* This function sends an address (or partial address) to the
@@ -229,82 +241,47 @@
 	writew(NFC_ADDR, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, addr, islast);
+	wait_op_done(host, islast);
 }
 
-/* This function requests the NANDFC to initate the transfer
- * of data currently in the NANDFC RAM buffer to the NAND device. */
-static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
-			int spare_only)
+static void send_page(struct mtd_info *mtd, unsigned int ops)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int bufs, i;
 
-	/* NANDFC buffer 0 is used for page read/write */
-	writew(buf_id, host->regs + NFC_BUF_ADDR);
+	if (nfc_is_v1() && mtd->writesize > 512)
+		bufs = 4;
+	else
+		bufs = 1;
 
-	/* Configure spare or page+spare access */
-	if (!host->pagesize_2k) {
-		uint16_t config1 = readw(host->regs + NFC_CONFIG1);
-		if (spare_only)
-			config1 |= NFC_SP_EN;
-		else
-			config1 &= ~(NFC_SP_EN);
-		writew(config1, host->regs + NFC_CONFIG1);
+	for (i = 0; i < bufs; i++) {
+
+		/* NANDFC buffer 0 is used for page read/write */
+		writew(i, host->regs + NFC_BUF_ADDR);
+
+		writew(ops, host->regs + NFC_CONFIG2);
+
+		/* Wait for operation to complete */
+		wait_op_done(host, true);
 	}
-
-	writew(NFC_INPUT, host->regs + NFC_CONFIG2);
-
-	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, spare_only, true);
-}
-
-/* Requests NANDFC to initated the transfer of data from the
- * NAND device into in the NANDFC ram buffer. */
-static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
-		int spare_only)
-{
-	DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
-
-	/* NANDFC buffer 0 is used for page read/write */
-	writew(buf_id, host->regs + NFC_BUF_ADDR);
-
-	/* Configure spare or page+spare access */
-	if (!host->pagesize_2k) {
-		uint32_t config1 = readw(host->regs + NFC_CONFIG1);
-		if (spare_only)
-			config1 |= NFC_SP_EN;
-		else
-			config1 &= ~NFC_SP_EN;
-		writew(config1, host->regs + NFC_CONFIG1);
-	}
-
-	writew(NFC_OUTPUT, host->regs + NFC_CONFIG2);
-
-	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, spare_only, true);
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
 static void send_read_id(struct mxc_nand_host *host)
 {
 	struct nand_chip *this = &host->nand;
-	uint16_t tmp;
 
 	/* NANDFC buffer 0 is used for device ID output */
 	writew(0x0, host->regs + NFC_BUF_ADDR);
 
-	/* Read ID into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
-
 	writew(NFC_ID, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, 0, true);
+	wait_op_done(host, true);
 
 	if (this->options & NAND_BUSWIDTH_16) {
-		void __iomem *main_buf = host->regs + MAIN_AREA0;
+		void __iomem *main_buf = host->main_area0;
 		/* compress the ID info */
 		writeb(readb(main_buf + 2), main_buf + 1);
 		writeb(readb(main_buf + 4), main_buf + 2);
@@ -312,15 +289,16 @@
 		writeb(readb(main_buf + 8), main_buf + 4);
 		writeb(readb(main_buf + 10), main_buf + 5);
 	}
+	memcpy(host->data_buf, host->main_area0, 16);
 }
 
 /* This function requests the NANDFC to perform a read of the
  * NAND device status and returns the current status. */
 static uint16_t get_dev_status(struct mxc_nand_host *host)
 {
-	void __iomem *main_buf = host->regs + MAIN_AREA1;
+	void __iomem *main_buf = host->main_area1;
 	uint32_t store;
-	uint16_t ret, tmp;
+	uint16_t ret;
 	/* Issue status request to NAND device */
 
 	/* store the main area1 first word, later do recovery */
@@ -329,15 +307,10 @@
 	 * corruption of read/write buffer on status requests. */
 	writew(1, host->regs + NFC_BUF_ADDR);
 
-	/* Read status into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
-	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
-
 	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
 
 	/* Wait for operation to complete */
-	wait_op_done(host, TROP_US_DELAY, 0, true);
+	wait_op_done(host, true);
 
 	/* Status is placed in first word of main buffer */
 	/* get status, then recovery area 1 data */
@@ -397,32 +370,14 @@
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	uint8_t ret = 0;
-	uint16_t col, rd_word;
-	uint16_t __iomem *main_buf = host->regs + MAIN_AREA0;
-	uint16_t __iomem *spare_buf = host->regs + SPARE_AREA0;
+	uint8_t ret;
 
 	/* Check for status request */
 	if (host->status_request)
 		return get_dev_status(host) & 0xFF;
 
-	/* Get column for 16-bit access */
-	col = host->col_addr >> 1;
-
-	/* If we are accessing the spare region */
-	if (host->spare_only)
-		rd_word = readw(&spare_buf[col]);
-	else
-		rd_word = readw(&main_buf[col]);
-
-	/* Pick upper/lower byte of word from RAM buffer */
-	if (host->col_addr & 0x1)
-		ret = (rd_word >> 8) & 0xFF;
-	else
-		ret = rd_word & 0xFF;
-
-	/* Update saved column address */
-	host->col_addr++;
+	ret = *(uint8_t *)(host->data_buf + host->buf_start);
+	host->buf_start++;
 
 	return ret;
 }
@@ -431,33 +386,10 @@
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	uint16_t col, rd_word, ret;
-	uint16_t __iomem *p;
+	uint16_t ret;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
-
-	col = host->col_addr;
-	/* Adjust saved column address */
-	if (col < mtd->writesize && host->spare_only)
-		col += mtd->writesize;
-
-	if (col < mtd->writesize)
-		p = (host->regs + MAIN_AREA0) + (col >> 1);
-	else
-		p = (host->regs + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
-
-	if (col & 1) {
-		rd_word = readw(p);
-		ret = (rd_word >> 8) & 0xff;
-		rd_word = readw(&p[1]);
-		ret |= (rd_word << 8) & 0xff00;
-
-	} else
-		ret = readw(p);
-
-	/* Update saved column address */
-	host->col_addr = col + 2;
+	ret = *(uint16_t *)(host->data_buf + host->buf_start);
+	host->buf_start += 2;
 
 	return ret;
 }
@@ -470,94 +402,14 @@
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	int n, col, i = 0;
+	u16 col = host->buf_start;
+	int n = mtd->oobsize + mtd->writesize - col;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
-	      len);
+	n = min(n, len);
 
-	col = host->col_addr;
+	memcpy(host->data_buf + col, buf, n);
 
-	/* Adjust saved column address */
-	if (col < mtd->writesize && host->spare_only)
-		col += mtd->writesize;
-
-	n = mtd->writesize + mtd->oobsize - col;
-	n = min(len, n);
-
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
-
-	while (n) {
-		void __iomem *p;
-
-		if (col < mtd->writesize)
-			p = host->regs + MAIN_AREA0 + (col & ~3);
-		else
-			p = host->regs + SPARE_AREA0 -
-						mtd->writesize + (col & ~3);
-
-		DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
-		      __LINE__, p);
-
-		if (((col | (int)&buf[i]) & 3) || n < 16) {
-			uint32_t data = 0;
-
-			if (col & 3 || n < 4)
-				data = readl(p);
-
-			switch (col & 3) {
-			case 0:
-				if (n) {
-					data = (data & 0xffffff00) |
-					    (buf[i++] << 0);
-					n--;
-					col++;
-				}
-			case 1:
-				if (n) {
-					data = (data & 0xffff00ff) |
-					    (buf[i++] << 8);
-					n--;
-					col++;
-				}
-			case 2:
-				if (n) {
-					data = (data & 0xff00ffff) |
-					    (buf[i++] << 16);
-					n--;
-					col++;
-				}
-			case 3:
-				if (n) {
-					data = (data & 0x00ffffff) |
-					    (buf[i++] << 24);
-					n--;
-					col++;
-				}
-			}
-
-			writel(data, p);
-		} else {
-			int m = mtd->writesize - col;
-
-			if (col >= mtd->writesize)
-				m += mtd->oobsize;
-
-			m = min(n, m) & ~3;
-
-			DEBUG(MTD_DEBUG_LEVEL3,
-			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
-			      __func__,  __LINE__, n, m, i, col);
-
-			memcpy(p, &buf[i], m);
-			col += m;
-			i += m;
-			n -= m;
-		}
-	}
-	/* Update saved column address */
-	host->col_addr = col;
+	host->buf_start += n;
 }
 
 /* Read the data buffer from the NAND Flash. To read the data from NAND
@@ -568,75 +420,14 @@
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	int n, col, i = 0;
+	u16 col = host->buf_start;
+	int n = mtd->oobsize + mtd->writesize - col;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+	n = min(n, len);
 
-	col = host->col_addr;
+	memcpy(buf, host->data_buf + col, len);
 
-	/* Adjust saved column address */
-	if (col < mtd->writesize && host->spare_only)
-		col += mtd->writesize;
-
-	n = mtd->writesize + mtd->oobsize - col;
-	n = min(len, n);
-
-	while (n) {
-		void __iomem *p;
-
-		if (col < mtd->writesize)
-			p = host->regs + MAIN_AREA0 + (col & ~3);
-		else
-			p = host->regs + SPARE_AREA0 -
-					mtd->writesize + (col & ~3);
-
-		if (((col | (int)&buf[i]) & 3) || n < 16) {
-			uint32_t data;
-
-			data = readl(p);
-			switch (col & 3) {
-			case 0:
-				if (n) {
-					buf[i++] = (uint8_t) (data);
-					n--;
-					col++;
-				}
-			case 1:
-				if (n) {
-					buf[i++] = (uint8_t) (data >> 8);
-					n--;
-					col++;
-				}
-			case 2:
-				if (n) {
-					buf[i++] = (uint8_t) (data >> 16);
-					n--;
-					col++;
-				}
-			case 3:
-				if (n) {
-					buf[i++] = (uint8_t) (data >> 24);
-					n--;
-					col++;
-				}
-			}
-		} else {
-			int m = mtd->writesize - col;
-
-			if (col >= mtd->writesize)
-				m += mtd->oobsize;
-
-			m = min(n, m) & ~3;
-			memcpy(&buf[i], p, m);
-			col += m;
-			i += m;
-			n -= m;
-		}
-	}
-	/* Update saved column address */
-	host->col_addr = col;
-
+	host->buf_start += len;
 }
 
 /* Used by the upper layer to verify the data in NAND Flash
@@ -654,23 +445,6 @@
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
 
-#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
-	if (chip > 0) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "ERROR:  Illegal chip select (chip = %d)\n", chip);
-		return;
-	}
-
-	if (chip == -1) {
-		writew(readw(host->regs + NFC_CONFIG1) & ~NFC_CE,
-				host->regs + NFC_CONFIG1);
-		return;
-	}
-
-	writew(readw(host->regs + NFC_CONFIG1) | NFC_CE,
-			host->regs + NFC_CONFIG1);
-#endif
-
 	switch (chip) {
 	case -1:
 		/* Disable the NFC clock */
@@ -692,94 +466,40 @@
 	}
 }
 
-/* Used by the upper layer to write command to NAND Flash for
- * different operations to be carried out on NAND Flash */
-static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
-				int column, int page_addr)
+/*
+ * Function to transfer data to/from spare area.
+ */
+static void copy_spare(struct mtd_info *mtd, bool bfrom)
+{
+	struct nand_chip *this = mtd->priv;
+	struct mxc_nand_host *host = this->priv;
+	u16 i, j;
+	u16 n = mtd->writesize >> 9;
+	u8 *d = host->data_buf + mtd->writesize;
+	u8 *s = host->spare0;
+	u16 t = host->spare_len;
+
+	j = (mtd->oobsize / n >> 1) << 1;
+
+	if (bfrom) {
+		for (i = 0; i < n - 1; i++)
+			memcpy(d + i * j, s + i * t, j);
+
+		/* the last section */
+		memcpy(d + i * j, s + i * t, mtd->oobsize - i * j);
+	} else {
+		for (i = 0; i < n - 1; i++)
+			memcpy(&s[i * t], &d[i * j], j);
+
+		/* the last section */
+		memcpy(&s[i * t], &d[i * j], mtd->oobsize - i * j);
+	}
+}
+
+static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	int useirq = true;
-
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
-	      command, column, page_addr);
-
-	/* Reset command state information */
-	host->status_request = false;
-
-	/* Command pre-processing step */
-	switch (command) {
-
-	case NAND_CMD_STATUS:
-		host->col_addr = 0;
-		host->status_request = true;
-		break;
-
-	case NAND_CMD_READ0:
-		host->col_addr = column;
-		host->spare_only = false;
-		useirq = false;
-		break;
-
-	case NAND_CMD_READOOB:
-		host->col_addr = column;
-		host->spare_only = true;
-		useirq = false;
-		if (host->pagesize_2k)
-			command = NAND_CMD_READ0; /* only READ0 is valid */
-		break;
-
-	case NAND_CMD_SEQIN:
-		if (column >= mtd->writesize) {
-			/*
-			 * FIXME: before send SEQIN command for write OOB,
-			 * We must read one page out.
-			 * For K9F1GXX has no READ1 command to set current HW
-			 * pointer to spare area, we must write the whole page
-			 * including OOB together.
-			 */
-			if (host->pagesize_2k)
-				/* call ourself to read a page */
-				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
-						page_addr);
-
-			host->col_addr = column - mtd->writesize;
-			host->spare_only = true;
-
-			/* Set program pointer to spare region */
-			if (!host->pagesize_2k)
-				send_cmd(host, NAND_CMD_READOOB, false);
-		} else {
-			host->spare_only = false;
-			host->col_addr = column;
-
-			/* Set program pointer to page start */
-			if (!host->pagesize_2k)
-				send_cmd(host, NAND_CMD_READ0, false);
-		}
-		useirq = false;
-		break;
-
-	case NAND_CMD_PAGEPROG:
-		send_prog_page(host, 0, host->spare_only);
-
-		if (host->pagesize_2k) {
-			/* data in 4 areas datas */
-			send_prog_page(host, 1, host->spare_only);
-			send_prog_page(host, 2, host->spare_only);
-			send_prog_page(host, 3, host->spare_only);
-		}
-
-		break;
-
-	case NAND_CMD_ERASE1:
-		useirq = false;
-		break;
-	}
-
-	/* Write out the command to the device. */
-	send_cmd(host, command, useirq);
 
 	/* Write out column address, if necessary */
 	if (column != -1) {
@@ -791,7 +511,7 @@
 		 * the full page.
 		 */
 		send_addr(host, 0, page_addr == -1);
-		if (host->pagesize_2k)
+		if (mtd->writesize > 512)
 			/* another col addr cycle for 2k page */
 			send_addr(host, 0, false);
 	}
@@ -801,7 +521,7 @@
 		/* paddr_0 - p_addr_7 */
 		send_addr(host, (page_addr & 0xff), false);
 
-		if (host->pagesize_2k) {
+		if (mtd->writesize > 512) {
 			if (mtd->size >= 0x10000000) {
 				/* paddr_8 - paddr_15 */
 				send_addr(host, (page_addr >> 8) & 0xff, false);
@@ -820,52 +540,136 @@
 				send_addr(host, (page_addr >> 8) & 0xff, true);
 		}
 	}
+}
 
-	/* Command post-processing step */
+/* Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+
+	DEBUG(MTD_DEBUG_LEVEL3,
+	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      command, column, page_addr);
+
+	/* Reset command state information */
+	host->status_request = false;
+
+	/* Command pre-processing step */
 	switch (command) {
 
-	case NAND_CMD_RESET:
+	case NAND_CMD_STATUS:
+		host->buf_start = 0;
+		host->status_request = true;
+
+		send_cmd(host, command, true);
+		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
-	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		if (host->pagesize_2k) {
-			/* send read confirm command */
+	case NAND_CMD_READOOB:
+		if (command == NAND_CMD_READ0)
+			host->buf_start = column;
+		else
+			host->buf_start = column + mtd->writesize;
+
+		if (mtd->writesize > 512)
+			command = NAND_CMD_READ0; /* only READ0 is valid */
+
+		send_cmd(host, command, false);
+		mxc_do_addr_cycle(mtd, column, page_addr);
+
+		if (mtd->writesize > 512)
 			send_cmd(host, NAND_CMD_READSTART, true);
-			/* read for each AREA */
-			send_read_page(host, 0, host->spare_only);
-			send_read_page(host, 1, host->spare_only);
-			send_read_page(host, 2, host->spare_only);
-			send_read_page(host, 3, host->spare_only);
-		} else
-			send_read_page(host, 0, host->spare_only);
+
+		send_page(mtd, NFC_OUTPUT);
+
+		memcpy(host->data_buf, host->main_area0, mtd->writesize);
+		copy_spare(mtd, true);
 		break;
 
-	case NAND_CMD_READID:
-		host->col_addr = 0;
-		send_read_id(host);
+	case NAND_CMD_SEQIN:
+		if (column >= mtd->writesize) {
+			/*
+			 * FIXME: before send SEQIN command for write OOB,
+			 * We must read one page out.
+			 * For K9F1GXX has no READ1 command to set current HW
+			 * pointer to spare area, we must write the whole page
+			 * including OOB together.
+			 */
+			if (mtd->writesize > 512)
+				/* call ourself to read a page */
+				mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+						page_addr);
+
+			host->buf_start = column;
+
+			/* Set program pointer to spare region */
+			if (mtd->writesize == 512)
+				send_cmd(host, NAND_CMD_READOOB, false);
+		} else {
+			host->buf_start = column;
+
+			/* Set program pointer to page start */
+			if (mtd->writesize == 512)
+				send_cmd(host, NAND_CMD_READ0, false);
+		}
+
+		send_cmd(host, command, false);
+		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
 	case NAND_CMD_PAGEPROG:
+		memcpy(host->main_area0, host->data_buf, mtd->writesize);
+		copy_spare(mtd, false);
+		send_page(mtd, NFC_INPUT);
+		send_cmd(host, command, true);
+		mxc_do_addr_cycle(mtd, column, page_addr);
 		break;
 
-	case NAND_CMD_STATUS:
+	case NAND_CMD_READID:
+		send_cmd(host, command, true);
+		mxc_do_addr_cycle(mtd, column, page_addr);
+		send_read_id(host);
+		host->buf_start = column;
 		break;
 
+	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
+		send_cmd(host, command, false);
+		mxc_do_addr_cycle(mtd, column, page_addr);
+
 		break;
 	}
 }
 
-/* Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks. */
-static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+/*
+ * The generic flash bbt decriptors overlap with our ecc
+ * hardware, so define some i.MX specific ones.
+ */
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
 
-static struct nand_bbt_descr smallpage_memorybased = {
-	.options = NAND_BBT_SCAN2NDPAGE,
-	.offs = 5,
-	.len = 1,
-	.pattern = scan_ff_pattern
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 0,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+	    | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 0,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
 };
 
 static int __init mxcnd_probe(struct platform_device *pdev)
@@ -877,12 +681,16 @@
 	struct resource *res;
 	uint16_t tmp;
 	int err = 0, nr_parts = 0;
+	struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
 	/* Allocate memory for MTD device structure and private data */
-	host = kzalloc(sizeof(struct mxc_nand_host), GFP_KERNEL);
+	host = kzalloc(sizeof(struct mxc_nand_host) + NAND_MAX_PAGESIZE +
+			NAND_MAX_OOBSIZE, GFP_KERNEL);
 	if (!host)
 		return -ENOMEM;
 
+	host->data_buf = (uint8_t *)(host + 1);
+
 	host->dev = &pdev->dev;
 	/* structures must be linked */
 	this = &host->nand;
@@ -890,7 +698,7 @@
 	mtd->priv = this;
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &pdev->dev;
-	mtd->name = "mxc_nand";
+	mtd->name = DRIVER_NAME;
 
 	/* 50 us command delay time */
 	this->chip_delay = 5;
@@ -920,44 +728,44 @@
 		goto eres;
 	}
 
-	host->regs = ioremap(res->start, res->end - res->start + 1);
-	if (!host->regs) {
+	host->base = ioremap(res->start, resource_size(res));
+	if (!host->base) {
 		err = -ENOMEM;
 		goto eres;
 	}
 
+	host->main_area0 = host->base;
+	host->main_area1 = host->base + 0x200;
+
+	if (nfc_is_v21()) {
+		host->regs = host->base + 0x1000;
+		host->spare0 = host->base + 0x1000;
+		host->spare_len = 64;
+		oob_smallpage = &nandv2_hw_eccoob_smallpage;
+		oob_largepage = &nandv2_hw_eccoob_largepage;
+	} else if (nfc_is_v1()) {
+		host->regs = host->base;
+		host->spare0 = host->base + 0x800;
+		host->spare_len = 16;
+		oob_smallpage = &nandv1_hw_eccoob_smallpage;
+		oob_largepage = &nandv1_hw_eccoob_largepage;
+	} else
+		BUG();
+
+	/* disable interrupt and spare enable */
 	tmp = readw(host->regs + NFC_CONFIG1);
 	tmp |= NFC_INT_MSK;
+	tmp &= ~NFC_SP_EN;
 	writew(tmp, host->regs + NFC_CONFIG1);
 
 	init_waitqueue_head(&host->irq_waitq);
 
 	host->irq = platform_get_irq(pdev, 0);
 
-	err = request_irq(host->irq, mxc_nfc_irq, 0, "mxc_nd", host);
+	err = request_irq(host->irq, mxc_nfc_irq, 0, DRIVER_NAME, host);
 	if (err)
 		goto eirq;
 
-	if (pdata->hw_ecc) {
-		this->ecc.calculate = mxc_nand_calculate_ecc;
-		this->ecc.hwctl = mxc_nand_enable_hwecc;
-		this->ecc.correct = mxc_nand_correct_data;
-		this->ecc.mode = NAND_ECC_HW;
-		this->ecc.size = 512;
-		this->ecc.bytes = 3;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp |= NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
-	} else {
-		this->ecc.size = 512;
-		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
-		this->ecc.mode = NAND_ECC_SOFT;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp &= ~NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
-	}
-
 	/* Reset NAND */
 	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
@@ -966,16 +774,47 @@
 	writew(0x2, host->regs + NFC_CONFIG);
 
 	/* Blocks to be unlocked */
-	writew(0x0, host->regs + NFC_UNLOCKSTART_BLKADDR);
-	writew(0x4000, host->regs + NFC_UNLOCKEND_BLKADDR);
+	if (nfc_is_v21()) {
+		writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
+	        writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
+		this->ecc.bytes = 9;
+	} else if (nfc_is_v1()) {
+		writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
+	        writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
+		this->ecc.bytes = 3;
+	} else
+		BUG();
 
 	/* Unlock Block Command for given address range */
 	writew(0x4, host->regs + NFC_WRPROT);
 
+	this->ecc.size = 512;
+	this->ecc.layout = oob_smallpage;
+
+	if (pdata->hw_ecc) {
+		this->ecc.calculate = mxc_nand_calculate_ecc;
+		this->ecc.hwctl = mxc_nand_enable_hwecc;
+		this->ecc.correct = mxc_nand_correct_data;
+		this->ecc.mode = NAND_ECC_HW;
+		tmp = readw(host->regs + NFC_CONFIG1);
+		tmp |= NFC_ECC_EN;
+		writew(tmp, host->regs + NFC_CONFIG1);
+	} else {
+		this->ecc.mode = NAND_ECC_SOFT;
+		tmp = readw(host->regs + NFC_CONFIG1);
+		tmp &= ~NFC_ECC_EN;
+		writew(tmp, host->regs + NFC_CONFIG1);
+	}
+
 	/* NAND bus width determines access funtions used by upper layer */
-	if (pdata->width == 2) {
+	if (pdata->width == 2)
 		this->options |= NAND_BUSWIDTH_16;
-		this->ecc.layout = &nand_hw_eccoob_16;
+
+	if (pdata->flash_bbt) {
+		this->bbt_td = &bbt_main_descr;
+		this->bbt_md = &bbt_mirror_descr;
+		/* update flash based bbt */
+		this->options |= NAND_USE_FLASH_BBT;
 	}
 
 	/* first scan to find the device and get the page size */
@@ -984,38 +823,8 @@
 		goto escan;
 	}
 
-	if (mtd->writesize == 2048) {
-		host->pagesize_2k = 1;
-		this->badblock_pattern = &smallpage_memorybased;
-	}
-
-	if (this->ecc.mode == NAND_ECC_HW) {
-		switch (mtd->oobsize) {
-		case 8:
-			this->ecc.layout = &nand_hw_eccoob_8;
-			break;
-		case 16:
-			this->ecc.layout = &nand_hw_eccoob_16;
-			break;
-		case 64:
-			this->ecc.layout = &nand_hw_eccoob_64;
-			break;
-		default:
-			/* page size not handled by HW ECC */
-			/* switching back to soft ECC */
-			this->ecc.size = 512;
-			this->ecc.bytes = 3;
-			this->ecc.layout = &nand_hw_eccoob_8;
-			this->ecc.mode = NAND_ECC_SOFT;
-			this->ecc.calculate = NULL;
-			this->ecc.correct = NULL;
-			this->ecc.hwctl = NULL;
-			tmp = readw(host->regs + NFC_CONFIG1);
-			tmp &= ~NFC_ECC_EN;
-			writew(tmp, host->regs + NFC_CONFIG1);
-			break;
-		}
-	}
+	if (mtd->writesize == 2048)
+		this->ecc.layout = oob_largepage;
 
 	/* second phase scan */
 	if (nand_scan_tail(mtd)) {
@@ -1043,7 +852,7 @@
 escan:
 	free_irq(host->irq, host);
 eirq:
-	iounmap(host->regs);
+	iounmap(host->base);
 eres:
 	clk_put(host->clk);
 eclk:
@@ -1062,7 +871,7 @@
 
 	nand_release(&host->mtd);
 	free_irq(host->irq, host);
-	iounmap(host->regs);
+	iounmap(host->base);
 	kfree(host);
 
 	return 0;
@@ -1113,7 +922,7 @@
 	.driver = {
 		   .name = DRIVER_NAME,
 		   },
-	.remove = __exit_p(mxcnd_remove),
+	.remove = __devexit_p(mxcnd_remove),
 	.suspend = mxcnd_suspend,
 	.resume = mxcnd_resume,
 };
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 2957cc7..8f2958f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -428,6 +428,28 @@
 	return nand_isbad_bbt(mtd, ofs, allowbbt);
 }
 
+/**
+ * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd:	MTD device structure
+ * @timeo:	Timeout
+ *
+ * Helper function for nand_wait_ready used when needing to wait in interrupt
+ * context.
+ */
+static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
+{
+	struct nand_chip *chip = mtd->priv;
+	int i;
+
+	/* Wait for the device to get ready */
+	for (i = 0; i < timeo; i++) {
+		if (chip->dev_ready(mtd))
+			break;
+		touch_softlockup_watchdog();
+		mdelay(1);
+	}
+}
+
 /*
  * Wait for the ready pin, after a command
  * The timeout is catched later.
@@ -437,6 +459,10 @@
 	struct nand_chip *chip = mtd->priv;
 	unsigned long timeo = jiffies + 2;
 
+	/* 400ms timeout */
+	if (in_interrupt() || oops_in_progress)
+		return panic_nand_wait_ready(mtd, 400);
+
 	led_trigger_event(nand_led_trigger, LED_FULL);
 	/* wait until command is processed or timeout occures */
 	do {
@@ -672,6 +698,22 @@
 }
 
 /**
+ * panic_nand_get_device - [GENERIC] Get chip for selected access
+ * @chip:	the nand chip descriptor
+ * @mtd:	MTD device structure
+ * @new_state:	the state which is requested
+ *
+ * Used when in panic, no locks are taken.
+ */
+static void panic_nand_get_device(struct nand_chip *chip,
+		      struct mtd_info *mtd, int new_state)
+{
+	/* Hardware controller shared among independend devices */
+	chip->controller->active = chip;
+	chip->state = new_state;
+}
+
+/**
  * nand_get_device - [GENERIC] Get chip for selected access
  * @chip:	the nand chip descriptor
  * @mtd:	MTD device structure
@@ -698,8 +740,14 @@
 		return 0;
 	}
 	if (new_state == FL_PM_SUSPENDED) {
-		spin_unlock(lock);
-		return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
+		if (chip->controller->active->state == FL_PM_SUSPENDED) {
+			chip->state = FL_PM_SUSPENDED;
+			spin_unlock(lock);
+			return 0;
+		} else {
+			spin_unlock(lock);
+			return -EAGAIN;
+		}
 	}
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	add_wait_queue(wq, &wait);
@@ -710,6 +758,32 @@
 }
 
 /**
+ * panic_nand_wait - [GENERIC]  wait until the command is done
+ * @mtd:	MTD device structure
+ * @chip:	NAND chip structure
+ * @timeo:	Timeout
+ *
+ * Wait for command done. This is a helper function for nand_wait used when
+ * we are in interrupt context. May happen when in panic and trying to write
+ * an oops trough mtdoops.
+ */
+static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
+			    unsigned long timeo)
+{
+	int i;
+	for (i = 0; i < timeo; i++) {
+		if (chip->dev_ready) {
+			if (chip->dev_ready(mtd))
+				break;
+		} else {
+			if (chip->read_byte(mtd) & NAND_STATUS_READY)
+				break;
+		}
+		mdelay(1);
+        }
+}
+
+/**
  * nand_wait - [DEFAULT]  wait until the command is done
  * @mtd:	MTD device structure
  * @chip:	NAND chip structure
@@ -740,15 +814,19 @@
 	else
 		chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 
-	while (time_before(jiffies, timeo)) {
-		if (chip->dev_ready) {
-			if (chip->dev_ready(mtd))
-				break;
-		} else {
-			if (chip->read_byte(mtd) & NAND_STATUS_READY)
-				break;
+	if (in_interrupt() || oops_in_progress)
+		panic_nand_wait(mtd, chip, timeo);
+	else {
+		while (time_before(jiffies, timeo)) {
+			if (chip->dev_ready) {
+				if (chip->dev_ready(mtd))
+					break;
+			} else {
+				if (chip->read_byte(mtd) & NAND_STATUS_READY)
+					break;
+			}
+			cond_resched();
 		}
-		cond_resched();
 	}
 	led_trigger_event(nand_led_trigger, LED_OFF);
 
@@ -1949,6 +2027,45 @@
 }
 
 /**
+ * panic_nand_write - [MTD Interface] NAND write with ECC
+ * @mtd:	MTD device structure
+ * @to:		offset to write to
+ * @len:	number of bytes to write
+ * @retlen:	pointer to variable to store the number of written bytes
+ * @buf:	the data to write
+ *
+ * NAND write with ECC. Used when performing writes in interrupt context, this
+ * may for example be called by mtdoops when writing an oops while in panic.
+ */
+static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+			    size_t *retlen, const uint8_t *buf)
+{
+	struct nand_chip *chip = mtd->priv;
+	int ret;
+
+	/* Do not allow reads past end of device */
+	if ((to + len) > mtd->size)
+		return -EINVAL;
+	if (!len)
+		return 0;
+
+	/* Wait for the device to get ready.  */
+	panic_nand_wait(mtd, chip, 400);
+
+	/* Grab the device.  */
+	panic_nand_get_device(chip, mtd, FL_WRITING);
+
+	chip->ops.len = len;
+	chip->ops.datbuf = (uint8_t *)buf;
+	chip->ops.oobbuf = NULL;
+
+	ret = nand_do_write_ops(mtd, to, &chip->ops);
+
+	*retlen = chip->ops.retlen;
+	return ret;
+}
+
+/**
  * nand_write - [MTD Interface] NAND write with ECC
  * @mtd:	MTD device structure
  * @to:		offset to write to
@@ -2645,7 +2762,8 @@
 	type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
 
 	if (IS_ERR(type)) {
-		printk(KERN_WARNING "No NAND device found!!!\n");
+		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
+			printk(KERN_WARNING "No NAND device found.\n");
 		chip->select_chip(mtd, -1);
 		return PTR_ERR(type);
 	}
@@ -2877,6 +2995,7 @@
 	mtd->unpoint = NULL;
 	mtd->read = nand_read;
 	mtd->write = nand_write;
+	mtd->panic_write = panic_nand_write;
 	mtd->read_oob = nand_read_oob;
 	mtd->write_oob = nand_write_oob;
 	mtd->sync = nand_sync;
diff --git a/drivers/mtd/nand/nand_bcm_umi.c b/drivers/mtd/nand/nand_bcm_umi.c
new file mode 100644
index 0000000..46a6bc9
--- /dev/null
+++ b/drivers/mtd/nand/nand_bcm_umi.c
@@ -0,0 +1,149 @@
+/*****************************************************************************
+* Copyright 2004 - 2009 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/* ---- Include Files ---------------------------------------------------- */
+#include <mach/reg_umi.h>
+#include "nand_bcm_umi.h"
+#ifdef BOOT0_BUILD
+#include <uart.h>
+#endif
+
+/* ---- External Variable Declarations ----------------------------------- */
+/* ---- External Function Prototypes ------------------------------------- */
+/* ---- Public Variables ------------------------------------------------- */
+/* ---- Private Constants and Types -------------------------------------- */
+/* ---- Private Function Prototypes -------------------------------------- */
+/* ---- Private Variables ------------------------------------------------ */
+/* ---- Private Functions ------------------------------------------------ */
+
+#if NAND_ECC_BCH
+/****************************************************************************
+*  nand_bch_ecc_flip_bit - Routine to flip an errored bit
+*
+*  PURPOSE:
+*     This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the
+*     errored bit specified
+*
+*  PARAMETERS:
+*     datap - Container that holds the 512 byte data
+*     errorLocation - Location of the bit that needs to be flipped
+*
+*  RETURNS:
+*     None
+****************************************************************************/
+static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation)
+{
+	int locWithinAByte = (errorLocation & REG_UMI_BCH_ERR_LOC_BYTE) >> 0;
+	int locWithinAWord = (errorLocation & REG_UMI_BCH_ERR_LOC_WORD) >> 3;
+	int locWithinAPage = (errorLocation & REG_UMI_BCH_ERR_LOC_PAGE) >> 5;
+
+	uint8_t errorByte = 0;
+	uint8_t byteMask = 1 << locWithinAByte;
+
+	/* BCH uses big endian, need to change the location
+	 * bits to little endian */
+	locWithinAWord = 3 - locWithinAWord;
+
+	errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord];
+
+#ifdef BOOT0_BUILD
+	puthexs("\nECC Correct Offset: ",
+		locWithinAPage * sizeof(uint32_t) + locWithinAWord);
+	puthexs(" errorByte:", errorByte);
+	puthex8(" Bit: ", locWithinAByte);
+#endif
+
+	if (errorByte & byteMask) {
+		/* bit needs to be cleared */
+		errorByte &= ~byteMask;
+	} else {
+		/* bit needs to be set */
+		errorByte |= byteMask;
+	}
+
+	/* write back the value with the fixed bit */
+	datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte;
+}
+
+/****************************************************************************
+*  nand_correct_page_bch - Routine to correct bit errors when reading NAND
+*
+*  PURPOSE:
+*     This routine reads the BCH registers to determine if there are any bit
+*     errors during the read of the last 512 bytes of data + ECC bytes.  If
+*     errors exists, the routine fixes it.
+*
+*  PARAMETERS:
+*     datap - Container that holds the 512 byte data
+*
+*  RETURNS:
+*     0 or greater = Number of errors corrected
+*                    (No errors are found or errors have been fixed)
+*    -1 = Error(s) cannot be fixed
+****************************************************************************/
+int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
+				  int numEccBytes)
+{
+	int numErrors;
+	int errorLocation;
+	int idx;
+	uint32_t regValue;
+
+	/* wait for read ECC to be valid */
+	regValue = nand_bcm_umi_bch_poll_read_ecc_calc();
+
+	/*
+	 * read the control status register to determine if there
+	 * are error'ed bits
+	 * see if errors are correctible
+	 */
+	if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) {
+		int i;
+
+		for (i = 0; i < numEccBytes; i++) {
+			if (readEccData[i] != 0xff) {
+				/* errors cannot be fixed, return -1 */
+				return -1;
+			}
+		}
+		/* If ECC is unprogrammed then we can't correct,
+		 * assume everything OK */
+		return 0;
+	}
+
+	if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) {
+		/* no errors */
+		return 0;
+	}
+
+	/*
+	 * Fix errored bits by doing the following:
+	 * 1. Read the number of errors in the control and status register
+	 * 2. Read the error location registers that corresponds to the number
+	 *    of errors reported
+	 * 3. Invert the bit in the data
+	 */
+	numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20;
+
+	for (idx = 0; idx < numErrors; idx++) {
+		errorLocation =
+		    REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK;
+
+		/* Flip bit */
+		nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation);
+	}
+	/* Errors corrected */
+	return numErrors;
+}
+#endif
diff --git a/drivers/mtd/nand/nand_bcm_umi.h b/drivers/mtd/nand/nand_bcm_umi.h
new file mode 100644
index 0000000..7cec2cd
--- /dev/null
+++ b/drivers/mtd/nand/nand_bcm_umi.h
@@ -0,0 +1,358 @@
+/*****************************************************************************
+* Copyright 2003 - 2009 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+#ifndef NAND_BCM_UMI_H
+#define NAND_BCM_UMI_H
+
+/* ---- Include Files ---------------------------------------------------- */
+#include <mach/reg_umi.h>
+#include <mach/reg_nand.h>
+#include <cfg_global.h>
+
+/* ---- Constants and Types ---------------------------------------------- */
+#if (CFG_GLOBAL_CHIP_FAMILY == CFG_GLOBAL_CHIP_FAMILY_BCMRING)
+#define NAND_ECC_BCH (CFG_GLOBAL_CHIP_REV > 0xA0)
+#else
+#define NAND_ECC_BCH 0
+#endif
+
+#define CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES	13
+
+#if NAND_ECC_BCH
+#ifdef BOOT0_BUILD
+#define NAND_ECC_NUM_BYTES 13
+#else
+#define NAND_ECC_NUM_BYTES CFG_GLOBAL_NAND_ECC_BCH_NUM_BYTES
+#endif
+#else
+#define NAND_ECC_NUM_BYTES 3
+#endif
+
+#define NAND_DATA_ACCESS_SIZE 512
+
+/* ---- Variable Externs ------------------------------------------ */
+/* ---- Function Prototypes --------------------------------------- */
+int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
+				  int numEccBytes);
+
+/* Check in device is ready */
+static inline int nand_bcm_umi_dev_ready(void)
+{
+	return REG_UMI_NAND_RCSR & REG_UMI_NAND_RCSR_RDY;
+}
+
+/* Wait until device is ready */
+static inline void nand_bcm_umi_wait_till_ready(void)
+{
+	while (nand_bcm_umi_dev_ready() == 0)
+		;
+}
+
+/* Enable Hamming ECC */
+static inline void nand_bcm_umi_hamming_enable_hwecc(void)
+{
+	/* disable and reset ECC, 512 byte page */
+	REG_UMI_NAND_ECC_CSR &= ~(REG_UMI_NAND_ECC_CSR_ECC_ENABLE |
+		REG_UMI_NAND_ECC_CSR_256BYTE);
+	/* enable ECC */
+	REG_UMI_NAND_ECC_CSR |= REG_UMI_NAND_ECC_CSR_ECC_ENABLE;
+}
+
+#if NAND_ECC_BCH
+/* BCH ECC specifics */
+#define ECC_BITS_PER_CORRECTABLE_BIT 13
+
+/* Enable BCH Read ECC */
+static inline void nand_bcm_umi_bch_enable_read_hwecc(void)
+{
+	/* disable and reset ECC */
+	REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
+	/* Turn on ECC */
+	REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
+}
+
+/* Enable BCH Write ECC */
+static inline void nand_bcm_umi_bch_enable_write_hwecc(void)
+{
+	/* disable and reset ECC */
+	REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID;
+	/* Turn on ECC */
+	REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_WR_EN;
+}
+
+/* Config number of BCH ECC bytes */
+static inline void nand_bcm_umi_bch_config_ecc(uint8_t numEccBytes)
+{
+	uint32_t nValue;
+	uint32_t tValue;
+	uint32_t kValue;
+	uint32_t numBits = numEccBytes * 8;
+
+	/* disable and reset ECC */
+	REG_UMI_BCH_CTRL_STATUS =
+	    REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID |
+	    REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID;
+
+	/* Every correctible bit requires 13 ECC bits */
+	tValue = (uint32_t) (numBits / ECC_BITS_PER_CORRECTABLE_BIT);
+
+	/* Total data in number of bits for generating and computing BCH ECC */
+	nValue = (NAND_DATA_ACCESS_SIZE + numEccBytes) * 8;
+
+	/* K parameter is used internally.  K = N - (T * 13) */
+	kValue = nValue - (tValue * ECC_BITS_PER_CORRECTABLE_BIT);
+
+	/* Write the settings */
+	REG_UMI_BCH_N = nValue;
+	REG_UMI_BCH_T = tValue;
+	REG_UMI_BCH_K = kValue;
+}
+
+/* Pause during ECC read calculation to skip bytes in OOB */
+static inline void nand_bcm_umi_bch_pause_read_ecc_calc(void)
+{
+	REG_UMI_BCH_CTRL_STATUS =
+	    REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN |
+	    REG_UMI_BCH_CTRL_STATUS_PAUSE_ECC_DEC;
+}
+
+/* Resume during ECC read calculation after skipping bytes in OOB */
+static inline void nand_bcm_umi_bch_resume_read_ecc_calc(void)
+{
+	REG_UMI_BCH_CTRL_STATUS = REG_UMI_BCH_CTRL_STATUS_ECC_RD_EN;
+}
+
+/* Poll read ECC calc to check when hardware completes */
+static inline uint32_t nand_bcm_umi_bch_poll_read_ecc_calc(void)
+{
+	uint32_t regVal;
+
+	do {
+		/* wait for ECC to be valid */
+		regVal = REG_UMI_BCH_CTRL_STATUS;
+	} while ((regVal & REG_UMI_BCH_CTRL_STATUS_RD_ECC_VALID) == 0);
+
+	return regVal;
+}
+
+/* Poll write ECC calc to check when hardware completes */
+static inline void nand_bcm_umi_bch_poll_write_ecc_calc(void)
+{
+	/* wait for ECC to be valid */
+	while ((REG_UMI_BCH_CTRL_STATUS & REG_UMI_BCH_CTRL_STATUS_WR_ECC_VALID)
+	       == 0)
+		;
+}
+
+/* Read the OOB and ECC, for kernel write OOB to a buffer */
+#if defined(__KERNEL__) && !defined(STANDALONE)
+static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
+	uint8_t *eccCalc, int numEccBytes, uint8_t *oobp)
+#else
+static inline void nand_bcm_umi_bch_read_oobEcc(uint32_t pageSize,
+	uint8_t *eccCalc, int numEccBytes)
+#endif
+{
+	int eccPos = 0;
+	int numToRead = 16;	/* There are 16 bytes per sector in the OOB */
+
+	/* ECC is already paused when this function is called */
+
+	if (pageSize == NAND_DATA_ACCESS_SIZE) {
+		while (numToRead > numEccBytes) {
+			/* skip free oob region */
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp++ = REG_NAND_DATA8;
+#else
+			REG_NAND_DATA8;
+#endif
+			numToRead--;
+		}
+
+		/* read ECC bytes before BI */
+		nand_bcm_umi_bch_resume_read_ecc_calc();
+
+		while (numToRead > 11) {
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp = REG_NAND_DATA8;
+			eccCalc[eccPos++] = *oobp;
+			oobp++;
+#else
+			eccCalc[eccPos++] = REG_NAND_DATA8;
+#endif
+		}
+
+		nand_bcm_umi_bch_pause_read_ecc_calc();
+
+		if (numToRead == 11) {
+			/* read BI */
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp++ = REG_NAND_DATA8;
+#else
+			REG_NAND_DATA8;
+#endif
+			numToRead--;
+		}
+
+		/* read ECC bytes */
+		nand_bcm_umi_bch_resume_read_ecc_calc();
+		while (numToRead) {
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp = REG_NAND_DATA8;
+			eccCalc[eccPos++] = *oobp;
+			oobp++;
+#else
+			eccCalc[eccPos++] = REG_NAND_DATA8;
+#endif
+			numToRead--;
+		}
+	} else {
+		/* skip BI */
+#if defined(__KERNEL__) && !defined(STANDALONE)
+		*oobp++ = REG_NAND_DATA8;
+#else
+		REG_NAND_DATA8;
+#endif
+		numToRead--;
+
+		while (numToRead > numEccBytes) {
+			/* skip free oob region */
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp++ = REG_NAND_DATA8;
+#else
+			REG_NAND_DATA8;
+#endif
+			numToRead--;
+		}
+
+		/* read ECC bytes */
+		nand_bcm_umi_bch_resume_read_ecc_calc();
+		while (numToRead) {
+#if defined(__KERNEL__) && !defined(STANDALONE)
+			*oobp = REG_NAND_DATA8;
+			eccCalc[eccPos++] = *oobp;
+			oobp++;
+#else
+			eccCalc[eccPos++] = REG_NAND_DATA8;
+#endif
+			numToRead--;
+		}
+	}
+}
+
+/* Helper function to write ECC */
+static inline void NAND_BCM_UMI_ECC_WRITE(int numEccBytes, int eccBytePos,
+					  uint8_t *oobp, uint8_t eccVal)
+{
+	if (eccBytePos <= numEccBytes)
+		*oobp = eccVal;
+}
+
+/* Write OOB with ECC */
+static inline void nand_bcm_umi_bch_write_oobEcc(uint32_t pageSize,
+						 uint8_t *oobp, int numEccBytes)
+{
+	uint32_t eccVal = 0xffffffff;
+
+	/* wait for write ECC to be valid */
+	nand_bcm_umi_bch_poll_write_ecc_calc();
+
+	/*
+	 ** Get the hardware ecc from the 32-bit result registers.
+	 ** Read after 512 byte accesses. Format B3B2B1B0
+	 ** where B3 = ecc3, etc.
+	 */
+
+	if (pageSize == NAND_DATA_ACCESS_SIZE) {
+		/* Now fill in the ECC bytes */
+		if (numEccBytes >= 13)
+			eccVal = REG_UMI_BCH_WR_ECC_3;
+
+		/* Usually we skip CM in oob[0,1] */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[0],
+			(eccVal >> 16) & 0xff);
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[1],
+			(eccVal >> 8) & 0xff);
+
+		/* Write ECC in oob[2,3,4] */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[2],
+			eccVal & 0xff);	/* ECC 12 */
+
+		if (numEccBytes >= 9)
+			eccVal = REG_UMI_BCH_WR_ECC_2;
+
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[3],
+			(eccVal >> 24) & 0xff);	/* ECC11 */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[4],
+			(eccVal >> 16) & 0xff);	/* ECC10 */
+
+		/* Always Skip BI in oob[5] */
+	} else {
+		/* Always Skip BI in oob[0] */
+
+		/* Now fill in the ECC bytes */
+		if (numEccBytes >= 13)
+			eccVal = REG_UMI_BCH_WR_ECC_3;
+
+		/* Usually skip CM in oob[1,2] */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 15, &oobp[1],
+			(eccVal >> 16) & 0xff);
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 14, &oobp[2],
+			(eccVal >> 8) & 0xff);
+
+		/* Write ECC in oob[3-15] */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 13, &oobp[3],
+			eccVal & 0xff);	/* ECC12 */
+
+		if (numEccBytes >= 9)
+			eccVal = REG_UMI_BCH_WR_ECC_2;
+
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 12, &oobp[4],
+			(eccVal >> 24) & 0xff);	/* ECC11 */
+		NAND_BCM_UMI_ECC_WRITE(numEccBytes, 11, &oobp[5],
+			(eccVal >> 16) & 0xff);	/* ECC10 */
+	}
+
+	/* Fill in the remainder of ECC locations */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 10, &oobp[6],
+		(eccVal >> 8) & 0xff);	/* ECC9 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 9, &oobp[7],
+		eccVal & 0xff);	/* ECC8 */
+
+	if (numEccBytes >= 5)
+		eccVal = REG_UMI_BCH_WR_ECC_1;
+
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 8, &oobp[8],
+		(eccVal >> 24) & 0xff);	/* ECC7 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 7, &oobp[9],
+		(eccVal >> 16) & 0xff);	/* ECC6 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 6, &oobp[10],
+		(eccVal >> 8) & 0xff);	/* ECC5 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 5, &oobp[11],
+		eccVal & 0xff);	/* ECC4 */
+
+	if (numEccBytes >= 1)
+		eccVal = REG_UMI_BCH_WR_ECC_0;
+
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 4, &oobp[12],
+		(eccVal >> 24) & 0xff);	/* ECC3 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 3, &oobp[13],
+		(eccVal >> 16) & 0xff);	/* ECC2 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 2, &oobp[14],
+		(eccVal >> 8) & 0xff);	/* ECC1 */
+	NAND_BCM_UMI_ECC_WRITE(numEccBytes, 1, &oobp[15],
+		eccVal & 0xff);	/* ECC0 */
+}
+#endif
+
+#endif /* NAND_BCM_UMI_H */
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 92320a6..271b8e7 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -150,20 +150,19 @@
 };
 
 /**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
  *			 block
- * @mtd:	MTD block structure
  * @buf:	input buffer with raw data
+ * @eccsize:	data bytes per ecc step (256 or 512)
  * @code:	output buffer with ECC
  */
-int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
 		       unsigned char *code)
 {
 	int i;
 	const uint32_t *bp = (uint32_t *)buf;
 	/* 256 or 512 bytes/ecc  */
-	const uint32_t eccsize_mult =
-			(((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+	const uint32_t eccsize_mult = eccsize >> 8;
 	uint32_t cur;		/* current value in buffer */
 	/* rp0..rp15..rp17 are the various accumulated parities (per byte) */
 	uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
@@ -412,6 +411,22 @@
 		    (invparity[par & 0x55] << 2) |
 		    (invparity[rp17] << 1) |
 		    (invparity[rp16] << 0);
+}
+EXPORT_SYMBOL(__nand_calculate_ecc);
+
+/**
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ *			 block
+ * @mtd:	MTD block structure
+ * @buf:	input buffer with raw data
+ * @code:	output buffer with ECC
+ */
+int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+		       unsigned char *code)
+{
+	__nand_calculate_ecc(buf,
+			((struct nand_chip *)mtd->priv)->ecc.size, code);
+
 	return 0;
 }
 EXPORT_SYMBOL(nand_calculate_ecc);
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index cd0711b..7281000 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -161,7 +161,7 @@
 MODULE_PARM_DESC(cache_file,     "File to use to cache nand pages instead of memory");
 
 /* The largest possible page size */
-#define NS_LARGEST_PAGE_SIZE	2048
+#define NS_LARGEST_PAGE_SIZE	4096
 
 /* The prefix for simulator output */
 #define NS_OUTPUT_PREFIX "[nandsim]"
@@ -259,7 +259,8 @@
 #define OPT_SMARTMEDIA   0x00000010 /* SmartMedia technology chips */
 #define OPT_AUTOINCR     0x00000020 /* page number auto inctimentation is possible */
 #define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
-#define OPT_LARGEPAGE    (OPT_PAGE2048) /* 2048-byte page chips */
+#define OPT_PAGE4096     0x00000080 /* 4096-byte page chips */
+#define OPT_LARGEPAGE    (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
 #define OPT_SMALLPAGE    (OPT_PAGE256  | OPT_PAGE512)  /* 256 and 512-byte page chips */
 
 /* Remove action bits ftom state */
@@ -588,6 +589,8 @@
 			ns->options |= OPT_PAGE512_8BIT;
 	} else if (ns->geom.pgsz == 2048) {
 		ns->options |= OPT_PAGE2048;
+	} else if (ns->geom.pgsz == 4096) {
+		ns->options |= OPT_PAGE4096;
 	} else {
 		NS_ERR("init_nandsim: unknown page size %u\n", ns->geom.pgsz);
 		return -EIO;
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 4e16c6f..8d46731 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -34,7 +34,12 @@
 {
 	struct platform_nand_data *pdata = pdev->dev.platform_data;
 	struct plat_nand_data *data;
-	int res = 0;
+	struct resource *res;
+	int err = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
 
 	/* Allocate memory for the device structure (and zero it) */
 	data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL);
@@ -43,12 +48,18 @@
 		return -ENOMEM;
 	}
 
-	data->io_base = ioremap(pdev->resource[0].start,
-				pdev->resource[0].end - pdev->resource[0].start + 1);
+	if (!request_mem_region(res->start, resource_size(res),
+				dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		err = -EBUSY;
+		goto out_free;
+	}
+
+	data->io_base = ioremap(res->start, resource_size(res));
 	if (data->io_base == NULL) {
 		dev_err(&pdev->dev, "ioremap failed\n");
-		kfree(data);
-		return -EIO;
+		err = -EIO;
+		goto out_release_io;
 	}
 
 	data->chip.priv = &data;
@@ -74,24 +85,24 @@
 
 	/* Handle any platform specific setup */
 	if (pdata->ctrl.probe) {
-		res = pdata->ctrl.probe(pdev);
-		if (res)
+		err = pdata->ctrl.probe(pdev);
+		if (err)
 			goto out;
 	}
 
 	/* Scan to find existance of the device */
 	if (nand_scan(&data->mtd, 1)) {
-		res = -ENXIO;
+		err = -ENXIO;
 		goto out;
 	}
 
 #ifdef CONFIG_MTD_PARTITIONS
 	if (pdata->chip.part_probe_types) {
-		res = parse_mtd_partitions(&data->mtd,
+		err = parse_mtd_partitions(&data->mtd,
 					pdata->chip.part_probe_types,
 					&data->parts, 0);
-		if (res > 0) {
-			add_mtd_partitions(&data->mtd, data->parts, res);
+		if (err > 0) {
+			add_mtd_partitions(&data->mtd, data->parts, err);
 			return 0;
 		}
 	}
@@ -99,14 +110,14 @@
 		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
 	if (pdata->chip.partitions) {
 		data->parts = pdata->chip.partitions;
-		res = add_mtd_partitions(&data->mtd, data->parts,
+		err = add_mtd_partitions(&data->mtd, data->parts,
 			pdata->chip.nr_partitions);
 	} else
 #endif
-	res = add_mtd_device(&data->mtd);
+	err = add_mtd_device(&data->mtd);
 
-	if (!res)
-		return res;
+	if (!err)
+		return err;
 
 	nand_release(&data->mtd);
 out:
@@ -114,8 +125,11 @@
 		pdata->ctrl.remove(pdev);
 	platform_set_drvdata(pdev, NULL);
 	iounmap(data->io_base);
+out_release_io:
+	release_mem_region(res->start, resource_size(res));
+out_free:
 	kfree(data);
-	return res;
+	return err;
 }
 
 /*
@@ -125,6 +139,9 @@
 {
 	struct plat_nand_data *data = platform_get_drvdata(pdev);
 	struct platform_nand_data *pdata = pdev->dev.platform_data;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	nand_release(&data->mtd);
 #ifdef CONFIG_MTD_PARTITIONS
@@ -134,6 +151,7 @@
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
+	release_mem_region(res->start, resource_size(res));
 	kfree(data);
 
 	return 0;
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 68b5b3a..fa6e9c7 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -774,7 +774,7 @@
 	chip->select_chip  = s3c2410_nand_select_chip;
 	chip->chip_delay   = 50;
 	chip->priv	   = nmtd;
-	chip->options	   = 0;
+	chip->options	   = set->options;
 	chip->controller   = &info->controller;
 
 	switch (info->cpu_type) {
diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 73af832..863513c 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -429,11 +429,10 @@
 		chip = mtd->priv;
 		txx9_priv = chip->priv;
 
+		nand_release(mtd);
 #ifdef CONFIG_MTD_PARTITIONS
-		del_mtd_partitions(mtd);
 		kfree(drvdata->parts[i]);
 #endif
-		del_mtd_device(mtd);
 		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 86c4f6dc..75f38b9 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -112,10 +112,24 @@
 	unsigned long timeout;
 	u32 syscfg;
 
-	if (state == FL_RESETING) {
-		int i;
+	if (state == FL_RESETING || state == FL_PREPARING_ERASE ||
+	    state == FL_VERIFYING_ERASE) {
+		int i = 21;
+		unsigned int intr_flags = ONENAND_INT_MASTER;
 
-		for (i = 0; i < 20; i++) {
+		switch (state) {
+		case FL_RESETING:
+			intr_flags |= ONENAND_INT_RESET;
+			break;
+		case FL_PREPARING_ERASE:
+			intr_flags |= ONENAND_INT_ERASE;
+			break;
+		case FL_VERIFYING_ERASE:
+			i = 101;
+			break;
+		}
+
+		while (--i) {
 			udelay(1);
 			intr = read_reg(c, ONENAND_REG_INTERRUPT);
 			if (intr & ONENAND_INT_MASTER)
@@ -126,7 +140,7 @@
 			wait_err("controller error", state, ctrl, intr);
 			return -EIO;
 		}
-		if (!(intr & ONENAND_INT_RESET)) {
+		if ((intr & intr_flags) != intr_flags) {
 			wait_err("timeout", state, ctrl, intr);
 			return -EIO;
 		}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ff66e43..f63b1db 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1,17 +1,19 @@
 /*
  *  linux/drivers/mtd/onenand/onenand_base.c
  *
- *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Copyright © 2005-2009 Samsung Electronics
+ *  Copyright © 2007 Nokia Corporation
+ *
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  *  Credits:
  *	Adrian Hunter <ext-adrian.hunter@nokia.com>:
  *	auto-placement support, read-while load support, various fixes
- *	Copyright (C) Nokia Corporation, 2007
  *
  *	Vishak G <vishak.g at samsung.com>, Rohit Hagargundgi <h.rohit at samsung.com>
  *	Flex-OneNAND support
- *	Copyright (C) Samsung Electronics, 2008
+ *	Amul Kumar Saha <amul.saha at samsung.com>
+ *	OTP support
  *
  * 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
@@ -32,6 +34,13 @@
 
 #include <asm/io.h>
 
+/*
+ * Multiblock erase if number of blocks to erase is 2 or more.
+ * Maximum number of blocks for simultaneous erase is 64.
+ */
+#define MB_ERASE_MIN_BLK_COUNT 2
+#define MB_ERASE_MAX_BLK_COUNT 64
+
 /* Default Flex-OneNAND boundary and lock respectively */
 static int flex_bdry[MAX_DIES * 2] = { -1, 0, -1, 0 };
 
@@ -43,6 +52,18 @@
 				"    : 0->Set boundary in unlocked status"
 				"    : 1->Set boundary in locked status");
 
+/* Default OneNAND/Flex-OneNAND OTP options*/
+static int otp;
+
+module_param(otp, int, 0400);
+MODULE_PARM_DESC(otp,	"Corresponding behaviour of OneNAND in OTP"
+			"Syntax : otp=LOCK_TYPE"
+			"LOCK_TYPE : Keys issued, for specific OTP Lock type"
+			"	   : 0 -> Default (No Blocks Locked)"
+			"	   : 1 -> OTP Block lock"
+			"	   : 2 -> 1st Block lock"
+			"	   : 3 -> BOTH OTP Block and 1st Block lock");
+
 /**
  *  onenand_oob_128 - oob info for Flex-Onenand with 4KB page
  *  For now, we expose only 64 out of 80 ecc bytes
@@ -339,6 +360,8 @@
 		break;
 
 	case ONENAND_CMD_ERASE:
+	case ONENAND_CMD_MULTIBLOCK_ERASE:
+	case ONENAND_CMD_ERASE_VERIFY:
 	case ONENAND_CMD_BUFFERRAM:
 	case ONENAND_CMD_OTP_ACCESS:
 		block = onenand_block(this, addr);
@@ -483,7 +506,7 @@
 		if (interrupt & flags)
 			break;
 
-		if (state != FL_READING)
+		if (state != FL_READING && state != FL_PREPARING_ERASE)
 			cond_resched();
 	}
 	/* To get correct interrupt status in timeout case */
@@ -500,25 +523,40 @@
 		int ecc = onenand_read_ecc(this);
 		if (ecc) {
 			if (ecc & ONENAND_ECC_2BIT_ALL) {
-				printk(KERN_ERR "onenand_wait: ECC error = 0x%04x\n", ecc);
+				printk(KERN_ERR "%s: ECC error = 0x%04x\n",
+					__func__, ecc);
 				mtd->ecc_stats.failed++;
 				return -EBADMSG;
 			} else if (ecc & ONENAND_ECC_1BIT_ALL) {
-				printk(KERN_DEBUG "onenand_wait: correctable ECC error = 0x%04x\n", ecc);
+				printk(KERN_DEBUG "%s: correctable ECC error = 0x%04x\n",
+					__func__, ecc);
 				mtd->ecc_stats.corrected++;
 			}
 		}
 	} else if (state == FL_READING) {
-		printk(KERN_ERR "onenand_wait: read timeout! ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+		printk(KERN_ERR "%s: read timeout! ctrl=0x%04x intr=0x%04x\n",
+			__func__, ctrl, interrupt);
+		return -EIO;
+	}
+
+	if (state == FL_PREPARING_ERASE && !(interrupt & ONENAND_INT_ERASE)) {
+		printk(KERN_ERR "%s: mb erase timeout! ctrl=0x%04x intr=0x%04x\n",
+		       __func__, ctrl, interrupt);
+		return -EIO;
+	}
+
+	if (!(interrupt & ONENAND_INT_MASTER)) {
+		printk(KERN_ERR "%s: timeout! ctrl=0x%04x intr=0x%04x\n",
+		       __func__, ctrl, interrupt);
 		return -EIO;
 	}
 
 	/* If there's controller error, it's a real error */
 	if (ctrl & ONENAND_CTRL_ERROR) {
-		printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n",
-			ctrl);
+		printk(KERN_ERR "%s: controller error = 0x%04x\n",
+			__func__, ctrl);
 		if (ctrl & ONENAND_CTRL_LOCK)
-			printk(KERN_ERR "onenand_wait: it's locked error.\n");
+			printk(KERN_ERR "%s: it's locked error.\n", __func__);
 		return -EIO;
 	}
 
@@ -1015,7 +1053,8 @@
 	/* We are attempting to reread, so decrement stats.failed
 	 * which was incremented by onenand_wait due to read failure
 	 */
-	printk(KERN_INFO "onenand_recover_lsb: Attempting to recover from uncorrectable read\n");
+	printk(KERN_INFO "%s: Attempting to recover from uncorrectable read\n",
+		__func__);
 	mtd->ecc_stats.failed--;
 
 	/* Issue the LSB page recovery command */
@@ -1046,7 +1085,8 @@
 	int ret = 0;
 	int writesize = this->writesize;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_mlc_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
+	      __func__, (unsigned int) from, (int) len);
 
 	if (ops->mode == MTD_OOB_AUTO)
 		oobsize = this->ecclayout->oobavail;
@@ -1057,7 +1097,8 @@
 
 	/* Do not allow reads past end of device */
 	if (from + len > mtd->size) {
-		printk(KERN_ERR "onenand_mlc_read_ops_nolock: Attempt read beyond end of device\n");
+		printk(KERN_ERR "%s: Attempt read beyond end of device\n",
+			__func__);
 		ops->retlen = 0;
 		ops->oobretlen = 0;
 		return -EINVAL;
@@ -1146,7 +1187,8 @@
 	int ret = 0, boundary = 0;
 	int writesize = this->writesize;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
+			__func__, (unsigned int) from, (int) len);
 
 	if (ops->mode == MTD_OOB_AUTO)
 		oobsize = this->ecclayout->oobavail;
@@ -1157,7 +1199,8 @@
 
 	/* Do not allow reads past end of device */
 	if ((from + len) > mtd->size) {
-		printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
+		printk(KERN_ERR "%s: Attempt read beyond end of device\n",
+			__func__);
 		ops->retlen = 0;
 		ops->oobretlen = 0;
 		return -EINVAL;
@@ -1275,7 +1318,8 @@
 
 	from += ops->ooboffs;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %i\n",
+		__func__, (unsigned int) from, (int) len);
 
 	/* Initialize return length value */
 	ops->oobretlen = 0;
@@ -1288,7 +1332,8 @@
 	column = from & (mtd->oobsize - 1);
 
 	if (unlikely(column >= oobsize)) {
-		printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
+		printk(KERN_ERR "%s: Attempted to start read outside oob\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -1296,7 +1341,8 @@
 	if (unlikely(from >= mtd->size ||
 		     column + len > ((mtd->size >> this->page_shift) -
 				     (from >> this->page_shift)) * oobsize)) {
-		printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
+		printk(KERN_ERR "%s: Attempted to read beyond end of device\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -1319,7 +1365,8 @@
 			ret = onenand_recover_lsb(mtd, from, ret);
 
 		if (ret && ret != -EBADMSG) {
-			printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
+			printk(KERN_ERR "%s: read failed = 0x%x\n",
+				__func__, ret);
 			break;
 		}
 
@@ -1450,20 +1497,21 @@
 	if (interrupt & ONENAND_INT_READ) {
 		int ecc = onenand_read_ecc(this);
 		if (ecc & ONENAND_ECC_2BIT_ALL) {
-			printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
-				", controller error 0x%04x\n", ecc, ctrl);
+			printk(KERN_WARNING "%s: ecc error = 0x%04x, "
+				"controller error 0x%04x\n",
+				__func__, ecc, ctrl);
 			return ONENAND_BBT_READ_ECC_ERROR;
 		}
 	} else {
-		printk(KERN_ERR "onenand_bbt_wait: read timeout!"
-			"ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
+		printk(KERN_ERR "%s: read timeout! ctrl=0x%04x intr=0x%04x\n",
+			__func__, ctrl, interrupt);
 		return ONENAND_BBT_READ_FATAL_ERROR;
 	}
 
 	/* Initial bad block case: 0x2400 or 0x0400 */
 	if (ctrl & ONENAND_CTRL_ERROR) {
-		printk(KERN_DEBUG "onenand_bbt_wait: "
-			"controller error = 0x%04x\n", ctrl);
+		printk(KERN_DEBUG "%s: controller error = 0x%04x\n",
+			__func__, ctrl);
 		return ONENAND_BBT_READ_ERROR;
 	}
 
@@ -1487,14 +1535,16 @@
 	size_t len = ops->ooblen;
 	u_char *buf = ops->oobbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08x, len = %zi\n",
+		__func__, (unsigned int) from, len);
 
 	/* Initialize return value */
 	ops->oobretlen = 0;
 
 	/* Do not allow reads past end of device */
 	if (unlikely((from + len) > mtd->size)) {
-		printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
+		printk(KERN_ERR "%s: Attempt read beyond end of device\n",
+			__func__);
 		return ONENAND_BBT_READ_FATAL_ERROR;
 	}
 
@@ -1661,21 +1711,23 @@
 	/* Wait for any existing operation to clear */
 	onenand_panic_wait(mtd);
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_panic_write: to = 0x%08x, len = %i\n",
-	      (unsigned int) to, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+		__func__, (unsigned int) to, (int) len);
 
 	/* Initialize retlen, in case of early exit */
 	*retlen = 0;
 
 	/* Do not allow writes past end of device */
 	if (unlikely((to + len) > mtd->size)) {
-		printk(KERN_ERR "onenand_panic_write: Attempt write to past end of device\n");
+		printk(KERN_ERR "%s: Attempt write to past end of device\n",
+			__func__);
 		return -EINVAL;
 	}
 
 	/* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
-                printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n");
+		printk(KERN_ERR "%s: Attempt to write not page aligned data\n",
+			__func__);
                 return -EINVAL;
         }
 
@@ -1711,7 +1763,7 @@
 		}
 
 		if (ret) {
-			printk(KERN_ERR "onenand_panic_write: write failed %d\n", ret);
+			printk(KERN_ERR "%s: write failed %d\n", __func__, ret);
 			break;
 		}
 
@@ -1792,7 +1844,8 @@
 	u_char *oobbuf;
 	int ret = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+		__func__, (unsigned int) to, (int) len);
 
 	/* Initialize retlen, in case of early exit */
 	ops->retlen = 0;
@@ -1800,13 +1853,15 @@
 
 	/* Do not allow writes past end of device */
 	if (unlikely((to + len) > mtd->size)) {
-		printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
+		printk(KERN_ERR "%s: Attempt write to past end of device\n",
+			__func__);
 		return -EINVAL;
 	}
 
 	/* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
-                printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
+		printk(KERN_ERR "%s: Attempt to write not page aligned data\n",
+			__func__);
                 return -EINVAL;
         }
 
@@ -1879,7 +1934,8 @@
 			onenand_update_bufferram(mtd, prev, !ret && !prev_subpage);
 			if (ret) {
 				written -= prevlen;
-				printk(KERN_ERR "onenand_write_ops_nolock: write failed %d\n", ret);
+				printk(KERN_ERR "%s: write failed %d\n",
+					__func__, ret);
 				break;
 			}
 
@@ -1887,7 +1943,8 @@
 				/* Only check verify write turn on */
 				ret = onenand_verify(mtd, buf - len, to - len, len);
 				if (ret)
-					printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
+					printk(KERN_ERR "%s: verify failed %d\n",
+						__func__, ret);
 				break;
 			}
 
@@ -1905,14 +1962,16 @@
 			/* In partial page write we don't update bufferram */
 			onenand_update_bufferram(mtd, to, !ret && !subpage);
 			if (ret) {
-				printk(KERN_ERR "onenand_write_ops_nolock: write failed %d\n", ret);
+				printk(KERN_ERR "%s: write failed %d\n",
+					__func__, ret);
 				break;
 			}
 
 			/* Only check verify write turn on */
 			ret = onenand_verify(mtd, buf, to, thislen);
 			if (ret) {
-				printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
+				printk(KERN_ERR "%s: verify failed %d\n",
+					__func__, ret);
 				break;
 			}
 
@@ -1968,7 +2027,8 @@
 
 	to += ops->ooboffs;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+		__func__, (unsigned int) to, (int) len);
 
 	/* Initialize retlen, in case of early exit */
 	ops->oobretlen = 0;
@@ -1981,14 +2041,15 @@
 	column = to & (mtd->oobsize - 1);
 
 	if (unlikely(column >= oobsize)) {
-		printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
+		printk(KERN_ERR "%s: Attempted to start write outside oob\n",
+			__func__);
 		return -EINVAL;
 	}
 
 	/* For compatibility with NAND: Do not allow write past end of page */
 	if (unlikely(column + len > oobsize)) {
-		printk(KERN_ERR "onenand_write_oob_nolock: "
-		      "Attempt to write past end of page\n");
+		printk(KERN_ERR "%s: Attempt to write past end of page\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -1996,7 +2057,8 @@
 	if (unlikely(to >= mtd->size ||
 		     column + len > ((mtd->size >> this->page_shift) -
 				     (to >> this->page_shift)) * oobsize)) {
-		printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
+		printk(KERN_ERR "%s: Attempted to write past end of device\n",
+		       __func__);
 		return -EINVAL;
 	}
 
@@ -2038,13 +2100,14 @@
 
 		ret = this->wait(mtd, FL_WRITING);
 		if (ret) {
-			printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
+			printk(KERN_ERR "%s: write failed %d\n", __func__, ret);
 			break;
 		}
 
 		ret = onenand_verify_oob(mtd, oobbuf, to);
 		if (ret) {
-			printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
+			printk(KERN_ERR "%s: verify failed %d\n",
+				__func__, ret);
 			break;
 		}
 
@@ -2140,78 +2203,186 @@
 	return bbm->isbad_bbt(mtd, ofs, allowbbt);
 }
 
-/**
- * onenand_erase - [MTD Interface] erase block(s)
- * @param mtd		MTD device structure
- * @param instr		erase instruction
- *
- * Erase one ore more blocks
- */
-static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+
+static int onenand_multiblock_erase_verify(struct mtd_info *mtd,
+					   struct erase_info *instr)
 {
 	struct onenand_chip *this = mtd->priv;
-	unsigned int block_size;
 	loff_t addr = instr->addr;
-	loff_t len = instr->len;
-	int ret = 0, i;
-	struct mtd_erase_region_info *region = NULL;
-	loff_t region_end = 0;
+	int len = instr->len;
+	unsigned int block_size = (1 << this->erase_shift);
+	int ret = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
-
-	/* Do not allow erase past end of device */
-	if (unlikely((len + addr) > mtd->size)) {
-		printk(KERN_ERR "onenand_erase: Erase past end of device\n");
-		return -EINVAL;
-	}
-
-	if (FLEXONENAND(this)) {
-		/* Find the eraseregion of this address */
-		i = flexonenand_region(mtd, addr);
-		region = &mtd->eraseregions[i];
-
-		block_size = region->erasesize;
-		region_end = region->offset + region->erasesize * region->numblocks;
-
-		/* Start address within region must align on block boundary.
-		 * Erase region's start offset is always block start address.
-		 */
-		if (unlikely((addr - region->offset) & (block_size - 1))) {
-			printk(KERN_ERR "onenand_erase: Unaligned address\n");
-			return -EINVAL;
+	while (len) {
+		this->command(mtd, ONENAND_CMD_ERASE_VERIFY, addr, block_size);
+		ret = this->wait(mtd, FL_VERIFYING_ERASE);
+		if (ret) {
+			printk(KERN_ERR "%s: Failed verify, block %d\n",
+			       __func__, onenand_block(this, addr));
+			instr->state = MTD_ERASE_FAILED;
+			instr->fail_addr = addr;
+			return -1;
 		}
-	} else {
-		block_size = 1 << this->erase_shift;
-
-		/* Start address must align on block boundary */
-		if (unlikely(addr & (block_size - 1))) {
-			printk(KERN_ERR "onenand_erase: Unaligned address\n");
-			return -EINVAL;
-		}
+		len -= block_size;
+		addr += block_size;
 	}
+	return 0;
+}
 
-	/* Length must align on block boundary */
-	if (unlikely(len & (block_size - 1))) {
-		printk(KERN_ERR "onenand_erase: Length not block aligned\n");
-		return -EINVAL;
-	}
+/**
+ * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase
+ * @param mtd		MTD device structure
+ * @param instr		erase instruction
+ * @param region	erase region
+ *
+ * Erase one or more blocks up to 64 block at a time
+ */
+static int onenand_multiblock_erase(struct mtd_info *mtd,
+				    struct erase_info *instr,
+				    unsigned int block_size)
+{
+	struct onenand_chip *this = mtd->priv;
+	loff_t addr = instr->addr;
+	int len = instr->len;
+	int eb_count = 0;
+	int ret = 0;
+	int bdry_block = 0;
 
-	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
-
-	/* Grab the lock and see if the device is available */
-	onenand_get_device(mtd, FL_ERASING);
-
-	/* Loop through the blocks */
 	instr->state = MTD_ERASING;
 
+	if (ONENAND_IS_DDP(this)) {
+		loff_t bdry_addr = this->chipsize >> 1;
+		if (addr < bdry_addr && (addr + len) > bdry_addr)
+			bdry_block = bdry_addr >> this->erase_shift;
+	}
+
+	/* Pre-check bbs */
+	while (len) {
+		/* Check if we have a bad block, we do not erase bad blocks */
+		if (onenand_block_isbad_nolock(mtd, addr, 0)) {
+			printk(KERN_WARNING "%s: attempt to erase a bad block "
+			       "at addr 0x%012llx\n",
+			       __func__, (unsigned long long) addr);
+			instr->state = MTD_ERASE_FAILED;
+			return -EIO;
+		}
+		len -= block_size;
+		addr += block_size;
+	}
+
+	len = instr->len;
+	addr = instr->addr;
+
+	/* loop over 64 eb batches */
+	while (len) {
+		struct erase_info verify_instr = *instr;
+		int max_eb_count = MB_ERASE_MAX_BLK_COUNT;
+
+		verify_instr.addr = addr;
+		verify_instr.len = 0;
+
+		/* do not cross chip boundary */
+		if (bdry_block) {
+			int this_block = (addr >> this->erase_shift);
+
+			if (this_block < bdry_block) {
+				max_eb_count = min(max_eb_count,
+						   (bdry_block - this_block));
+			}
+		}
+
+		eb_count = 0;
+
+		while (len > block_size && eb_count < (max_eb_count - 1)) {
+			this->command(mtd, ONENAND_CMD_MULTIBLOCK_ERASE,
+				      addr, block_size);
+			onenand_invalidate_bufferram(mtd, addr, block_size);
+
+			ret = this->wait(mtd, FL_PREPARING_ERASE);
+			if (ret) {
+				printk(KERN_ERR "%s: Failed multiblock erase, "
+				       "block %d\n", __func__,
+				       onenand_block(this, addr));
+				instr->state = MTD_ERASE_FAILED;
+				instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+				return -EIO;
+			}
+
+			len -= block_size;
+			addr += block_size;
+			eb_count++;
+		}
+
+		/* last block of 64-eb series */
+		cond_resched();
+		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
+		onenand_invalidate_bufferram(mtd, addr, block_size);
+
+		ret = this->wait(mtd, FL_ERASING);
+		/* Check if it is write protected */
+		if (ret) {
+			printk(KERN_ERR "%s: Failed erase, block %d\n",
+			       __func__, onenand_block(this, addr));
+			instr->state = MTD_ERASE_FAILED;
+			instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+			return -EIO;
+		}
+
+		len -= block_size;
+		addr += block_size;
+		eb_count++;
+
+		/* verify */
+		verify_instr.len = eb_count * block_size;
+		if (onenand_multiblock_erase_verify(mtd, &verify_instr)) {
+			instr->state = verify_instr.state;
+			instr->fail_addr = verify_instr.fail_addr;
+			return -EIO;
+		}
+
+	}
+	return 0;
+}
+
+
+/**
+ * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
+ * @param mtd		MTD device structure
+ * @param instr		erase instruction
+ * @param region	erase region
+ * @param block_size	erase block size
+ *
+ * Erase one or more blocks one block at a time
+ */
+static int onenand_block_by_block_erase(struct mtd_info *mtd,
+					struct erase_info *instr,
+					struct mtd_erase_region_info *region,
+					unsigned int block_size)
+{
+	struct onenand_chip *this = mtd->priv;
+	loff_t addr = instr->addr;
+	int len = instr->len;
+	loff_t region_end = 0;
+	int ret = 0;
+
+	if (region) {
+		/* region is set for Flex-OneNAND */
+		region_end = region->offset + region->erasesize * region->numblocks;
+	}
+
+	instr->state = MTD_ERASING;
+
+	/* Loop through the blocks */
 	while (len) {
 		cond_resched();
 
 		/* Check if we have a bad block, we do not erase bad blocks */
 		if (onenand_block_isbad_nolock(mtd, addr, 0)) {
-			printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr);
+			printk(KERN_WARNING "%s: attempt to erase a bad block "
+					"at addr 0x%012llx\n",
+					__func__, (unsigned long long) addr);
 			instr->state = MTD_ERASE_FAILED;
-			goto erase_exit;
+			return -EIO;
 		}
 
 		this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
@@ -2221,11 +2392,11 @@
 		ret = this->wait(mtd, FL_ERASING);
 		/* Check, if it is write protected */
 		if (ret) {
-			printk(KERN_ERR "onenand_erase: Failed erase, block %d\n",
-						 onenand_block(this, addr));
+			printk(KERN_ERR "%s: Failed erase, block %d\n",
+				__func__, onenand_block(this, addr));
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr = addr;
-			goto erase_exit;
+			return -EIO;
 		}
 
 		len -= block_size;
@@ -2241,25 +2412,88 @@
 
 			if (len & (block_size - 1)) {
 				/* FIXME: This should be handled at MTD partitioning level. */
-				printk(KERN_ERR "onenand_erase: Unaligned address\n");
-				goto erase_exit;
+				printk(KERN_ERR "%s: Unaligned address\n",
+					__func__);
+				return -EIO;
 			}
 		}
+	}
+	return 0;
+}
 
+/**
+ * onenand_erase - [MTD Interface] erase block(s)
+ * @param mtd		MTD device structure
+ * @param instr		erase instruction
+ *
+ * Erase one or more blocks
+ */
+static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned int block_size;
+	loff_t addr = instr->addr;
+	loff_t len = instr->len;
+	int ret = 0;
+	struct mtd_erase_region_info *region = NULL;
+	loff_t region_offset = 0;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: start=0x%012llx, len=%llu\n", __func__,
+	      (unsigned long long) instr->addr, (unsigned long long) instr->len);
+
+	/* Do not allow erase past end of device */
+	if (unlikely((len + addr) > mtd->size)) {
+		printk(KERN_ERR "%s: Erase past end of device\n", __func__);
+		return -EINVAL;
 	}
 
-	instr->state = MTD_ERASE_DONE;
+	if (FLEXONENAND(this)) {
+		/* Find the eraseregion of this address */
+		int i = flexonenand_region(mtd, addr);
 
-erase_exit:
+		region = &mtd->eraseregions[i];
+		block_size = region->erasesize;
 
-	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
+		/* Start address within region must align on block boundary.
+		 * Erase region's start offset is always block start address.
+		 */
+		region_offset = region->offset;
+	} else
+		block_size = 1 << this->erase_shift;
+
+	/* Start address must align on block boundary */
+	if (unlikely((addr - region_offset) & (block_size - 1))) {
+		printk(KERN_ERR "%s: Unaligned address\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Length must align on block boundary */
+	if (unlikely(len & (block_size - 1))) {
+		printk(KERN_ERR "%s: Length not block aligned\n", __func__);
+		return -EINVAL;
+	}
+
+	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+
+	/* Grab the lock and see if the device is available */
+	onenand_get_device(mtd, FL_ERASING);
+
+	if (region || instr->len < MB_ERASE_MIN_BLK_COUNT * block_size) {
+		/* region is set for Flex-OneNAND (no mb erase) */
+		ret = onenand_block_by_block_erase(mtd, instr,
+						   region, block_size);
+	} else {
+		ret = onenand_multiblock_erase(mtd, instr, block_size);
+	}
 
 	/* Deselect and wake up anyone waiting on the device */
 	onenand_release_device(mtd);
 
 	/* Do call back function */
-	if (!ret)
+	if (!ret) {
+		instr->state = MTD_ERASE_DONE;
 		mtd_erase_callback(instr);
+	}
 
 	return ret;
 }
@@ -2272,7 +2506,7 @@
  */
 static void onenand_sync(struct mtd_info *mtd)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
+	DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
 	onenand_get_device(mtd, FL_SYNCING);
@@ -2406,7 +2640,8 @@
 		/* Check lock status */
 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
 		if (!(status & wp_status_mask))
-			printk(KERN_ERR "wp status = 0x%x\n", status);
+			printk(KERN_ERR "%s: wp status = 0x%x\n",
+				__func__, status);
 
 		return 0;
 	}
@@ -2435,7 +2670,8 @@
 		/* Check lock status */
 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
 		if (!(status & wp_status_mask))
-			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
+			printk(KERN_ERR "%s: block = %d, wp status = 0x%x\n",
+				__func__, block, status);
 	}
 
 	return 0;
@@ -2502,7 +2738,8 @@
 		/* Check lock status */
 		status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
 		if (!(status & ONENAND_WP_US)) {
-			printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
+			printk(KERN_ERR "%s: block = %d, wp status = 0x%x\n",
+				__func__, block, status);
 			return 0;
 		}
 	}
@@ -2557,6 +2794,208 @@
 
 #ifdef CONFIG_MTD_ONENAND_OTP
 
+/**
+ * onenand_otp_command - Send OTP specific command to OneNAND device
+ * @param mtd	 MTD device structure
+ * @param cmd	 the command to be sent
+ * @param addr	 offset to read from or write to
+ * @param len	 number of bytes to read or write
+ */
+static int onenand_otp_command(struct mtd_info *mtd, int cmd, loff_t addr,
+				size_t len)
+{
+	struct onenand_chip *this = mtd->priv;
+	int value, block, page;
+
+	/* Address translation */
+	switch (cmd) {
+	case ONENAND_CMD_OTP_ACCESS:
+		block = (int) (addr >> this->erase_shift);
+		page = -1;
+		break;
+
+	default:
+		block = (int) (addr >> this->erase_shift);
+		page = (int) (addr >> this->page_shift);
+
+		if (ONENAND_IS_2PLANE(this)) {
+			/* Make the even block number */
+			block &= ~1;
+			/* Is it the odd plane? */
+			if (addr & this->writesize)
+				block++;
+			page >>= 1;
+		}
+		page &= this->page_mask;
+		break;
+	}
+
+	if (block != -1) {
+		/* Write 'DFS, FBA' of Flash */
+		value = onenand_block_address(this, block);
+		this->write_word(value, this->base +
+				ONENAND_REG_START_ADDRESS1);
+	}
+
+	if (page != -1) {
+		/* Now we use page size operation */
+		int sectors = 4, count = 4;
+		int dataram;
+
+		switch (cmd) {
+		default:
+			if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
+				cmd = ONENAND_CMD_2X_PROG;
+			dataram = ONENAND_CURRENT_BUFFERRAM(this);
+			break;
+		}
+
+		/* Write 'FPA, FSA' of Flash */
+		value = onenand_page_address(page, sectors);
+		this->write_word(value, this->base +
+				ONENAND_REG_START_ADDRESS8);
+
+		/* Write 'BSA, BSC' of DataRAM */
+		value = onenand_buffer_address(dataram, sectors, count);
+		this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
+	}
+
+	/* Interrupt clear */
+	this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
+
+	/* Write command */
+	this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
+
+	return 0;
+}
+
+/**
+ * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP
+ * @param mtd		MTD device structure
+ * @param to		offset to write to
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of written bytes
+ * @param buf		the data to write
+ *
+ * OneNAND write out-of-band only for OTP
+ */
+static int onenand_otp_write_oob_nolock(struct mtd_info *mtd, loff_t to,
+				    struct mtd_oob_ops *ops)
+{
+	struct onenand_chip *this = mtd->priv;
+	int column, ret = 0, oobsize;
+	int written = 0;
+	u_char *oobbuf;
+	size_t len = ops->ooblen;
+	const u_char *buf = ops->oobbuf;
+	int block, value, status;
+
+	to += ops->ooboffs;
+
+	/* Initialize retlen, in case of early exit */
+	ops->oobretlen = 0;
+
+	oobsize = mtd->oobsize;
+
+	column = to & (mtd->oobsize - 1);
+
+	oobbuf = this->oob_buf;
+
+	/* Loop until all data write */
+	while (written < len) {
+		int thislen = min_t(int, oobsize, len - written);
+
+		cond_resched();
+
+		block = (int) (to >> this->erase_shift);
+		/*
+		 * Write 'DFS, FBA' of Flash
+		 * Add: F100h DQ=DFS, FBA
+		 */
+
+		value = onenand_block_address(this, block);
+		this->write_word(value, this->base +
+				ONENAND_REG_START_ADDRESS1);
+
+		/*
+		 * Select DataRAM for DDP
+		 * Add: F101h DQ=DBS
+		 */
+
+		value = onenand_bufferram_address(this, block);
+		this->write_word(value, this->base +
+				ONENAND_REG_START_ADDRESS2);
+		ONENAND_SET_NEXT_BUFFERRAM(this);
+
+		/*
+		 * Enter OTP access mode
+		 */
+		this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+		this->wait(mtd, FL_OTPING);
+
+		/* We send data to spare ram with oobsize
+		 * to prevent byte access */
+		memcpy(oobbuf + column, buf, thislen);
+
+		/*
+		 * Write Data into DataRAM
+		 * Add: 8th Word
+		 * in sector0/spare/page0
+		 * DQ=XXFCh
+		 */
+		this->write_bufferram(mtd, ONENAND_SPARERAM,
+					oobbuf, 0, mtd->oobsize);
+
+		onenand_otp_command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
+		onenand_update_bufferram(mtd, to, 0);
+		if (ONENAND_IS_2PLANE(this)) {
+			ONENAND_SET_BUFFERRAM1(this);
+			onenand_update_bufferram(mtd, to + this->writesize, 0);
+		}
+
+		ret = this->wait(mtd, FL_WRITING);
+		if (ret) {
+			printk(KERN_ERR "%s: write failed %d\n", __func__, ret);
+			break;
+		}
+
+		/* Exit OTP access mode */
+		this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+		this->wait(mtd, FL_RESETING);
+
+		status = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+		status &= 0x60;
+
+		if (status == 0x60) {
+			printk(KERN_DEBUG "\nBLOCK\tSTATUS\n");
+			printk(KERN_DEBUG "1st Block\tLOCKED\n");
+			printk(KERN_DEBUG "OTP Block\tLOCKED\n");
+		} else if (status == 0x20) {
+			printk(KERN_DEBUG "\nBLOCK\tSTATUS\n");
+			printk(KERN_DEBUG "1st Block\tLOCKED\n");
+			printk(KERN_DEBUG "OTP Block\tUN-LOCKED\n");
+		} else if (status == 0x40) {
+			printk(KERN_DEBUG "\nBLOCK\tSTATUS\n");
+			printk(KERN_DEBUG "1st Block\tUN-LOCKED\n");
+			printk(KERN_DEBUG "OTP Block\tLOCKED\n");
+		} else {
+			printk(KERN_DEBUG "Reboot to check\n");
+		}
+
+		written += thislen;
+		if (written == len)
+			break;
+
+		to += mtd->writesize;
+		buf += thislen;
+		column = 0;
+	}
+
+	ops->oobretlen = written;
+
+	return ret;
+}
+
 /* Internal OTP operation */
 typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
 		size_t *retlen, u_char *buf);
@@ -2659,11 +3098,11 @@
 	struct mtd_oob_ops ops;
 	int ret;
 
-	/* Enter OTP access mode */
-	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
-	this->wait(mtd, FL_OTPING);
-
 	if (FLEXONENAND(this)) {
+
+		/* Enter OTP access mode */
+		this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+		this->wait(mtd, FL_OTPING);
 		/*
 		 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
 		 * main area of page 49.
@@ -2674,19 +3113,19 @@
 		ops.oobbuf = NULL;
 		ret = onenand_write_ops_nolock(mtd, mtd->writesize * 49, &ops);
 		*retlen = ops.retlen;
+
+		/* Exit OTP access mode */
+		this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+		this->wait(mtd, FL_RESETING);
 	} else {
 		ops.mode = MTD_OOB_PLACE;
 		ops.ooblen = len;
 		ops.oobbuf = buf;
 		ops.ooboffs = 0;
-		ret = onenand_write_oob_nolock(mtd, from, &ops);
+		ret = onenand_otp_write_oob_nolock(mtd, from, &ops);
 		*retlen = ops.oobretlen;
 	}
 
-	/* Exit OTP access mode */
-	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-	this->wait(mtd, FL_RESETING);
-
 	return ret;
 }
 
@@ -2717,16 +3156,21 @@
 	if (density < ONENAND_DEVICE_DENSITY_512Mb)
 		otp_pages = 20;
 	else
-		otp_pages = 10;
+		otp_pages = 50;
 
 	if (mode == MTD_OTP_FACTORY) {
 		from += mtd->writesize * otp_pages;
-		otp_pages = 64 - otp_pages;
+		otp_pages = ONENAND_PAGES_PER_BLOCK - otp_pages;
 	}
 
 	/* Check User/Factory boundary */
-	if (((mtd->writesize * otp_pages) - (from + len)) < 0)
-		return 0;
+	if (mode == MTD_OTP_USER) {
+		if (mtd->writesize * otp_pages < from + len)
+			return 0;
+	} else {
+		if (mtd->writesize * otp_pages <  len)
+			return 0;
+	}
 
 	onenand_get_device(mtd, FL_OTPING);
 	while (len > 0 && otp_pages > 0) {
@@ -2749,13 +3193,12 @@
 			*retlen += sizeof(struct otp_info);
 		} else {
 			size_t tmp_retlen;
-			int size = len;
 
 			ret = action(mtd, from, len, &tmp_retlen, buf);
 
-			buf += size;
-			len -= size;
-			*retlen += size;
+			buf += tmp_retlen;
+			len -= tmp_retlen;
+			*retlen += tmp_retlen;
 
 			if (ret)
 				break;
@@ -2868,21 +3311,11 @@
 	u_char *buf = FLEXONENAND(this) ? this->page_buf : this->oob_buf;
 	size_t retlen;
 	int ret;
+	unsigned int otp_lock_offset = ONENAND_OTP_LOCK_OFFSET;
 
 	memset(buf, 0xff, FLEXONENAND(this) ? this->writesize
 						 : mtd->oobsize);
 	/*
-	 * Note: OTP lock operation
-	 *       OTP block : 0xXXFC
-	 *       1st block : 0xXXF3 (If chip support)
-	 *       Both      : 0xXXF0 (If chip support)
-	 */
-	if (FLEXONENAND(this))
-		buf[FLEXONENAND_OTP_LOCK_OFFSET] = 0xFC;
-	else
-		buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
-
-	/*
 	 * Write lock mark to 8th word of sector0 of page0 of the spare0.
 	 * We write 16 bytes spare area instead of 2 bytes.
 	 * For Flex-OneNAND, we write lock mark to 1st word of sector 4 of
@@ -2892,10 +3325,30 @@
 	from = 0;
 	len = FLEXONENAND(this) ? mtd->writesize : 16;
 
+	/*
+	 * Note: OTP lock operation
+	 *       OTP block : 0xXXFC			XX 1111 1100
+	 *       1st block : 0xXXF3 (If chip support)	XX 1111 0011
+	 *       Both      : 0xXXF0 (If chip support)	XX 1111 0000
+	 */
+	if (FLEXONENAND(this))
+		otp_lock_offset = FLEXONENAND_OTP_LOCK_OFFSET;
+
+	/* ONENAND_OTP_AREA | ONENAND_OTP_BLOCK0 | ONENAND_OTP_AREA_BLOCK0 */
+	if (otp == 1)
+		buf[otp_lock_offset] = 0xFC;
+	else if (otp == 2)
+		buf[otp_lock_offset] = 0xF3;
+	else if (otp == 3)
+		buf[otp_lock_offset] = 0xF0;
+	else if (otp != 0)
+		printk(KERN_DEBUG "[OneNAND] Invalid option selected for OTP\n");
+
 	ret = onenand_otp_walk(mtd, from, len, &retlen, buf, do_otp_lock, MTD_OTP_USER);
 
 	return ret ? : retlen;
 }
+
 #endif	/* CONFIG_MTD_ONENAND_OTP */
 
 /**
@@ -3172,7 +3625,8 @@
 				break;
 
 		if (i != mtd->oobsize) {
-			printk(KERN_WARNING "Block %d not erased.\n", block);
+			printk(KERN_WARNING "%s: Block %d not erased.\n",
+				__func__, block);
 			return 1;
 		}
 	}
@@ -3204,8 +3658,8 @@
 	blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
 
 	if (boundary >= blksperdie) {
-		printk(KERN_ERR "flexonenand_set_boundary: Invalid boundary value. "
-				"Boundary not changed.\n");
+		printk(KERN_ERR "%s: Invalid boundary value. "
+				"Boundary not changed.\n", __func__);
 		return -EINVAL;
 	}
 
@@ -3214,7 +3668,8 @@
 	new = boundary + (die * this->density_mask);
 	ret = flexonenand_check_blocks_erased(mtd, min(old, new) + 1, max(old, new));
 	if (ret) {
-		printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
+		printk(KERN_ERR "%s: Please erase blocks "
+				"before boundary change\n", __func__);
 		return ret;
 	}
 
@@ -3227,12 +3682,12 @@
 
 	thisboundary = this->read_word(this->base + ONENAND_DATARAM);
 	if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
-		printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
+		printk(KERN_ERR "%s: boundary locked\n", __func__);
 		ret = 1;
 		goto out;
 	}
 
-	printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
+	printk(KERN_INFO "Changing die %d boundary: %d%s\n",
 			die, boundary, lock ? "(Locked)" : "(Unlocked)");
 
 	addr = die ? this->diesize[0] : 0;
@@ -3243,7 +3698,8 @@
 	this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
 	ret = this->wait(mtd, FL_ERASING);
 	if (ret) {
-		printk(KERN_ERR "flexonenand_set_boundary: Failed PI erase for Die %d\n", die);
+		printk(KERN_ERR "%s: Failed PI erase for Die %d\n",
+		       __func__, die);
 		goto out;
 	}
 
@@ -3251,7 +3707,8 @@
 	this->command(mtd, ONENAND_CMD_PROG, addr, 0);
 	ret = this->wait(mtd, FL_WRITING);
 	if (ret) {
-		printk(KERN_ERR "flexonenand_set_boundary: Failed PI write for Die %d\n", die);
+		printk(KERN_ERR "%s: Failed PI write for Die %d\n",
+			__func__, die);
 		goto out;
 	}
 
@@ -3408,8 +3865,8 @@
 	if (this->state == FL_PM_SUSPENDED)
 		onenand_release_device(mtd);
 	else
-		printk(KERN_ERR "resume() called for the chip which is not"
-				"in suspended state\n");
+		printk(KERN_ERR "%s: resume() called for the chip which is not "
+				"in suspended state\n", __func__);
 }
 
 /**
@@ -3464,7 +3921,8 @@
 	if (!this->page_buf) {
 		this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
 		if (!this->page_buf) {
-			printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
+			printk(KERN_ERR "%s: Can't allocate page_buf\n",
+				__func__);
 			return -ENOMEM;
 		}
 		this->options |= ONENAND_PAGEBUF_ALLOC;
@@ -3472,7 +3930,8 @@
 	if (!this->oob_buf) {
 		this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
 		if (!this->oob_buf) {
-			printk(KERN_ERR "onenand_scan(): Can't allocate oob_buf\n");
+			printk(KERN_ERR "%s: Can't allocate oob_buf\n",
+				__func__);
 			if (this->options & ONENAND_PAGEBUF_ALLOC) {
 				this->options &= ~ONENAND_PAGEBUF_ALLOC;
 				kfree(this->page_buf);
@@ -3505,8 +3964,8 @@
 		break;
 
 	default:
-		printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
-			mtd->oobsize);
+		printk(KERN_WARNING "%s: No OOB scheme defined for oobsize %d\n",
+			__func__, mtd->oobsize);
 		mtd->subpage_sft = 0;
 		/* To prevent kernel oops */
 		this->ecclayout = &onenand_oob_32;
diff --git a/drivers/mtd/tests/Makefile b/drivers/mtd/tests/Makefile
index c1d5013..b44dcab 100644
--- a/drivers/mtd/tests/Makefile
+++ b/drivers/mtd/tests/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o
 obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
new file mode 100644
index 0000000..c1f3105
--- /dev/null
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -0,0 +1,87 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/mtd/nand_ecc.h>
+
+#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
+
+static void inject_single_bit_error(void *data, size_t size)
+{
+	unsigned long offset = random32() % (size * BITS_PER_BYTE);
+
+	__change_bit(offset, data);
+}
+
+static unsigned char data[512];
+static unsigned char error_data[512];
+
+static int nand_ecc_test(const size_t size)
+{
+	unsigned char code[3];
+	unsigned char error_code[3];
+	char testname[30];
+
+	BUG_ON(sizeof(data) < size);
+
+	sprintf(testname, "nand-ecc-%zu", size);
+
+	get_random_bytes(data, size);
+
+	memcpy(error_data, data, size);
+	inject_single_bit_error(error_data, size);
+
+	__nand_calculate_ecc(data, size, code);
+	__nand_calculate_ecc(error_data, size, error_code);
+	__nand_correct_data(error_data, code, error_code, size);
+
+	if (!memcmp(data, error_data, size)) {
+		printk(KERN_INFO "mtd_nandecctest: ok - %s\n", testname);
+		return 0;
+	}
+
+	printk(KERN_ERR "mtd_nandecctest: not ok - %s\n", testname);
+
+	printk(KERN_DEBUG "hexdump of data:\n");
+	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
+			data, size, false);
+	printk(KERN_DEBUG "hexdump of error data:\n");
+	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
+			error_data, size, false);
+
+	return -1;
+}
+
+#else
+
+static int nand_ecc_test(const size_t size)
+{
+	return 0;
+}
+
+#endif
+
+static int __init ecc_test_init(void)
+{
+	srandom32(jiffies);
+
+	nand_ecc_test(256);
+	nand_ecc_test(512);
+
+	return 0;
+}
+
+static void __exit ecc_test_exit(void)
+{
+}
+
+module_init(ecc_test_init);
+module_exit(ecc_test_exit);
+
+MODULE_DESCRIPTION("NAND ECC function test module");
+MODULE_AUTHOR("Akinobu Mita");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
index 5553cd4..5813920 100644
--- a/drivers/mtd/tests/mtd_oobtest.c
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -343,7 +343,6 @@
 		printk(PRINT_PREF "error: cannot allocate memory\n");
 		return -ENOMEM;
 	}
-	memset(bbt, 0 , ebcnt);
 
 	printk(PRINT_PREF "scanning for bad eraseblocks\n");
 	for (i = 0; i < ebcnt; ++i) {
@@ -392,7 +391,6 @@
 	       mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
 
 	err = -ENOMEM;
-	mtd->erasesize = mtd->erasesize;
 	readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!readbuf) {
 		printk(PRINT_PREF "error: cannot allocate memory\n");
@@ -476,18 +474,10 @@
 	use_len_max = mtd->ecclayout->oobavail;
 	vary_offset = 1;
 	simple_srand(5);
-	printk(PRINT_PREF "writing OOBs of whole device\n");
-	for (i = 0; i < ebcnt; ++i) {
-		if (bbt[i])
-			continue;
-		err = write_eraseblock(i);
-		if (err)
-			goto out;
-		if (i % 256 == 0)
-			printk(PRINT_PREF "written up to eraseblock %u\n", i);
-		cond_resched();
-	}
-	printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+	err = write_whole_device();
+	if (err)
+		goto out;
 
 	/* Check all eraseblocks */
 	use_offset = 0;
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
index 103cac4..ce17cbe 100644
--- a/drivers/mtd/tests/mtd_pagetest.c
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -523,6 +523,7 @@
 	do_div(tmp, mtd->erasesize);
 	ebcnt = tmp;
 	pgcnt = mtd->erasesize / mtd->writesize;
+	pgsize = mtd->writesize;
 
 	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
 	       "page size %u, count of eraseblocks %u, pages per "
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index a5be9ac..e58a653 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1953,6 +1953,8 @@
 
 source "drivers/net/fs_enet/Kconfig"
 
+source "drivers/net/octeon/Kconfig"
+
 endif # NET_ETHERNET
 
 #
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 246323d..ad1346d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -285,3 +285,5 @@
 obj-$(CONFIG_SFC) += sfc/
 
 obj-$(CONFIG_WIMAX) += wimax/
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 1f6c548..0bd47d3 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -1245,9 +1245,15 @@
 	drvinfo->n_stats = BCM_ENET_STATS_LEN;
 }
 
-static int bcm_enet_get_stats_count(struct net_device *netdev)
+static int bcm_enet_get_sset_count(struct net_device *netdev,
+					int string_set)
 {
-	return BCM_ENET_STATS_LEN;
+	switch (string_set) {
+	case ETH_SS_STATS:
+		return BCM_ENET_STATS_LEN;
+	default:
+		return -EINVAL;
+	}
 }
 
 static void bcm_enet_get_strings(struct net_device *netdev,
@@ -1473,7 +1479,7 @@
 
 static struct ethtool_ops bcm_enet_ethtool_ops = {
 	.get_strings		= bcm_enet_get_strings,
-	.get_stats_count	= bcm_enet_get_stats_count,
+	.get_sset_count		= bcm_enet_get_sset_count,
 	.get_ethtool_stats      = bcm_enet_get_ethtool_stats,
 	.get_settings		= bcm_enet_get_settings,
 	.set_settings		= bcm_enet_set_settings,
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index d69e683..0fb7a49 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -352,7 +354,8 @@
 		}
 	}
 
-	pr_debug("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
+	pr_debug("Port %d Received link speed %d update from adapter\n",
+		 port->actor_port_number, speed);
 	return speed;
 }
 
@@ -378,12 +381,14 @@
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
 			retval=0x1;
-			pr_debug("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
+			pr_debug("Port %d Received status full duplex update from adapter\n",
+				 port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
 			retval=0x0;
-			pr_debug("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
+			pr_debug("Port %d Received status NOT full duplex update from adapter\n",
+				 port->actor_port_number);
 			break;
 		}
 	}
@@ -980,7 +985,9 @@
 
 	// check if the state machine was changed
 	if (port->sm_mux_state != last_state) {
-		pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
+		pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n",
+			 port->actor_port_number, last_state,
+			 port->sm_mux_state);
 		switch (port->sm_mux_state) {
 		case AD_MUX_DETACHED:
 			__detach_bond_from_agg(port);
@@ -1079,7 +1086,9 @@
 
 	// check if the State machine was changed or new lacpdu arrived
 	if ((port->sm_rx_state != last_state) || (lacpdu)) {
-		pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
+		pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n",
+			 port->actor_port_number, last_state,
+			 port->sm_rx_state);
 		switch (port->sm_rx_state) {
 		case AD_RX_INITIALIZE:
 			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
@@ -1126,9 +1135,8 @@
 			// detect loopback situation
 			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
 				// INFO_RECEIVED_LOOPBACK_FRAMES
-				pr_err(DRV_NAME ": %s: An illegal loopback occurred on "
-				       "adapter (%s). Check the configuration to verify that all "
-				       "Adapters are connected to 802.3ad compliant switch ports\n",
+				pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
+				       "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
 				       port->slave->dev->master->name, port->slave->dev->name);
 				__release_rx_machine_lock(port);
 				return;
@@ -1166,7 +1174,8 @@
 			__update_lacpdu_from_port(port);
 
 			if (ad_lacpdu_send(port) >= 0) {
-				pr_debug("Sent LACPDU on port %d\n", port->actor_port_number);
+				pr_debug("Sent LACPDU on port %d\n",
+					 port->actor_port_number);
 
 				/* mark ntt as false, so it will not be sent again until
 				   demanded */
@@ -1241,7 +1250,9 @@
 
 	// check if the state machine was changed
 	if (port->sm_periodic_state != last_state) {
-		pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
+		pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n",
+			 port->actor_port_number, last_state,
+			 port->sm_periodic_state);
 		switch (port->sm_periodic_state) {
 		case AD_NO_PERIODIC:
 			port->sm_periodic_timer_counter = 0;	   // zero timer
@@ -1298,7 +1309,9 @@
 				port->next_port_in_aggregator=NULL;
 				port->actor_port_aggregator_identifier=0;
 
-				pr_debug("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
+				pr_debug("Port %d left LAG %d\n",
+					 port->actor_port_number,
+					 temp_aggregator->aggregator_identifier);
 				// if the aggregator is empty, clear its parameters, and set it ready to be attached
 				if (!temp_aggregator->lag_ports) {
 					ad_clear_agg(temp_aggregator);
@@ -1307,9 +1320,7 @@
 			}
 		}
 		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-			pr_warning(DRV_NAME ": %s: Warning: Port %d (on %s) "
-				   "was related to aggregator %d but was not "
-				   "on its port list\n",
+			pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
 				   port->slave->dev->master->name,
 				   port->actor_port_number,
 				   port->slave->dev->name,
@@ -1343,7 +1354,9 @@
 			port->next_port_in_aggregator=aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
 			aggregator->lag_ports=port;
-			pr_debug("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+			pr_debug("Port %d joined LAG %d(existing LAG)\n",
+				 port->actor_port_number,
+				 port->aggregator->aggregator_identifier);
 
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
@@ -1380,10 +1393,11 @@
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
 
-			pr_debug("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+			pr_debug("Port %d joined LAG %d(new LAG)\n",
+				 port->actor_port_number,
+				 port->aggregator->aggregator_identifier);
 		} else {
-			pr_err(DRV_NAME ": %s: Port %d (on %s) did not find "
-			       "a suitable aggregator\n",
+			pr_err("%s: Port %d (on %s) did not find a suitable aggregator\n",
 			       port->slave->dev->master->name,
 			       port->actor_port_number, port->slave->dev->name);
 		}
@@ -1460,8 +1474,7 @@
 		break;
 
 	default:
-		pr_warning(DRV_NAME
-			   ": %s: Impossible agg select mode %d\n",
+		pr_warning("%s: Impossible agg select mode %d\n",
 			   curr->slave->dev->master->name,
 			   __get_agg_selection_mode(curr->lag_ports));
 		break;
@@ -1546,40 +1559,38 @@
 	// if there is new best aggregator, activate it
 	if (best) {
 		pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-		       best->aggregator_identifier, best->num_of_ports,
-		       best->actor_oper_aggregator_key,
-		       best->partner_oper_aggregator_key,
-		       best->is_individual, best->is_active);
+			 best->aggregator_identifier, best->num_of_ports,
+			 best->actor_oper_aggregator_key,
+			 best->partner_oper_aggregator_key,
+			 best->is_individual, best->is_active);
 		pr_debug("best ports %p slave %p %s\n",
-		       best->lag_ports, best->slave,
-		       best->slave ? best->slave->dev->name : "NULL");
+			 best->lag_ports, best->slave,
+			 best->slave ? best->slave->dev->name : "NULL");
 
 		for (agg = __get_first_agg(best->lag_ports); agg;
 		     agg = __get_next_agg(agg)) {
 
 			pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-				agg->aggregator_identifier, agg->num_of_ports,
-				agg->actor_oper_aggregator_key,
-				agg->partner_oper_aggregator_key,
-				agg->is_individual, agg->is_active);
+				 agg->aggregator_identifier, agg->num_of_ports,
+				 agg->actor_oper_aggregator_key,
+				 agg->partner_oper_aggregator_key,
+				 agg->is_individual, agg->is_active);
 		}
 
 		// check if any partner replys
 		if (best->is_individual) {
-			pr_warning(DRV_NAME ": %s: Warning: No 802.3ad"
-			       " response from the link partner for any"
-			       " adapters in the bond\n",
-			       best->slave->dev->master->name);
+			pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
+				   best->slave->dev->master->name);
 		}
 
 		best->is_active = 1;
 		pr_debug("LAG %d chosen as the active LAG\n",
-			best->aggregator_identifier);
+			 best->aggregator_identifier);
 		pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
-			best->aggregator_identifier, best->num_of_ports,
-			best->actor_oper_aggregator_key,
-			best->partner_oper_aggregator_key,
-			best->is_individual, best->is_active);
+			 best->aggregator_identifier, best->num_of_ports,
+			 best->actor_oper_aggregator_key,
+			 best->partner_oper_aggregator_key,
+			 best->is_individual, best->is_active);
 
 		// disable the ports that were related to the former active_aggregator
 		if (active) {
@@ -1633,7 +1644,8 @@
 		aggregator->lag_ports = NULL;
 		aggregator->is_active = 0;
 		aggregator->num_of_ports = 0;
-		pr_debug("LAG %d was cleared\n", aggregator->aggregator_identifier);
+		pr_debug("LAG %d was cleared\n",
+			 aggregator->aggregator_identifier);
 	}
 }
 
@@ -1728,7 +1740,9 @@
 static void ad_enable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator->is_active) {
-		pr_debug("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+		pr_debug("Enabling port %d(LAG %d)\n",
+			 port->actor_port_number,
+			 port->aggregator->aggregator_identifier);
 		__enable_port(port);
 	}
 }
@@ -1741,7 +1755,9 @@
 static void ad_disable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
-		pr_debug("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+		pr_debug("Disabling port %d(LAG %d)\n",
+			 port->actor_port_number,
+			 port->aggregator->aggregator_identifier);
 		__disable_port(port);
 	}
 }
@@ -1779,7 +1795,8 @@
 
 	// send the marker information
 	if (ad_marker_send(port, &marker) >= 0) {
-		pr_debug("Sent Marker Information on port %d\n", port->actor_port_number);
+		pr_debug("Sent Marker Information on port %d\n",
+			 port->actor_port_number);
 	}
 }
 #endif
@@ -1803,7 +1820,8 @@
 	// send the marker response
 
 	if (ad_marker_send(port, &marker) >= 0) {
-		pr_debug("Sent Marker Response on port %d\n", port->actor_port_number);
+		pr_debug("Sent Marker Response on port %d\n",
+			 port->actor_port_number);
 	}
 }
 
@@ -1889,8 +1907,7 @@
 	struct aggregator *aggregator;
 
 	if (bond == NULL) {
-		pr_err(DRV_NAME ": %s: The slave %s is not attached to "
-		       "its bond\n",
+		pr_err("%s: The slave %s is not attached to its bond\n",
 		       slave->dev->master->name, slave->dev->name);
 		return -1;
 	}
@@ -1966,13 +1983,13 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		pr_warning(DRV_NAME ": Warning: %s: Trying to "
-			   "unbind an uninitialized port on %s\n",
+		pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n",
 			   slave->dev->master->name, slave->dev->name);
 		return;
 	}
 
-	pr_debug("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
+	pr_debug("Unbinding Link Aggregation Group %d\n",
+		 aggregator->aggregator_identifier);
 
 	/* Tell the partner that this port is not suitable for aggregation */
 	port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -1996,10 +2013,12 @@
 			// if new aggregator found, copy the aggregator's parameters
 			// and connect the related lag_ports to the new aggregator
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
+				pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n",
+					 aggregator->aggregator_identifier,
+					 new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
-					pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+					pr_info("%s: Removing an active aggregator\n",
 						aggregator->slave->dev->master->name);
 					// select new active aggregator
 					 select_new_active_agg = 1;
@@ -2030,8 +2049,7 @@
 					ad_agg_selection_logic(__get_first_agg(port));
 				}
 			} else {
-				pr_warning(DRV_NAME ": %s: Warning: unbinding aggregator, "
-					   "and could not find a new aggregator for its ports\n",
+				pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
 					   slave->dev->master->name);
 			}
 		} else { // in case that the only port related to this aggregator is the one we want to remove
@@ -2039,7 +2057,7 @@
 			// clear the aggregator
 			ad_clear_agg(aggregator);
 			if (select_new_active_agg) {
-				pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+				pr_info("%s: Removing an active aggregator\n",
 					slave->dev->master->name);
 				// select new active aggregator
 				ad_agg_selection_logic(__get_first_agg(port));
@@ -2066,7 +2084,7 @@
 					// clear the aggregator
 					ad_clear_agg(temp_aggregator);
 					if (select_new_active_agg) {
-						pr_info(DRV_NAME ": %s: Removing an active aggregator\n",
+						pr_info("%s: Removing an active aggregator\n",
 							slave->dev->master->name);
 						// select new active aggregator
 						ad_agg_selection_logic(__get_first_agg(port));
@@ -2115,8 +2133,8 @@
 		// select the active aggregator for the bond
 		if ((port = __get_first_port(bond))) {
 			if (!port->slave) {
-				pr_warning(DRV_NAME ": %s: Warning: bond's first port is "
-					   "uninitialized\n", bond->dev->name);
+				pr_warning("%s: Warning: bond's first port is uninitialized\n",
+					   bond->dev->name);
 				goto re_arm;
 			}
 
@@ -2129,8 +2147,8 @@
 	// for each port run the state machines
 	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
 		if (!port->slave) {
-			pr_warning(DRV_NAME ": %s: Warning: Found an uninitialized "
-				   "port\n", bond->dev->name);
+			pr_warning("%s: Warning: Found an uninitialized port\n",
+				   bond->dev->name);
 			goto re_arm;
 		}
 
@@ -2171,15 +2189,15 @@
 		port = &(SLAVE_AD_INFO(slave).port);
 
 		if (!port->slave) {
-			pr_warning(DRV_NAME ": %s: Warning: port of slave %s "
-				   "is uninitialized\n",
+			pr_warning("%s: Warning: port of slave %s is uninitialized\n",
 				   slave->dev->name, slave->dev->master->name);
 			return;
 		}
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
-			pr_debug("Received LACPDU on port %d\n", port->actor_port_number);
+			pr_debug("Received LACPDU on port %d\n",
+				 port->actor_port_number);
 			ad_rx_machine(lacpdu, port);
 			break;
 
@@ -2188,17 +2206,20 @@
 
 			switch (((struct bond_marker *)lacpdu)->tlv_type) {
 			case AD_MARKER_INFORMATION_SUBTYPE:
-				pr_debug("Received Marker Information on port %d\n", port->actor_port_number);
+				pr_debug("Received Marker Information on port %d\n",
+					 port->actor_port_number);
 				ad_marker_info_received((struct bond_marker *)lacpdu, port);
 				break;
 
 			case AD_MARKER_RESPONSE_SUBTYPE:
-				pr_debug("Received Marker Response on port %d\n", port->actor_port_number);
+				pr_debug("Received Marker Response on port %d\n",
+					 port->actor_port_number);
 				ad_marker_response_received((struct bond_marker *)lacpdu, port);
 				break;
 
 			default:
-				pr_debug("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
+				pr_debug("Received an unknown Marker subtype on slot %d\n",
+					 port->actor_port_number);
 			}
 		}
 	}
@@ -2218,8 +2239,7 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		pr_warning(DRV_NAME ": Warning: %s: speed "
-			   "changed for uninitialized port on %s\n",
+		pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
 			   slave->dev->master->name, slave->dev->name);
 		return;
 	}
@@ -2246,8 +2266,7 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		pr_warning(DRV_NAME ": %s: Warning: duplex changed "
-			   "for uninitialized port on %s\n",
+		pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
 			   slave->dev->master->name, slave->dev->name);
 		return;
 	}
@@ -2275,8 +2294,7 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		pr_warning(DRV_NAME ": Warning: %s: link status changed for "
-			   "uninitialized port on %s\n",
+		pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
 			   slave->dev->master->name, slave->dev->name);
 		return;
 	}
@@ -2381,8 +2399,8 @@
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-		pr_debug(DRV_NAME ": %s: Error: "
-			 "bond_3ad_get_active_agg_info failed\n", dev->name);
+		pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n",
+			 dev->name);
 		goto out;
 	}
 
@@ -2391,8 +2409,7 @@
 
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
-		pr_debug(DRV_NAME ": %s: Error: active aggregator is empty\n",
-			 dev->name);
+		pr_debug("%s: Error: active aggregator is empty\n", dev->name);
 		goto out;
 	}
 
@@ -2410,8 +2427,8 @@
 	}
 
 	if (slave_agg_no >= 0) {
-		pr_err(DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
-		       "for aggregator ID %d\n", dev->name, agg_id);
+		pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
+		       dev->name, agg_id);
 		goto out;
 	}
 
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 00ab51e..40fdc41 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -201,8 +203,7 @@
 
 	new_hashtbl = kzalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
-		pr_err(DRV_NAME
-		       ": %s: Error: Failed to allocate TLB hash table\n",
+		pr_err("%s: Error: Failed to allocate TLB hash table\n",
 		       bond->dev->name);
 		return -1;
 	}
@@ -514,8 +515,7 @@
 				 client_info->slave->dev->dev_addr,
 				 client_info->mac_dst);
 		if (!skb) {
-			pr_err(DRV_NAME
-			       ": %s: Error: failed to create an ARP packet\n",
+			pr_err("%s: Error: failed to create an ARP packet\n",
 			       client_info->slave->dev->master->name);
 			continue;
 		}
@@ -525,8 +525,7 @@
 		if (client_info->tag) {
 			skb = vlan_put_tag(skb, client_info->vlan_id);
 			if (!skb) {
-				pr_err(DRV_NAME
-				       ": %s: Error: failed to insert VLAN tag\n",
+				pr_err("%s: Error: failed to insert VLAN tag\n",
 				       client_info->slave->dev->master->name);
 				continue;
 			}
@@ -609,9 +608,7 @@
 		client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 		if (!client_info->slave) {
-			pr_err(DRV_NAME
-			       ": %s: Error: found a client with no channel in "
-			       "the client's hash table\n",
+			pr_err("%s: Error: found a client with no channel in the client's hash table\n",
 			       bond->dev->name);
 			continue;
 		}
@@ -806,8 +803,7 @@
 
 	new_hashtbl = kmalloc(size, GFP_KERNEL);
 	if (!new_hashtbl) {
-		pr_err(DRV_NAME
-		       ": %s: Error: Failed to allocate RLB hash table\n",
+		pr_err("%s: Error: Failed to allocate RLB hash table\n",
 		       bond->dev->name);
 		return -1;
 	}
@@ -928,8 +924,7 @@
 
 			skb = vlan_put_tag(skb, vlan->vlan_id);
 			if (!skb) {
-				pr_err(DRV_NAME
-				       ": %s: Error: failed to insert VLAN tag\n",
+				pr_err("%s: Error: failed to insert VLAN tag\n",
 				       bond->dev->name);
 				continue;
 			}
@@ -958,11 +953,8 @@
 	memcpy(s_addr.sa_data, addr, dev->addr_len);
 	s_addr.sa_family = dev->type;
 	if (dev_set_mac_address(dev, &s_addr)) {
-		pr_err(DRV_NAME
-		       ": %s: Error: dev_set_mac_address of dev %s failed! ALB "
-		       "mode requires that the base driver support setting "
-		       "the hw address also when the network device's "
-		       "interface is open\n",
+		pr_err("%s: Error: dev_set_mac_address of dev %s failed!\n"
+		       "ALB mode requires that the base driver support setting the hw address also when the network device's interface is open\n",
 		       dev->master->name, dev->name);
 		return -EOPNOTSUPP;
 	}
@@ -1169,18 +1161,12 @@
 		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
 				       bond->alb_info.rlb_enabled);
 
-		pr_warning(DRV_NAME
-			   ": %s: Warning: the hw address of slave %s is "
-			   "in use by the bond; giving it the hw address "
-			   "of %s\n",
+		pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
 			   bond->dev->name, slave->dev->name,
 			   free_mac_slave->dev->name);
 
 	} else if (has_bond_addr) {
-		pr_err(DRV_NAME
-		       ": %s: Error: the hw address of slave %s is in use by the "
-		       "bond; couldn't find a slave with a free hw address to "
-		       "give it (this should not have happened)\n",
+		pr_err("%s: Error: the hw address of slave %s is in use by the bond; couldn't find a slave with a free hw address to give it (this should not have happened)\n",
 		       bond->dev->name, slave->dev->name);
 		return -EFAULT;
 	}
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index b72e1dc..6dd64cf 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/if_vlan.h>
 #include <net/ipv6.h>
@@ -74,20 +76,20 @@
 	addrconf_addr_solict_mult(daddr, &mcaddr);
 
 	pr_debug("ipv6 na on slave %s: dest %pI6, src %pI6\n",
-	       slave_dev->name, &mcaddr, daddr);
+		 slave_dev->name, &mcaddr, daddr);
 
 	skb = ndisc_build_skb(slave_dev, &mcaddr, daddr, &icmp6h, daddr,
 			      ND_OPT_TARGET_LL_ADDR);
 
 	if (!skb) {
-		pr_err(DRV_NAME ": NA packet allocation failed\n");
+		pr_err("NA packet allocation failed\n");
 		return;
 	}
 
 	if (vlan_id) {
 		skb = vlan_put_tag(skb, vlan_id);
 		if (!skb) {
-			pr_err(DRV_NAME ": failed to insert VLAN tag\n");
+			pr_err("failed to insert VLAN tag\n");
 			return;
 		}
 	}
@@ -109,8 +111,8 @@
 	struct inet6_dev *idev;
 	int is_router;
 
-	pr_debug("bond_send_unsol_na: bond %s slave %s\n", bond->dev->name,
-				slave ? slave->dev->name : "NULL");
+	pr_debug("%s: bond %s slave %s\n", bond->dev->name,
+		 __func__, slave ? slave->dev->name : "NULL");
 
 	if (!slave || !bond->send_unsol_na ||
 	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index af9b9c4..3f0071c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -31,6 +31,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -260,7 +262,7 @@
 	struct vlan_entry *vlan;
 
 	pr_debug("bond: %s, vlan id %d\n",
-		(bond ? bond->dev->name : "None"), vlan_id);
+		 (bond ? bond->dev->name : "None"), vlan_id);
 
 	vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL);
 	if (!vlan)
@@ -303,8 +305,8 @@
 			if (bond_is_lb(bond))
 				bond_alb_clear_vlan(bond, vlan_id);
 
-			pr_debug("removed VLAN ID %d from bond %s\n", vlan_id,
-				bond->dev->name);
+			pr_debug("removed VLAN ID %d from bond %s\n",
+				 vlan_id, bond->dev->name);
 
 			kfree(vlan);
 
@@ -323,8 +325,8 @@
 		}
 	}
 
-	pr_debug("couldn't find VLAN ID %d in bond %s\n", vlan_id,
-		bond->dev->name);
+	pr_debug("couldn't find VLAN ID %d in bond %s\n",
+		 vlan_id, bond->dev->name);
 
 out:
 	write_unlock_bh(&bond->lock);
@@ -348,7 +350,7 @@
 	bond_for_each_slave(bond, slave, i) {
 		if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
 			pr_debug("found VLAN challenged slave - %s\n",
-				slave->dev->name);
+				 slave->dev->name);
 			return 1;
 		}
 	}
@@ -499,8 +501,7 @@
 
 	res = bond_add_vlan(bond, vid);
 	if (res) {
-		pr_err(DRV_NAME
-		       ": %s: Error: Failed to add vlan id %d\n",
+		pr_err("%s: Error: Failed to add vlan id %d\n",
 		       bond_dev->name, vid);
 	}
 }
@@ -534,8 +535,7 @@
 
 	res = bond_del_vlan(bond, vid);
 	if (res) {
-		pr_err(DRV_NAME
-		       ": %s: Error: Failed to remove vlan id %d\n",
+		pr_err("%s: Error: Failed to remove vlan id %d\n",
 		       bond_dev->name, vid);
 	}
 }
@@ -1053,8 +1053,7 @@
 
 		rv = dev_set_mac_address(new_active->dev, &saddr);
 		if (rv) {
-			pr_err(DRV_NAME
-			       ": %s: Error %d setting MAC of slave %s\n",
+			pr_err("%s: Error %d setting MAC of slave %s\n",
 			       bond->dev->name, -rv, new_active->dev->name);
 			goto out;
 		}
@@ -1067,16 +1066,14 @@
 
 		rv = dev_set_mac_address(old_active->dev, &saddr);
 		if (rv)
-			pr_err(DRV_NAME
-			       ": %s: Error %d setting MAC of slave %s\n",
+			pr_err("%s: Error %d setting MAC of slave %s\n",
 			       bond->dev->name, -rv, new_active->dev->name);
 out:
 		read_lock(&bond->lock);
 		write_lock_bh(&bond->curr_slave_lock);
 		break;
 	default:
-		pr_err(DRV_NAME
-		       ": %s: bond_do_fail_over_mac impossible: bad policy %d\n",
+		pr_err("%s: bond_do_fail_over_mac impossible: bad policy %d\n",
 		       bond->dev->name, bond->params.fail_over_mac);
 		break;
 	}
@@ -1178,11 +1175,9 @@
 
 		if (new_active->link == BOND_LINK_BACK) {
 			if (USES_PRIMARY(bond->params.mode)) {
-				pr_info(DRV_NAME
-				       ": %s: making interface %s the new "
-				       "active one %d ms earlier.\n",
-				       bond->dev->name, new_active->dev->name,
-				       (bond->params.updelay - new_active->delay) * bond->params.miimon);
+				pr_info("%s: making interface %s the new active one %d ms earlier.\n",
+					bond->dev->name, new_active->dev->name,
+					(bond->params.updelay - new_active->delay) * bond->params.miimon);
 			}
 
 			new_active->delay = 0;
@@ -1195,10 +1190,8 @@
 				bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
 		} else {
 			if (USES_PRIMARY(bond->params.mode)) {
-				pr_info(DRV_NAME
-				       ": %s: making interface %s the new "
-				       "active one.\n",
-				       bond->dev->name, new_active->dev->name);
+				pr_info("%s: making interface %s the new active one.\n",
+					bond->dev->name, new_active->dev->name);
 			}
 		}
 	}
@@ -1268,13 +1261,11 @@
 			return;
 
 		if (netif_carrier_ok(bond->dev)) {
-			pr_info(DRV_NAME
-			       ": %s: first active interface up!\n",
-			       bond->dev->name);
+			pr_info("%s: first active interface up!\n",
+				bond->dev->name);
 		} else {
-			pr_info(DRV_NAME ": %s: "
-			       "now running without any active interface !\n",
-			       bond->dev->name);
+			pr_info("%s: now running without any active interface !\n",
+				bond->dev->name);
 		}
 	}
 }
@@ -1423,16 +1414,14 @@
 
 	if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
 		slave_ops->ndo_do_ioctl == NULL) {
-		pr_warning(DRV_NAME
-		       ": %s: Warning: no link monitoring support for %s\n",
-		       bond_dev->name, slave_dev->name);
+		pr_warning("%s: Warning: no link monitoring support for %s\n",
+			   bond_dev->name, slave_dev->name);
 	}
 
 	/* bond must be initialized by bond_open() before enslaving */
 	if (!(bond_dev->flags & IFF_UP)) {
-		pr_warning(DRV_NAME
-			" %s: master_dev is not up in bond_enslave\n",
-			bond_dev->name);
+		pr_warning("%s: master_dev is not up in bond_enslave\n",
+			   bond_dev->name);
 	}
 
 	/* already enslaved */
@@ -1446,19 +1435,13 @@
 	if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
 		pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
 		if (!list_empty(&bond->vlan_list)) {
-			pr_err(DRV_NAME
-			       ": %s: Error: cannot enslave VLAN "
-			       "challenged slave %s on VLAN enabled "
-			       "bond %s\n", bond_dev->name, slave_dev->name,
-			       bond_dev->name);
+			pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
+			       bond_dev->name, slave_dev->name, bond_dev->name);
 			return -EPERM;
 		} else {
-			pr_warning(DRV_NAME
-			       ": %s: Warning: enslaved VLAN challenged "
-			       "slave %s. Adding VLANs will be blocked as "
-			       "long as %s is part of bond %s\n",
-			       bond_dev->name, slave_dev->name, slave_dev->name,
-			       bond_dev->name);
+			pr_warning("%s: Warning: enslaved VLAN challenged slave %s. Adding VLANs will be blocked as long as %s is part of bond %s\n",
+				   bond_dev->name, slave_dev->name,
+				   slave_dev->name, bond_dev->name);
 			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 		}
 	} else {
@@ -1478,8 +1461,7 @@
 	 * enslaving it; the old ifenslave will not.
 	 */
 	if ((slave_dev->flags & IFF_UP)) {
-		pr_err(DRV_NAME ": %s is up. "
-		       "This may be due to an out of date ifenslave.\n",
+		pr_err("%s is up. This may be due to an out of date ifenslave.\n",
 		       slave_dev->name);
 		res = -EPERM;
 		goto err_undo_flags;
@@ -1495,7 +1477,8 @@
 	if (bond->slave_cnt == 0) {
 		if (bond_dev->type != slave_dev->type) {
 			pr_debug("%s: change device type from %d to %d\n",
-				bond_dev->name, bond_dev->type, slave_dev->type);
+				 bond_dev->name,
+				 bond_dev->type, slave_dev->type);
 
 			netdev_bonding_change(bond_dev, NETDEV_BONDING_OLDTYPE);
 
@@ -1507,28 +1490,21 @@
 			netdev_bonding_change(bond_dev, NETDEV_BONDING_NEWTYPE);
 		}
 	} else if (bond_dev->type != slave_dev->type) {
-		pr_err(DRV_NAME ": %s ether type (%d) is different "
-			"from other slaves (%d), can not enslave it.\n",
-			slave_dev->name,
-			slave_dev->type, bond_dev->type);
-			res = -EINVAL;
-			goto err_undo_flags;
+		pr_err("%s ether type (%d) is different from other slaves (%d), can not enslave it.\n",
+		       slave_dev->name,
+		       slave_dev->type, bond_dev->type);
+		res = -EINVAL;
+		goto err_undo_flags;
 	}
 
 	if (slave_ops->ndo_set_mac_address == NULL) {
 		if (bond->slave_cnt == 0) {
-			pr_warning(DRV_NAME
-			       ": %s: Warning: The first slave device "
-			       "specified does not support setting the MAC "
-			       "address. Setting fail_over_mac to active.",
-			       bond_dev->name);
+			pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.",
+				   bond_dev->name);
 			bond->params.fail_over_mac = BOND_FOM_ACTIVE;
 		} else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) {
-			pr_err(DRV_NAME
-				": %s: Error: The slave device specified "
-				"does not support setting the MAC address, "
-				"but fail_over_mac is not set to active.\n"
-				, bond_dev->name);
+			pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n",
+			       bond_dev->name);
 			res = -EOPNOTSUPP;
 			goto err_undo_flags;
 		}
@@ -1655,22 +1631,12 @@
 			 * supported); thus, we don't need to change
 			 * the messages for netif_carrier.
 			 */
-			pr_warning(DRV_NAME
-			       ": %s: Warning: MII and ETHTOOL support not "
-			       "available for interface %s, and "
-			       "arp_interval/arp_ip_target module parameters "
-			       "not specified, thus bonding will not detect "
-			       "link failures! see bonding.txt for details.\n",
+			pr_warning("%s: Warning: MII and ETHTOOL support not available for interface %s, and arp_interval/arp_ip_target module parameters not specified, thus bonding will not detect link failures! see bonding.txt for details.\n",
 			       bond_dev->name, slave_dev->name);
 		} else if (link_reporting == -1) {
 			/* unable get link status using mii/ethtool */
-			pr_warning(DRV_NAME
-			       ": %s: Warning: can't get link status from "
-			       "interface %s; the network driver associated "
-			       "with this interface does not support MII or "
-			       "ETHTOOL link status reporting, thus miimon "
-			       "has no effect on this interface.\n",
-			       bond_dev->name, slave_dev->name);
+			pr_warning("%s: Warning: can't get link status from interface %s; the network driver associated with this interface does not support MII or ETHTOOL link status reporting, thus miimon has no effect on this interface.\n",
+				   bond_dev->name, slave_dev->name);
 		}
 	}
 
@@ -1678,34 +1644,27 @@
 	if (!bond->params.miimon ||
 	    (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
 		if (bond->params.updelay) {
-			pr_debug("Initial state of slave_dev is "
-				"BOND_LINK_BACK\n");
+			pr_debug("Initial state of slave_dev is BOND_LINK_BACK\n");
 			new_slave->link  = BOND_LINK_BACK;
 			new_slave->delay = bond->params.updelay;
 		} else {
-			pr_debug("Initial state of slave_dev is "
-				"BOND_LINK_UP\n");
+			pr_debug("Initial state of slave_dev is BOND_LINK_UP\n");
 			new_slave->link  = BOND_LINK_UP;
 		}
 		new_slave->jiffies = jiffies;
 	} else {
-		pr_debug("Initial state of slave_dev is "
-			"BOND_LINK_DOWN\n");
+		pr_debug("Initial state of slave_dev is BOND_LINK_DOWN\n");
 		new_slave->link  = BOND_LINK_DOWN;
 	}
 
 	if (bond_update_speed_duplex(new_slave) &&
 	    (new_slave->link != BOND_LINK_DOWN)) {
-		pr_warning(DRV_NAME
-		       ": %s: Warning: failed to get speed and duplex from %s, "
-		       "assumed to be 100Mb/sec and Full.\n",
-		       bond_dev->name, new_slave->dev->name);
+		pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n",
+			   bond_dev->name, new_slave->dev->name);
 
 		if (bond->params.mode == BOND_MODE_8023AD) {
-			pr_warning(DRV_NAME
-			       ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL "
-			       "support in base driver for proper aggregator "
-			       "selection.\n", bond_dev->name);
+			pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n",
+				   bond_dev->name);
 		}
 	}
 
@@ -1777,11 +1736,10 @@
 	if (res)
 		goto err_close;
 
-	pr_info(DRV_NAME
-	       ": %s: enslaving %s as a%s interface with a%s link.\n",
-	       bond_dev->name, slave_dev->name,
-	       new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
-	       new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
+	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
+		bond_dev->name, slave_dev->name,
+		new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
+		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
 
 	/* enslave is successful */
 	return 0;
@@ -1833,8 +1791,7 @@
 	/* slave is not a slave or master is not master of this slave */
 	if (!(slave_dev->flags & IFF_SLAVE) ||
 	    (slave_dev->master != bond_dev)) {
-		pr_err(DRV_NAME
-		       ": %s: Error: cannot release %s.\n",
+		pr_err("%s: Error: cannot release %s.\n",
 		       bond_dev->name, slave_dev->name);
 		return -EINVAL;
 	}
@@ -1844,9 +1801,8 @@
 	slave = bond_get_slave_by_dev(bond, slave_dev);
 	if (!slave) {
 		/* not a slave of this bond */
-		pr_info(DRV_NAME
-		       ": %s: %s not enslaved\n",
-		       bond_dev->name, slave_dev->name);
+		pr_info("%s: %s not enslaved\n",
+			bond_dev->name, slave_dev->name);
 		write_unlock_bh(&bond->lock);
 		return -EINVAL;
 	}
@@ -1854,14 +1810,10 @@
 	if (!bond->params.fail_over_mac) {
 		if (!compare_ether_addr(bond_dev->dev_addr, slave->perm_hwaddr) &&
 		    bond->slave_cnt > 1)
-			pr_warning(DRV_NAME
-			       ": %s: Warning: the permanent HWaddr of %s - "
-			       "%pM - is still in use by %s. "
-			       "Set the HWaddr of %s to a different address "
-			       "to avoid conflicts.\n",
-			       bond_dev->name, slave_dev->name,
-			       slave->perm_hwaddr,
-			       bond_dev->name, slave_dev->name);
+			pr_warning("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
+				   bond_dev->name, slave_dev->name,
+				   slave->perm_hwaddr,
+				   bond_dev->name, slave_dev->name);
 	}
 
 	/* Inform AD package of unbinding of slave. */
@@ -1872,12 +1824,10 @@
 		bond_3ad_unbind_slave(slave);
 	}
 
-	pr_info(DRV_NAME
-	       ": %s: releasing %s interface %s\n",
-	       bond_dev->name,
-	       (slave->state == BOND_STATE_ACTIVE)
-	       ? "active" : "backup",
-	       slave_dev->name);
+	pr_info("%s: releasing %s interface %s\n",
+		bond_dev->name,
+		(slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+		slave_dev->name);
 
 	oldcurrent = bond->curr_active_slave;
 
@@ -1934,21 +1884,15 @@
 		if (list_empty(&bond->vlan_list)) {
 			bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 		} else {
-			pr_warning(DRV_NAME
-			       ": %s: Warning: clearing HW address of %s while it "
-			       "still has VLANs.\n",
-			       bond_dev->name, bond_dev->name);
-			pr_warning(DRV_NAME
-			       ": %s: When re-adding slaves, make sure the bond's "
-			       "HW address matches its VLANs'.\n",
-			       bond_dev->name);
+			pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
+				   bond_dev->name, bond_dev->name);
+			pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
+				   bond_dev->name);
 		}
 	} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
 		   !bond_has_challenged_slaves(bond)) {
-		pr_info(DRV_NAME
-		       ": %s: last VLAN challenged slave %s "
-		       "left bond %s. VLAN blocking is removed\n",
-		       bond_dev->name, slave_dev->name, bond_dev->name);
+		pr_info("%s: last VLAN challenged slave %s left bond %s. VLAN blocking is removed\n",
+			bond_dev->name, slave_dev->name, bond_dev->name);
 		bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
 	}
 
@@ -2011,8 +1955,8 @@
 
 	ret = bond_release(bond_dev, slave_dev);
 	if ((ret == 0) && (bond->slave_cnt == 0)) {
-		pr_info(DRV_NAME ": %s: destroying bond %s.\n",
-		       bond_dev->name, bond_dev->name);
+		pr_info("%s: destroying bond %s.\n",
+			bond_dev->name, bond_dev->name);
 		unregister_netdevice(bond_dev);
 	}
 	return ret;
@@ -2116,19 +2060,13 @@
 	if (list_empty(&bond->vlan_list))
 		bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 	else {
-		pr_warning(DRV_NAME
-		       ": %s: Warning: clearing HW address of %s while it "
-		       "still has VLANs.\n",
-		       bond_dev->name, bond_dev->name);
-		pr_warning(DRV_NAME
-		       ": %s: When re-adding slaves, make sure the bond's "
-		       "HW address matches its VLANs'.\n",
-		       bond_dev->name);
+		pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
+			   bond_dev->name, bond_dev->name);
+		pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
+			   bond_dev->name);
 	}
 
-	pr_info(DRV_NAME
-	       ": %s: released all slaves\n",
-	       bond_dev->name);
+	pr_info("%s: released all slaves\n", bond_dev->name);
 
 out:
 	write_unlock_bh(&bond->lock);
@@ -2254,16 +2192,14 @@
 			slave->link = BOND_LINK_FAIL;
 			slave->delay = bond->params.downdelay;
 			if (slave->delay) {
-				pr_info(DRV_NAME
-				       ": %s: link status down for %s"
-				       "interface %s, disabling it in %d ms.\n",
-				       bond->dev->name,
-				       (bond->params.mode ==
-					BOND_MODE_ACTIVEBACKUP) ?
-				       ((slave->state == BOND_STATE_ACTIVE) ?
-					"active " : "backup ") : "",
-				       slave->dev->name,
-				       bond->params.downdelay * bond->params.miimon);
+				pr_info("%s: link status down for %sinterface %s, disabling it in %d ms.\n",
+					bond->dev->name,
+					(bond->params.mode ==
+					 BOND_MODE_ACTIVEBACKUP) ?
+					((slave->state == BOND_STATE_ACTIVE) ?
+					 "active " : "backup ") : "",
+					slave->dev->name,
+					bond->params.downdelay * bond->params.miimon);
 			}
 			/*FALLTHRU*/
 		case BOND_LINK_FAIL:
@@ -2273,13 +2209,11 @@
 				 */
 				slave->link = BOND_LINK_UP;
 				slave->jiffies = jiffies;
-				pr_info(DRV_NAME
-				       ": %s: link status up again after %d "
-				       "ms for interface %s.\n",
-				       bond->dev->name,
-				       (bond->params.downdelay - slave->delay) *
-				       bond->params.miimon,
-				       slave->dev->name);
+				pr_info("%s: link status up again after %d ms for interface %s.\n",
+					bond->dev->name,
+					(bond->params.downdelay - slave->delay) *
+					bond->params.miimon,
+					slave->dev->name);
 				continue;
 			}
 
@@ -2300,25 +2234,21 @@
 			slave->delay = bond->params.updelay;
 
 			if (slave->delay) {
-				pr_info(DRV_NAME
-				       ": %s: link status up for "
-				       "interface %s, enabling it in %d ms.\n",
-				       bond->dev->name, slave->dev->name,
-				       ignore_updelay ? 0 :
-				       bond->params.updelay *
-				       bond->params.miimon);
+				pr_info("%s: link status up for interface %s, enabling it in %d ms.\n",
+					bond->dev->name, slave->dev->name,
+					ignore_updelay ? 0 :
+					bond->params.updelay *
+					bond->params.miimon);
 			}
 			/*FALLTHRU*/
 		case BOND_LINK_BACK:
 			if (!link_state) {
 				slave->link = BOND_LINK_DOWN;
-				pr_info(DRV_NAME
-				       ": %s: link status down again after %d "
-				       "ms for interface %s.\n",
-				       bond->dev->name,
-				       (bond->params.updelay - slave->delay) *
-				       bond->params.miimon,
-				       slave->dev->name);
+				pr_info("%s: link status down again after %d ms for interface %s.\n",
+					bond->dev->name,
+					(bond->params.updelay - slave->delay) *
+					bond->params.miimon,
+					slave->dev->name);
 
 				continue;
 			}
@@ -2366,10 +2296,8 @@
 				slave->state = BOND_STATE_BACKUP;
 			}
 
-			pr_info(DRV_NAME
-			       ": %s: link status definitely "
-			       "up for interface %s.\n",
-			       bond->dev->name, slave->dev->name);
+			pr_info("%s: link status definitely up for interface %s.\n",
+				bond->dev->name, slave->dev->name);
 
 			/* notify ad that the link status has changed */
 			if (bond->params.mode == BOND_MODE_8023AD)
@@ -2395,10 +2323,8 @@
 			    bond->params.mode == BOND_MODE_8023AD)
 				bond_set_slave_inactive_flags(slave);
 
-			pr_info(DRV_NAME
-			       ": %s: link status definitely down for "
-			       "interface %s, disabling it\n",
-			       bond->dev->name, slave->dev->name);
+			pr_info("%s: link status definitely down for interface %s, disabling it\n",
+				bond->dev->name, slave->dev->name);
 
 			if (bond->params.mode == BOND_MODE_8023AD)
 				bond_3ad_handle_link_change(slave,
@@ -2414,8 +2340,7 @@
 			continue;
 
 		default:
-			pr_err(DRV_NAME
-			       ": %s: invalid new link %d on slave %s\n",
+			pr_err("%s: invalid new link %d on slave %s\n",
 			       bond->dev->name, slave->new_link,
 			       slave->dev->name);
 			slave->new_link = BOND_LINK_NOCHANGE;
@@ -2534,19 +2459,19 @@
 	struct sk_buff *skb;
 
 	pr_debug("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
-	       slave_dev->name, dest_ip, src_ip, vlan_id);
+		 slave_dev->name, dest_ip, src_ip, vlan_id);
 
 	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
 			 NULL, slave_dev->dev_addr, NULL);
 
 	if (!skb) {
-		pr_err(DRV_NAME ": ARP packet allocation failed\n");
+		pr_err("ARP packet allocation failed\n");
 		return;
 	}
 	if (vlan_id) {
 		skb = vlan_put_tag(skb, vlan_id);
 		if (!skb) {
-			pr_err(DRV_NAME ": failed to insert VLAN tag\n");
+			pr_err("failed to insert VLAN tag\n");
 			return;
 		}
 	}
@@ -2586,9 +2511,8 @@
 		rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl);
 		if (rv) {
 			if (net_ratelimit()) {
-				pr_warning(DRV_NAME
-			     ": %s: no route to arp_ip_target %pI4\n",
-				       bond->dev->name, &fl.fl4_dst);
+				pr_warning("%s: no route to arp_ip_target %pI4\n",
+					   bond->dev->name, &fl.fl4_dst);
 			}
 			continue;
 		}
@@ -2623,10 +2547,9 @@
 		}
 
 		if (net_ratelimit()) {
-			pr_warning(DRV_NAME
-	       ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n",
-			       bond->dev->name, &fl.fl4_dst,
-			       rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
+			pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
+				   bond->dev->name, &fl.fl4_dst,
+				   rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
 		}
 		ip_rt_put(rt);
 	}
@@ -2644,8 +2567,8 @@
 	struct vlan_entry *vlan;
 	struct net_device *vlan_dev;
 
-	pr_debug("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name,
-				slave ? slave->dev->name : "NULL");
+	pr_debug("bond_send_grat_arp: bond %s slave %s\n",
+		 bond->dev->name, slave ? slave->dev->name : "NULL");
 
 	if (!slave || !bond->send_grat_arp ||
 	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
@@ -2674,7 +2597,8 @@
 
 	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
 		pr_debug("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n",
-			&sip, &tip, i, &targets[i], bond_has_this_ip(bond, tip));
+			 &sip, &tip, i, &targets[i],
+			 bond_has_this_ip(bond, tip));
 		if (sip == targets[i]) {
 			if (bond_has_this_ip(bond, tip))
 				slave->last_arp_rx = jiffies;
@@ -2698,8 +2622,8 @@
 	read_lock(&bond->lock);
 
 	pr_debug("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
-		bond->dev->name, skb->dev ? skb->dev->name : "NULL",
-		orig_dev ? orig_dev->name : "NULL");
+		 bond->dev->name, skb->dev ? skb->dev->name : "NULL",
+		 orig_dev ? orig_dev->name : "NULL");
 
 	slave = bond_get_slave_by_dev(bond, orig_dev);
 	if (!slave || !slave_do_arp_validate(bond, slave))
@@ -2724,9 +2648,9 @@
 	memcpy(&tip, arp_ptr, 4);
 
 	pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
-		bond->dev->name, slave->dev->name, slave->state,
-		bond->params.arp_validate, slave_do_arp_validate(bond, slave),
-		&sip, &tip);
+		 bond->dev->name, slave->dev->name, slave->state,
+		 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
+		 &sip, &tip);
 
 	/*
 	 * Backup slaves won't see the ARP reply, but do come through
@@ -2800,17 +2724,14 @@
 				 * is closed.
 				 */
 				if (!oldcurrent) {
-					pr_info(DRV_NAME
-					       ": %s: link status definitely "
-					       "up for interface %s, ",
-					       bond->dev->name,
-					       slave->dev->name);
+					pr_info("%s: link status definitely up for interface %s, ",
+						bond->dev->name,
+						slave->dev->name);
 					do_failover = 1;
 				} else {
-					pr_info(DRV_NAME
-					       ": %s: interface %s is now up\n",
-					       bond->dev->name,
-					       slave->dev->name);
+					pr_info("%s: interface %s is now up\n",
+						bond->dev->name,
+						slave->dev->name);
 				}
 			}
 		} else {
@@ -2829,10 +2750,9 @@
 				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
 
-				pr_info(DRV_NAME
-				       ": %s: interface %s is now down.\n",
-				       bond->dev->name,
-				       slave->dev->name);
+				pr_info("%s: interface %s is now down.\n",
+					bond->dev->name,
+					slave->dev->name);
 
 				if (slave == oldcurrent)
 					do_failover = 1;
@@ -2965,9 +2885,7 @@
 				slave->link = BOND_LINK_UP;
 				bond->current_arp_slave = NULL;
 
-				pr_info(DRV_NAME
-					": %s: link status definitely "
-					"up for interface %s.\n",
+				pr_info("%s: link status definitely up for interface %s.\n",
 					bond->dev->name, slave->dev->name);
 
 				if (!bond->curr_active_slave ||
@@ -2985,9 +2903,7 @@
 			slave->link = BOND_LINK_DOWN;
 			bond_set_slave_inactive_flags(slave);
 
-			pr_info(DRV_NAME
-				": %s: link status definitely down for "
-				"interface %s, disabling it\n",
+			pr_info("%s: link status definitely down for interface %s, disabling it\n",
 				bond->dev->name, slave->dev->name);
 
 			if (slave == bond->curr_active_slave) {
@@ -2998,8 +2914,7 @@
 			continue;
 
 		default:
-			pr_err(DRV_NAME
-			       ": %s: impossible: new_link %d on slave %s\n",
+			pr_err("%s: impossible: new_link %d on slave %s\n",
 			       bond->dev->name, slave->new_link,
 			       slave->dev->name);
 			continue;
@@ -3028,9 +2943,9 @@
 	read_lock(&bond->curr_slave_lock);
 
 	if (bond->current_arp_slave && bond->curr_active_slave)
-		pr_info(DRV_NAME "PROBE: c_arp %s && cas %s BAD\n",
-		       bond->current_arp_slave->dev->name,
-		       bond->curr_active_slave->dev->name);
+		pr_info("PROBE: c_arp %s && cas %s BAD\n",
+			bond->current_arp_slave->dev->name,
+			bond->curr_active_slave->dev->name);
 
 	if (bond->curr_active_slave) {
 		bond_arp_send_all(bond, bond->curr_active_slave);
@@ -3078,9 +2993,8 @@
 
 			bond_set_slave_inactive_flags(slave);
 
-			pr_info(DRV_NAME
-			       ": %s: backup interface %s is now down.\n",
-			       bond->dev->name, slave->dev->name);
+			pr_info("%s: backup interface %s is now down.\n",
+				bond->dev->name, slave->dev->name);
 		}
 	}
 }
@@ -3360,9 +3274,8 @@
 						    S_IRUGO, bn->proc_dir,
 						    &bond_info_fops, bond);
 		if (bond->proc_entry == NULL)
-			pr_warning(DRV_NAME
-			       ": Warning: Cannot create /proc/net/%s/%s\n",
-			       DRV_NAME, bond_dev->name);
+			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
+				   DRV_NAME, bond_dev->name);
 		else
 			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
 	}
@@ -3388,9 +3301,8 @@
 	if (!bn->proc_dir) {
 		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
 		if (!bn->proc_dir)
-			pr_warning(DRV_NAME
-				": Warning: cannot create /proc/net/%s\n",
-				DRV_NAME);
+			pr_warning("Warning: cannot create /proc/net/%s\n",
+				   DRV_NAME);
 	}
 }
 
@@ -3539,8 +3451,8 @@
 	struct net_device *event_dev = (struct net_device *)ptr;
 
 	pr_debug("event_dev: %s, event: %lx\n",
-		(event_dev ? event_dev->name : "None"),
-		event);
+		 event_dev ? event_dev->name : "None",
+		 event);
 
 	if (!(event_dev->priv_flags & IFF_BONDING))
 		return NOTIFY_DONE;
@@ -3875,8 +3787,7 @@
 	struct mii_ioctl_data *mii = NULL;
 	int res = 0;
 
-	pr_debug("bond_ioctl: master=%s, cmd=%d\n",
-		bond_dev->name, cmd);
+	pr_debug("bond_ioctl: master=%s, cmd=%d\n", bond_dev->name, cmd);
 
 	switch (cmd) {
 	case SIOCGMIIPHY:
@@ -3945,12 +3856,12 @@
 
 	slave_dev = dev_get_by_name(dev_net(bond_dev), ifr->ifr_slave);
 
-	pr_debug("slave_dev=%p: \n", slave_dev);
+	pr_debug("slave_dev=%p:\n", slave_dev);
 
 	if (!slave_dev)
 		res = -ENODEV;
 	else {
-		pr_debug("slave_dev->name=%s: \n", slave_dev->name);
+		pr_debug("slave_dev->name=%s:\n", slave_dev->name);
 		switch (cmd) {
 		case BOND_ENSLAVE_OLD:
 		case SIOCBONDENSLAVE:
@@ -4059,7 +3970,7 @@
 	int i;
 
 	pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
-		(bond_dev ? bond_dev->name : "None"), new_mtu);
+		 (bond_dev ? bond_dev->name : "None"), new_mtu);
 
 	/* Can't hold bond->lock with bh disabled here since
 	 * some base drivers panic. On the other hand we can't
@@ -4077,8 +3988,10 @@
 	 */
 
 	bond_for_each_slave(bond, slave, i) {
-		pr_debug("s %p s->p %p c_m %p\n", slave,
-			slave->prev, slave->dev->netdev_ops->ndo_change_mtu);
+		pr_debug("s %p s->p %p c_m %p\n",
+			 slave,
+			 slave->prev,
+			 slave->dev->netdev_ops->ndo_change_mtu);
 
 		res = dev_set_mtu(slave->dev, new_mtu);
 
@@ -4108,8 +4021,8 @@
 
 		tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
 		if (tmp_res) {
-			pr_debug("unwind err %d dev %s\n", tmp_res,
-				slave->dev->name);
+			pr_debug("unwind err %d dev %s\n",
+				 tmp_res, slave->dev->name);
 		}
 	}
 
@@ -4135,7 +4048,8 @@
 		return bond_alb_set_mac_address(bond_dev, addr);
 
 
-	pr_debug("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
+	pr_debug("bond=%p, name=%s\n",
+		 bond, bond_dev ? bond_dev->name : "None");
 
 	/*
 	 * If fail_over_mac is set to active, do nothing and return
@@ -4200,8 +4114,8 @@
 
 		tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
 		if (tmp_res) {
-			pr_debug("unwind err %d dev %s\n", tmp_res,
-				slave->dev->name);
+			pr_debug("unwind err %d dev %s\n",
+				 tmp_res, slave->dev->name);
 		}
 	}
 
@@ -4357,9 +4271,7 @@
 			if (tx_dev) {
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (!skb2) {
-					pr_err(DRV_NAME
-					       ": %s: Error: bond_xmit_broadcast(): "
-					       "skb_clone() failed\n",
+					pr_err("%s: Error: bond_xmit_broadcast(): skb_clone() failed\n",
 					       bond_dev->name);
 					continue;
 				}
@@ -4425,8 +4337,8 @@
 		return bond_alb_xmit(skb, dev);
 	default:
 		/* Should never happen, mode already checked */
-		pr_err(DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
-		     dev->name, bond->params.mode);
+		pr_err("%s: Error: Unknown bonding mode %d\n",
+		       dev->name, bond->params.mode);
 		WARN_ON_ONCE(1);
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
@@ -4462,10 +4374,8 @@
 		break;
 	default:
 		/* Should never happen, mode already checked */
-		pr_err(DRV_NAME
-		       ": %s: Error: Unknown bonding mode %d\n",
-		       bond_dev->name,
-		       mode);
+		pr_err("%s: Error: Unknown bonding mode %d\n",
+		       bond_dev->name, mode);
 		break;
 	}
 }
@@ -4650,8 +4560,7 @@
 	if (mode) {
 		bond_mode = bond_parse_parm(mode, bond_mode_tbl);
 		if (bond_mode == -1) {
-			pr_err(DRV_NAME
-			       ": Error: Invalid bonding mode \"%s\"\n",
+			pr_err("Error: Invalid bonding mode \"%s\"\n",
 			       mode == NULL ? "NULL" : mode);
 			return -EINVAL;
 		}
@@ -4660,16 +4569,13 @@
 	if (xmit_hash_policy) {
 		if ((bond_mode != BOND_MODE_XOR) &&
 		    (bond_mode != BOND_MODE_8023AD)) {
-			pr_info(DRV_NAME
-				": xmit_hash_policy param is irrelevant in"
-				" mode %s\n",
+			pr_info("xmit_hash_policy param is irrelevant in mode %s\n",
 			       bond_mode_name(bond_mode));
 		} else {
 			xmit_hashtype = bond_parse_parm(xmit_hash_policy,
 							xmit_hashtype_tbl);
 			if (xmit_hashtype == -1) {
-				pr_err(DRV_NAME
-				       ": Error: Invalid xmit_hash_policy \"%s\"\n",
+				pr_err("Error: Invalid xmit_hash_policy \"%s\"\n",
 				       xmit_hash_policy == NULL ? "NULL" :
 				       xmit_hash_policy);
 				return -EINVAL;
@@ -4679,14 +4585,12 @@
 
 	if (lacp_rate) {
 		if (bond_mode != BOND_MODE_8023AD) {
-			pr_info(DRV_NAME
-			       ": lacp_rate param is irrelevant in mode %s\n",
-			       bond_mode_name(bond_mode));
+			pr_info("lacp_rate param is irrelevant in mode %s\n",
+				bond_mode_name(bond_mode));
 		} else {
 			lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl);
 			if (lacp_fast == -1) {
-				pr_err(DRV_NAME
-				       ": Error: Invalid lacp rate \"%s\"\n",
+				pr_err("Error: Invalid lacp rate \"%s\"\n",
 				       lacp_rate == NULL ? "NULL" : lacp_rate);
 				return -EINVAL;
 			}
@@ -4696,82 +4600,64 @@
 	if (ad_select) {
 		params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
 		if (params->ad_select == -1) {
-			pr_err(DRV_NAME
-			       ": Error: Invalid ad_select \"%s\"\n",
+			pr_err("Error: Invalid ad_select \"%s\"\n",
 			       ad_select == NULL ? "NULL" : ad_select);
 			return -EINVAL;
 		}
 
 		if (bond_mode != BOND_MODE_8023AD) {
-			pr_warning(DRV_NAME
-			       ": ad_select param only affects 802.3ad mode\n");
+			pr_warning("ad_select param only affects 802.3ad mode\n");
 		}
 	} else {
 		params->ad_select = BOND_AD_STABLE;
 	}
 
 	if (max_bonds < 0) {
-		pr_warning(DRV_NAME
-		       ": Warning: max_bonds (%d) not in range %d-%d, so it "
-		       "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
-		       max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
+		pr_warning("Warning: max_bonds (%d) not in range %d-%d, so it was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
+			   max_bonds, 0, INT_MAX, BOND_DEFAULT_MAX_BONDS);
 		max_bonds = BOND_DEFAULT_MAX_BONDS;
 	}
 
 	if (miimon < 0) {
-		pr_warning(DRV_NAME
-		       ": Warning: miimon module parameter (%d), "
-		       "not in range 0-%d, so it was reset to %d\n",
-		       miimon, INT_MAX, BOND_LINK_MON_INTERV);
+		pr_warning("Warning: miimon module parameter (%d), not in range 0-%d, so it was reset to %d\n",
+			   miimon, INT_MAX, BOND_LINK_MON_INTERV);
 		miimon = BOND_LINK_MON_INTERV;
 	}
 
 	if (updelay < 0) {
-		pr_warning(DRV_NAME
-		       ": Warning: updelay module parameter (%d), "
-		       "not in range 0-%d, so it was reset to 0\n",
-		       updelay, INT_MAX);
+		pr_warning("Warning: updelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			   updelay, INT_MAX);
 		updelay = 0;
 	}
 
 	if (downdelay < 0) {
-		pr_warning(DRV_NAME
-		       ": Warning: downdelay module parameter (%d), "
-		       "not in range 0-%d, so it was reset to 0\n",
-		       downdelay, INT_MAX);
+		pr_warning("Warning: downdelay module parameter (%d), not in range 0-%d, so it was reset to 0\n",
+			   downdelay, INT_MAX);
 		downdelay = 0;
 	}
 
 	if ((use_carrier != 0) && (use_carrier != 1)) {
-		pr_warning(DRV_NAME
-		       ": Warning: use_carrier module parameter (%d), "
-		       "not of valid value (0/1), so it was set to 1\n",
-		       use_carrier);
+		pr_warning("Warning: use_carrier module parameter (%d), not of valid value (0/1), so it was set to 1\n",
+			   use_carrier);
 		use_carrier = 1;
 	}
 
 	if (num_grat_arp < 0 || num_grat_arp > 255) {
-		pr_warning(DRV_NAME
-		       ": Warning: num_grat_arp (%d) not in range 0-255 so it "
-		       "was reset to 1 \n", num_grat_arp);
+		pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1 \n",
+			   num_grat_arp);
 		num_grat_arp = 1;
 	}
 
 	if (num_unsol_na < 0 || num_unsol_na > 255) {
-		pr_warning(DRV_NAME
-		       ": Warning: num_unsol_na (%d) not in range 0-255 so it "
-		       "was reset to 1 \n", num_unsol_na);
+		pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1 \n",
+			   num_unsol_na);
 		num_unsol_na = 1;
 	}
 
 	/* reset values for 802.3ad */
 	if (bond_mode == BOND_MODE_8023AD) {
 		if (!miimon) {
-			pr_warning(DRV_NAME
-			       ": Warning: miimon must be specified, "
-			       "otherwise bonding will not detect link "
-			       "failure, speed and duplex which are "
-			       "essential for 802.3ad operation\n");
+			pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure, speed and duplex which are essential for 802.3ad operation\n");
 			pr_warning("Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
@@ -4781,24 +4667,15 @@
 	if ((bond_mode == BOND_MODE_TLB) ||
 	    (bond_mode == BOND_MODE_ALB)) {
 		if (!miimon) {
-			pr_warning(DRV_NAME
-			       ": Warning: miimon must be specified, "
-			       "otherwise bonding will not detect link "
-			       "failure and link speed which are essential "
-			       "for TLB/ALB load balancing\n");
+			pr_warning("Warning: miimon must be specified, otherwise bonding will not detect link failure and link speed which are essential for TLB/ALB load balancing\n");
 			pr_warning("Forcing miimon to 100msec\n");
 			miimon = 100;
 		}
 	}
 
 	if (bond_mode == BOND_MODE_ALB) {
-		pr_notice(DRV_NAME
-		       ": In ALB mode you might experience client "
-		       "disconnections upon reconnection of a link if the "
-		       "bonding module updelay parameter (%d msec) is "
-		       "incompatible with the forwarding delay time of the "
-		       "switch\n",
-		       updelay);
+		pr_notice("In ALB mode you might experience client disconnections upon reconnection of a link if the bonding module updelay parameter (%d msec) is incompatible with the forwarding delay time of the switch\n",
+			  updelay);
 	}
 
 	if (!miimon) {
@@ -4806,49 +4683,37 @@
 			/* just warn the user the up/down delay will have
 			 * no effect since miimon is zero...
 			 */
-			pr_warning(DRV_NAME
-			       ": Warning: miimon module parameter not set "
-			       "and updelay (%d) or downdelay (%d) module "
-			       "parameter is set; updelay and downdelay have "
-			       "no effect unless miimon is set\n",
-			       updelay, downdelay);
+			pr_warning("Warning: miimon module parameter not set and updelay (%d) or downdelay (%d) module parameter is set; updelay and downdelay have no effect unless miimon is set\n",
+				   updelay, downdelay);
 		}
 	} else {
 		/* don't allow arp monitoring */
 		if (arp_interval) {
-			pr_warning(DRV_NAME
-			       ": Warning: miimon (%d) and arp_interval (%d) "
-			       "can't be used simultaneously, disabling ARP "
-			       "monitoring\n",
-			       miimon, arp_interval);
+			pr_warning("Warning: miimon (%d) and arp_interval (%d) can't be used simultaneously, disabling ARP monitoring\n",
+				   miimon, arp_interval);
 			arp_interval = 0;
 		}
 
 		if ((updelay % miimon) != 0) {
-			pr_warning(DRV_NAME
-			       ": Warning: updelay (%d) is not a multiple "
-			       "of miimon (%d), updelay rounded to %d ms\n",
-			       updelay, miimon, (updelay / miimon) * miimon);
+			pr_warning("Warning: updelay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
+				   updelay, miimon,
+				   (updelay / miimon) * miimon);
 		}
 
 		updelay /= miimon;
 
 		if ((downdelay % miimon) != 0) {
-			pr_warning(DRV_NAME
-			       ": Warning: downdelay (%d) is not a multiple "
-			       "of miimon (%d), downdelay rounded to %d ms\n",
-			       downdelay, miimon,
-			       (downdelay / miimon) * miimon);
+			pr_warning("Warning: downdelay (%d) is not a multiple of miimon (%d), downdelay rounded to %d ms\n",
+				   downdelay, miimon,
+				   (downdelay / miimon) * miimon);
 		}
 
 		downdelay /= miimon;
 	}
 
 	if (arp_interval < 0) {
-		pr_warning(DRV_NAME
-		       ": Warning: arp_interval module parameter (%d) "
-		       ", not in range 0-%d, so it was reset to %d\n",
-		       arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
+		pr_warning("Warning: arp_interval module parameter (%d) , not in range 0-%d, so it was reset to %d\n",
+			   arp_interval, INT_MAX, BOND_LINK_ARP_INTERV);
 		arp_interval = BOND_LINK_ARP_INTERV;
 	}
 
@@ -4858,10 +4723,8 @@
 		/* not complete check, but should be good enough to
 		   catch mistakes */
 		if (!isdigit(arp_ip_target[arp_ip_count][0])) {
-			pr_warning(DRV_NAME
-			       ": Warning: bad arp_ip_target module parameter "
-			       "(%s), ARP monitoring will not be performed\n",
-			       arp_ip_target[arp_ip_count]);
+			pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
+				   arp_ip_target[arp_ip_count]);
 			arp_interval = 0;
 		} else {
 			__be32 ip = in_aton(arp_ip_target[arp_ip_count]);
@@ -4871,31 +4734,25 @@
 
 	if (arp_interval && !arp_ip_count) {
 		/* don't allow arping if no arp_ip_target given... */
-		pr_warning(DRV_NAME
-		       ": Warning: arp_interval module parameter (%d) "
-		       "specified without providing an arp_ip_target "
-		       "parameter, arp_interval was reset to 0\n",
-		       arp_interval);
+		pr_warning("Warning: arp_interval module parameter (%d) specified without providing an arp_ip_target parameter, arp_interval was reset to 0\n",
+			   arp_interval);
 		arp_interval = 0;
 	}
 
 	if (arp_validate) {
 		if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
-			pr_err(DRV_NAME
-			       ": arp_validate only supported in active-backup mode\n");
+			pr_err("arp_validate only supported in active-backup mode\n");
 			return -EINVAL;
 		}
 		if (!arp_interval) {
-			pr_err(DRV_NAME
-			       ": arp_validate requires arp_interval\n");
+			pr_err("arp_validate requires arp_interval\n");
 			return -EINVAL;
 		}
 
 		arp_validate_value = bond_parse_parm(arp_validate,
 						     arp_validate_tbl);
 		if (arp_validate_value == -1) {
-			pr_err(DRV_NAME
-			       ": Error: invalid arp_validate \"%s\"\n",
+			pr_err("Error: invalid arp_validate \"%s\"\n",
 			       arp_validate == NULL ? "NULL" : arp_validate);
 			return -EINVAL;
 		}
@@ -4903,17 +4760,14 @@
 		arp_validate_value = 0;
 
 	if (miimon) {
-		pr_info(DRV_NAME
-		       ": MII link monitoring set to %d ms\n",
-		       miimon);
+		pr_info("MII link monitoring set to %d ms\n", miimon);
 	} else if (arp_interval) {
 		int i;
 
-		pr_info(DRV_NAME ": ARP monitoring set to %d ms,"
-		       " validate %s, with %d target(s):",
-		       arp_interval,
-		       arp_validate_tbl[arp_validate_value].modename,
-		       arp_ip_count);
+		pr_info("ARP monitoring set to %d ms, validate %s, with %d target(s):",
+			arp_interval,
+			arp_validate_tbl[arp_validate_value].modename,
+			arp_ip_count);
 
 		for (i = 0; i < arp_ip_count; i++)
 			pr_info(" %s", arp_ip_target[i]);
@@ -4924,21 +4778,15 @@
 		/* miimon and arp_interval not set, we need one so things
 		 * work as expected, see bonding.txt for details
 		 */
-		pr_warning(DRV_NAME
-		       ": Warning: either miimon or arp_interval and "
-		       "arp_ip_target module parameters must be specified, "
-		       "otherwise bonding will not detect link failures! see "
-		       "bonding.txt for details.\n");
+		pr_warning("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n");
 	}
 
 	if (primary && !USES_PRIMARY(bond_mode)) {
 		/* currently, using a primary only makes sense
 		 * in active backup, TLB or ALB modes
 		 */
-		pr_warning(DRV_NAME
-		       ": Warning: %s primary device specified but has no "
-		       "effect in %s mode\n",
-		       primary, bond_mode_name(bond_mode));
+		pr_warning("Warning: %s primary device specified but has no effect in %s mode\n",
+			   primary, bond_mode_name(bond_mode));
 		primary = NULL;
 	}
 
@@ -4946,8 +4794,7 @@
 		primary_reselect_value = bond_parse_parm(primary_reselect,
 							 pri_reselect_tbl);
 		if (primary_reselect_value == -1) {
-			pr_err(DRV_NAME
-			       ": Error: Invalid primary_reselect \"%s\"\n",
+			pr_err("Error: Invalid primary_reselect \"%s\"\n",
 			       primary_reselect ==
 					NULL ? "NULL" : primary_reselect);
 			return -EINVAL;
@@ -4960,16 +4807,13 @@
 		fail_over_mac_value = bond_parse_parm(fail_over_mac,
 						      fail_over_mac_tbl);
 		if (fail_over_mac_value == -1) {
-			pr_err(DRV_NAME
-			       ": Error: invalid fail_over_mac \"%s\"\n",
+			pr_err("Error: invalid fail_over_mac \"%s\"\n",
 			       arp_validate == NULL ? "NULL" : arp_validate);
 			return -EINVAL;
 		}
 
 		if (bond_mode != BOND_MODE_ACTIVEBACKUP)
-			pr_warning(DRV_NAME
-			       ": Warning: fail_over_mac only affects "
-			       "active-backup mode.\n");
+			pr_warning("Warning: fail_over_mac only affects active-backup mode.\n");
 	} else {
 		fail_over_mac_value = BOND_FOM_NONE;
 	}
@@ -5076,8 +4920,7 @@
 	bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
 				bond_setup);
 	if (!bond_dev) {
-		pr_err(DRV_NAME ": %s: eek! can't alloc netdev!\n",
-		       name);
+		pr_err("%s: eek! can't alloc netdev!\n", name);
 		res = -ENOMEM;
 		goto out;
 	}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 4e00b4f..5acd557 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -19,6 +19,9 @@
  * file called LICENSE.
  *
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -109,11 +112,10 @@
 		goto err_no_cmd;
 
 	if (command[0] == '+') {
-		pr_info(DRV_NAME
-			": %s is being created...\n", ifname);
+		pr_info("%s is being created...\n", ifname);
 		rv = bond_create(net, ifname);
 		if (rv) {
-			pr_info(DRV_NAME ": Bond creation failed.\n");
+			pr_info("Bond creation failed.\n");
 			res = rv;
 		}
 	} else if (command[0] == '-') {
@@ -122,12 +124,10 @@
 		rtnl_lock();
 		bond_dev = bond_get_by_name(net, ifname);
 		if (bond_dev) {
-			pr_info(DRV_NAME ": %s is being deleted...\n",
-				ifname);
+			pr_info("%s is being deleted...\n", ifname);
 			unregister_netdevice(bond_dev);
 		} else {
-			pr_err(DRV_NAME ": unable to delete non-existent %s\n",
-			       ifname);
+			pr_err("unable to delete non-existent %s\n", ifname);
 			res = -ENODEV;
 		}
 		rtnl_unlock();
@@ -140,8 +140,7 @@
 	return res;
 
 err_no_cmd:
-	pr_err(DRV_NAME ": no command found in bonding_masters."
-	       " Use +ifname or -ifname.\n");
+	pr_err("no command found in bonding_masters. Use +ifname or -ifname.\n");
 	return -EPERM;
 }
 
@@ -225,8 +224,8 @@
 
 	/* Quick sanity check -- is the bond interface up? */
 	if (!(bond->dev->flags & IFF_UP)) {
-		pr_warning(DRV_NAME ": %s: doing slave updates when "
-			   "interface is down.\n", bond->dev->name);
+		pr_warning("%s: doing slave updates when interface is down.\n",
+			   bond->dev->name);
 	}
 
 	/* Note:  We can't hold bond->lock here, as bond_create grabs it. */
@@ -247,17 +246,14 @@
 
 		dev = __dev_get_by_name(dev_net(bond->dev), ifname);
 		if (!dev) {
-			pr_info(DRV_NAME
-			       ": %s: Interface %s does not exist!\n",
-			       bond->dev->name, ifname);
+			pr_info("%s: Interface %s does not exist!\n",
+				bond->dev->name, ifname);
 			ret = -ENODEV;
 			goto out;
 		}
 
 		if (dev->flags & IFF_UP) {
-			pr_err(DRV_NAME
-			       ": %s: Error: Unable to enslave %s "
-			       "because it is already up.\n",
+			pr_err("%s: Error: Unable to enslave %s because it is already up.\n",
 			       bond->dev->name, dev->name);
 			ret = -EPERM;
 			goto out;
@@ -266,8 +262,7 @@
 		read_lock(&bond->lock);
 		bond_for_each_slave(bond, slave, i)
 			if (slave->dev == dev) {
-				pr_err(DRV_NAME
-				       ": %s: Interface %s is already enslaved!\n",
+				pr_err("%s: Interface %s is already enslaved!\n",
 				       bond->dev->name, ifname);
 				ret = -EPERM;
 				read_unlock(&bond->lock);
@@ -275,8 +270,7 @@
 			}
 		read_unlock(&bond->lock);
 
-		pr_info(DRV_NAME ": %s: Adding slave %s.\n",
-			bond->dev->name, ifname);
+		pr_info("%s: Adding slave %s.\n", bond->dev->name, ifname);
 
 		/* If this is the first slave, then we need to set
 		   the master's hardware address to be the same as the
@@ -313,7 +307,7 @@
 				break;
 			}
 		if (dev) {
-			pr_info(DRV_NAME ": %s: Removing slave %s\n",
+			pr_info("%s: Removing slave %s\n",
 				bond->dev->name, dev->name);
 				res = bond_release(bond->dev, dev);
 			if (res) {
@@ -323,16 +317,16 @@
 			/* set the slave MTU to the default */
 			dev_set_mtu(dev, original_mtu);
 		} else {
-			pr_err(DRV_NAME ": unable to remove non-existent"
-			       " slave %s for bond %s.\n",
-				ifname, bond->dev->name);
+			pr_err("unable to remove non-existent slave %s for bond %s.\n",
+			       ifname, bond->dev->name);
 			ret = -ENODEV;
 		}
 		goto out;
 	}
 
 err_no_cmd:
-	pr_err(DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
+	pr_err("no command found in slaves file for bond %s. Use +ifname or -ifname.\n",
+	       bond->dev->name);
 	ret = -EPERM;
 
 out:
@@ -365,18 +359,16 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		pr_err(DRV_NAME ": unable to update mode of %s"
-		       " because interface is up.\n", bond->dev->name);
+		pr_err("unable to update mode of %s because interface is up.\n",
+		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
 
 	new_value = bond_parse_parm(buf, bond_mode_tbl);
 	if (new_value < 0)  {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid mode value %.*s.\n",
-		       bond->dev->name,
-		       (int)strlen(buf) - 1, buf);
+		pr_err("%s: Ignoring invalid mode value %.*s.\n",
+		       bond->dev->name, (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
 		goto out;
 	} else {
@@ -388,8 +380,8 @@
 
 		bond->params.mode = new_value;
 		bond_set_mode_ops(bond, bond->params.mode);
-		pr_info(DRV_NAME ": %s: setting mode to %s (%d).\n",
-		       bond->dev->name, bond_mode_tbl[new_value].modename,
+		pr_info("%s: setting mode to %s (%d).\n",
+			bond->dev->name, bond_mode_tbl[new_value].modename,
 		       new_value);
 	}
 out:
@@ -421,8 +413,7 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		pr_err(DRV_NAME
-		       "%s: Interface is up. Unable to update xmit policy.\n",
+		pr_err("%s: Interface is up. Unable to update xmit policy.\n",
 		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
@@ -430,8 +421,7 @@
 
 	new_value = bond_parse_parm(buf, xmit_hashtype_tbl);
 	if (new_value < 0)  {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
+		pr_err("%s: Ignoring invalid xmit hash policy value %.*s.\n",
 		       bond->dev->name,
 		       (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
@@ -439,7 +429,7 @@
 	} else {
 		bond->params.xmit_policy = new_value;
 		bond_set_mode_ops(bond, bond->params.mode);
-		pr_info(DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+		pr_info("%s: setting xmit hash policy to %s (%d).\n",
 			bond->dev->name,
 			xmit_hashtype_tbl[new_value].modename, new_value);
 	}
@@ -472,20 +462,18 @@
 
 	new_value = bond_parse_parm(buf, arp_validate_tbl);
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid arp_validate value %s\n",
+		pr_err("%s: Ignoring invalid arp_validate value %s\n",
 		       bond->dev->name, buf);
 		return -EINVAL;
 	}
 	if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
-		pr_err(DRV_NAME
-		       ": %s: arp_validate only supported in active-backup mode.\n",
+		pr_err("%s: arp_validate only supported in active-backup mode.\n",
 		       bond->dev->name);
 		return -EINVAL;
 	}
-	pr_info(DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
-	       bond->dev->name, arp_validate_tbl[new_value].modename,
-	       new_value);
+	pr_info("%s: setting arp_validate to %s (%d).\n",
+		bond->dev->name, arp_validate_tbl[new_value].modename,
+		new_value);
 
 	if (!bond->params.arp_validate && new_value)
 		bond_register_arp(bond);
@@ -523,24 +511,22 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->slave_cnt != 0) {
-		pr_err(DRV_NAME
-		       ": %s: Can't alter fail_over_mac with slaves in bond.\n",
+		pr_err("%s: Can't alter fail_over_mac with slaves in bond.\n",
 		       bond->dev->name);
 		return -EPERM;
 	}
 
 	new_value = bond_parse_parm(buf, fail_over_mac_tbl);
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid fail_over_mac value %s.\n",
+		pr_err("%s: Ignoring invalid fail_over_mac value %s.\n",
 		       bond->dev->name, buf);
 		return -EINVAL;
 	}
 
 	bond->params.fail_over_mac = new_value;
-	pr_info(DRV_NAME ": %s: Setting fail_over_mac to %s (%d).\n",
-	       bond->dev->name, fail_over_mac_tbl[new_value].modename,
-	       new_value);
+	pr_info("%s: Setting fail_over_mac to %s (%d).\n",
+		bond->dev->name, fail_over_mac_tbl[new_value].modename,
+		new_value);
 
 	return count;
 }
@@ -571,31 +557,26 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no arp_interval value specified.\n",
+		pr_err("%s: no arp_interval value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+		pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
 		       bond->dev->name, new_value, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	pr_info(DRV_NAME
-	       ": %s: Setting ARP monitoring interval to %d.\n",
-	       bond->dev->name, new_value);
+	pr_info("%s: Setting ARP monitoring interval to %d.\n",
+		bond->dev->name, new_value);
 	bond->params.arp_interval = new_value;
 	if (bond->params.arp_interval)
 		bond->dev->priv_flags |= IFF_MASTER_ARPMON;
 	if (bond->params.miimon) {
-		pr_info(DRV_NAME
-		       ": %s: ARP monitoring cannot be used with MII monitoring. "
-		       "%s Disabling MII monitoring.\n",
-		       bond->dev->name, bond->dev->name);
+		pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+			bond->dev->name, bond->dev->name);
 		bond->params.miimon = 0;
 		if (delayed_work_pending(&bond->mii_work)) {
 			cancel_delayed_work(&bond->mii_work);
@@ -603,10 +584,8 @@
 		}
 	}
 	if (!bond->params.arp_targets[0]) {
-		pr_info(DRV_NAME
-		       ": %s: ARP monitoring has been set up, "
-		       "but no ARP targets have been specified.\n",
-		       bond->dev->name);
+		pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+			bond->dev->name);
 	}
 	if (bond->dev->flags & IFF_UP) {
 		/* If the interface is up, we may need to fire off
@@ -666,8 +645,7 @@
 	/* look for adds */
 	if (buf[0] == '+') {
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-			pr_err(DRV_NAME
-			       ": %s: invalid ARP target %pI4 specified for addition\n",
+			pr_err("%s: invalid ARP target %pI4 specified for addition\n",
 			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
@@ -675,23 +653,20 @@
 		/* look for an empty slot to put the target in, and check for dupes */
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
 			if (targets[i] == newtarget) { /* duplicate */
-				pr_err(DRV_NAME
-				       ": %s: ARP target %pI4 is already present\n",
+				pr_err("%s: ARP target %pI4 is already present\n",
 				       bond->dev->name, &newtarget);
 				ret = -EINVAL;
 				goto out;
 			}
 			if (targets[i] == 0) {
-				pr_info(DRV_NAME
-				       ": %s: adding ARP target %pI4.\n",
-				       bond->dev->name, &newtarget);
+				pr_info("%s: adding ARP target %pI4.\n",
+					bond->dev->name, &newtarget);
 				done = 1;
 				targets[i] = newtarget;
 			}
 		}
 		if (!done) {
-			pr_err(DRV_NAME
-			       ": %s: ARP target table is full!\n",
+			pr_err("%s: ARP target table is full!\n",
 			       bond->dev->name);
 			ret = -EINVAL;
 			goto out;
@@ -699,8 +674,7 @@
 
 	} else if (buf[0] == '-')	{
 		if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
-			pr_err(DRV_NAME
-			       ": %s: invalid ARP target %pI4 specified for removal\n",
+			pr_err("%s: invalid ARP target %pI4 specified for removal\n",
 			       bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
@@ -709,9 +683,8 @@
 		for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
 			if (targets[i] == newtarget) {
 				int j;
-				pr_info(DRV_NAME
-				       ": %s: removing ARP target %pI4.\n",
-				       bond->dev->name, &newtarget);
+				pr_info("%s: removing ARP target %pI4.\n",
+					bond->dev->name, &newtarget);
 				for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
 					targets[j] = targets[j+1];
 
@@ -720,16 +693,14 @@
 			}
 		}
 		if (!done) {
-			pr_info(DRV_NAME
-			       ": %s: unable to remove nonexistent ARP target %pI4.\n",
-			       bond->dev->name, &newtarget);
+			pr_info("%s: unable to remove nonexistent ARP target %pI4.\n",
+				bond->dev->name, &newtarget);
 			ret = -EINVAL;
 			goto out;
 		}
 	} else {
-		pr_err(DRV_NAME ": no command found in arp_ip_targets file"
-		       " for bond %s. Use +<addr> or -<addr>.\n",
-			bond->dev->name);
+		pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
@@ -761,41 +732,34 @@
 	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
-		pr_err(DRV_NAME
-		       ": %s: Unable to set down delay as MII monitoring is disabled\n",
+		pr_err("%s: Unable to set down delay as MII monitoring is disabled\n",
 		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no down delay value specified.\n",
-		       bond->dev->name);
+		pr_err("%s: no down delay value specified.\n", bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
 		if ((new_value % bond->params.miimon) != 0) {
-			pr_warning(DRV_NAME
-				   ": %s: Warning: down delay (%d) is not a "
-				   "multiple of miimon (%d), delay rounded "
-				   "to %d ms\n",
+			pr_warning("%s: Warning: down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
 				   bond->dev->name, new_value,
 				   bond->params.miimon,
 				   (new_value / bond->params.miimon) *
 				   bond->params.miimon);
 		}
 		bond->params.downdelay = new_value / bond->params.miimon;
-		pr_info(DRV_NAME ": %s: Setting down delay to %d.\n",
-		       bond->dev->name,
-		       bond->params.downdelay * bond->params.miimon);
+		pr_info("%s: Setting down delay to %d.\n",
+			bond->dev->name,
+			bond->params.downdelay * bond->params.miimon);
 
 	}
 
@@ -823,41 +787,35 @@
 	struct bonding *bond = to_bond(d);
 
 	if (!(bond->params.miimon)) {
-		pr_err(DRV_NAME
-		       ": %s: Unable to set up delay as MII monitoring is disabled\n",
+		pr_err("%s: Unable to set up delay as MII monitoring is disabled\n",
 		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no up delay value specified.\n",
+		pr_err("%s: no up delay value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+		pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
 		if ((new_value % bond->params.miimon) != 0) {
-			pr_warning(DRV_NAME
-				   ": %s: Warning: up delay (%d) is not a "
-				   "multiple of miimon (%d), updelay rounded "
-				   "to %d ms\n",
+			pr_warning("%s: Warning: up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
 				   bond->dev->name, new_value,
 				   bond->params.miimon,
 				   (new_value / bond->params.miimon) *
 				   bond->params.miimon);
 		}
 		bond->params.updelay = new_value / bond->params.miimon;
-		pr_info(DRV_NAME ": %s: Setting up delay to %d.\n",
-		       bond->dev->name, bond->params.updelay * bond->params.miimon);
-
+		pr_info("%s: Setting up delay to %d.\n",
+			bond->dev->name,
+			bond->params.updelay * bond->params.miimon);
 	}
 
 out:
@@ -889,16 +847,14 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		pr_err(DRV_NAME
-		       ": %s: Unable to update LACP rate because interface is up.\n",
+		pr_err("%s: Unable to update LACP rate because interface is up.\n",
 		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
 
 	if (bond->params.mode != BOND_MODE_8023AD) {
-		pr_err(DRV_NAME
-		       ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+		pr_err("%s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
 		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
@@ -908,12 +864,11 @@
 
 	if ((new_value == 1) || (new_value == 0)) {
 		bond->params.lacp_fast = new_value;
-		pr_info(DRV_NAME ": %s: Setting LACP rate to %s (%d).\n",
+		pr_info("%s: Setting LACP rate to %s (%d).\n",
 			bond->dev->name, bond_lacp_tbl[new_value].modename,
 			new_value);
 	} else {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid LACP rate value %.*s.\n",
+		pr_err("%s: Ignoring invalid LACP rate value %.*s.\n",
 		       bond->dev->name, (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
 	}
@@ -943,9 +898,8 @@
 	struct bonding *bond = to_bond(d);
 
 	if (bond->dev->flags & IFF_UP) {
-		pr_err(DRV_NAME
-		       ": %s: Unable to update ad_select because interface "
-		       "is up.\n", bond->dev->name);
+		pr_err("%s: Unable to update ad_select because interface is up.\n",
+		       bond->dev->name);
 		ret = -EPERM;
 		goto out;
 	}
@@ -954,13 +908,11 @@
 
 	if (new_value != -1) {
 		bond->params.ad_select = new_value;
-		pr_info(DRV_NAME
-		       ": %s: Setting ad_select to %s (%d).\n",
-		       bond->dev->name, ad_select_tbl[new_value].modename,
-		       new_value);
+		pr_info("%s: Setting ad_select to %s (%d).\n",
+			bond->dev->name, ad_select_tbl[new_value].modename,
+			new_value);
 	} else {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid ad_select value %.*s.\n",
+		pr_err("%s: Ignoring invalid ad_select value %.*s.\n",
 		       bond->dev->name, (int)strlen(buf) - 1, buf);
 		ret = -EINVAL;
 	}
@@ -990,15 +942,13 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no num_grat_arp value specified.\n",
+		pr_err("%s: no num_grat_arp value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0 || new_value > 255) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
+		pr_err("%s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
 		       bond->dev->name, new_value);
 		ret = -EINVAL;
 		goto out;
@@ -1031,16 +981,14 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no num_unsol_na value specified.\n",
+		pr_err("%s: no num_unsol_na value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
 	if (new_value < 0 || new_value > 255) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
+		pr_err("%s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
 		       bond->dev->name, new_value);
 		ret = -EINVAL;
 		goto out;
@@ -1075,40 +1023,31 @@
 	struct bonding *bond = to_bond(d);
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no miimon value specified.\n",
+		pr_err("%s: no miimon value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if (new_value < 0) {
-		pr_err(DRV_NAME
-		       ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
+		pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
 		       bond->dev->name, new_value, 1, INT_MAX);
 		ret = -EINVAL;
 		goto out;
 	} else {
-		pr_info(DRV_NAME
-		       ": %s: Setting MII monitoring interval to %d.\n",
-		       bond->dev->name, new_value);
+		pr_info("%s: Setting MII monitoring interval to %d.\n",
+			bond->dev->name, new_value);
 		bond->params.miimon = new_value;
 		if (bond->params.updelay)
-			pr_info(DRV_NAME
-			      ": %s: Note: Updating updelay (to %d) "
-			      "since it is a multiple of the miimon value.\n",
-			      bond->dev->name,
-			      bond->params.updelay * bond->params.miimon);
+			pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+				bond->dev->name,
+				bond->params.updelay * bond->params.miimon);
 		if (bond->params.downdelay)
-			pr_info(DRV_NAME
-			      ": %s: Note: Updating downdelay (to %d) "
-			      "since it is a multiple of the miimon value.\n",
-			      bond->dev->name,
-			      bond->params.downdelay * bond->params.miimon);
+			pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+				bond->dev->name,
+				bond->params.downdelay * bond->params.miimon);
 		if (bond->params.arp_interval) {
-			pr_info(DRV_NAME
-			       ": %s: MII monitoring cannot be used with "
-			       "ARP monitoring. Disabling ARP monitoring...\n",
-			       bond->dev->name);
+			pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+				bond->dev->name);
 			bond->params.arp_interval = 0;
 			bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
 			if (bond->params.arp_validate) {
@@ -1176,17 +1115,15 @@
 	write_lock_bh(&bond->curr_slave_lock);
 
 	if (!USES_PRIMARY(bond->params.mode)) {
-		pr_info(DRV_NAME
-		       ": %s: Unable to set primary slave; %s is in mode %d\n",
-		       bond->dev->name, bond->dev->name, bond->params.mode);
+		pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
+			bond->dev->name, bond->dev->name, bond->params.mode);
 	} else {
 		bond_for_each_slave(bond, slave, i) {
 			if (strnicmp
 			    (slave->dev->name, buf,
 			     strlen(slave->dev->name)) == 0) {
-				pr_info(DRV_NAME
-				       ": %s: Setting %s as primary slave.\n",
-				       bond->dev->name, slave->dev->name);
+				pr_info("%s: Setting %s as primary slave.\n",
+					bond->dev->name, slave->dev->name);
 				bond->primary_slave = slave;
 				strcpy(bond->params.primary, slave->dev->name);
 				bond_select_active_slave(bond);
@@ -1197,15 +1134,13 @@
 		/* if we got here, then we didn't match the name of any slave */
 
 		if (strlen(buf) == 0 || buf[0] == '\n') {
-			pr_info(DRV_NAME
-			       ": %s: Setting primary slave to None.\n",
-			       bond->dev->name);
+			pr_info("%s: Setting primary slave to None.\n",
+				bond->dev->name);
 			bond->primary_slave = NULL;
 				bond_select_active_slave(bond);
 		} else {
-			pr_info(DRV_NAME
-			       ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
-			       bond->dev->name, (int)strlen(buf) - 1, buf);
+			pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n",
+				bond->dev->name, (int)strlen(buf) - 1, buf);
 		}
 	}
 out:
@@ -1244,8 +1179,7 @@
 
 	new_value = bond_parse_parm(buf, pri_reselect_tbl);
 	if (new_value < 0)  {
-		pr_err(DRV_NAME
-		       ": %s: Ignoring invalid primary_reselect value %.*s.\n",
+		pr_err("%s: Ignoring invalid primary_reselect value %.*s.\n",
 		       bond->dev->name,
 		       (int) strlen(buf) - 1, buf);
 		ret = -EINVAL;
@@ -1253,7 +1187,7 @@
 	}
 
 	bond->params.primary_reselect = new_value;
-	pr_info(DRV_NAME ": %s: setting primary_reselect to %s (%d).\n",
+	pr_info("%s: setting primary_reselect to %s (%d).\n",
 		bond->dev->name, pri_reselect_tbl[new_value].modename,
 		new_value);
 
@@ -1291,20 +1225,18 @@
 
 
 	if (sscanf(buf, "%d", &new_value) != 1) {
-		pr_err(DRV_NAME
-		       ": %s: no use_carrier value specified.\n",
+		pr_err("%s: no use_carrier value specified.\n",
 		       bond->dev->name);
 		ret = -EINVAL;
 		goto out;
 	}
 	if ((new_value == 0) || (new_value == 1)) {
 		bond->params.use_carrier = new_value;
-		pr_info(DRV_NAME ": %s: Setting use_carrier to %d.\n",
-		       bond->dev->name, new_value);
+		pr_info("%s: Setting use_carrier to %d.\n",
+			bond->dev->name, new_value);
 	} else {
-		pr_info(DRV_NAME
-		       ": %s: Ignoring invalid use_carrier value %d.\n",
-		       bond->dev->name, new_value);
+		pr_info("%s: Ignoring invalid use_carrier value %d.\n",
+			bond->dev->name, new_value);
 	}
 out:
 	return count;
@@ -1349,8 +1281,7 @@
 	write_lock_bh(&bond->curr_slave_lock);
 
 	if (!USES_PRIMARY(bond->params.mode))
-		pr_info(DRV_NAME ": %s: Unable to change active slave;"
-			" %s is in mode %d\n",
+		pr_info("%s: Unable to change active slave; %s is in mode %d\n",
 			bond->dev->name, bond->dev->name, bond->params.mode);
 	else {
 		bond_for_each_slave(bond, slave, i) {
@@ -1361,9 +1292,9 @@
         			new_active = slave;
         			if (new_active == old_active) {
 					/* do nothing */
-					pr_info(DRV_NAME
-						": %s: %s is already the current active slave.\n",
-						bond->dev->name, slave->dev->name);
+					pr_info("%s: %s is already the current active slave.\n",
+						bond->dev->name,
+						slave->dev->name);
 					goto out;
 				}
 				else {
@@ -1371,16 +1302,15 @@
             				    (old_active) &&
 				            (new_active->link == BOND_LINK_UP) &&
 				            IS_UP(new_active->dev)) {
-						pr_info(DRV_NAME
-							": %s: Setting %s as active slave.\n",
-							bond->dev->name, slave->dev->name);
+						pr_info("%s: Setting %s as active slave.\n",
+							bond->dev->name,
+							slave->dev->name);
 							bond_change_active_slave(bond, new_active);
         				}
 					else {
-						pr_info(DRV_NAME
-							": %s: Could not set %s as active slave; "
-							"either %s is down or the link is down.\n",
-							bond->dev->name, slave->dev->name,
+						pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
+							bond->dev->name,
+							slave->dev->name,
 							slave->dev->name);
 					}
 					goto out;
@@ -1391,14 +1321,12 @@
 		/* if we got here, then we didn't match the name of any slave */
 
 		if (strlen(buf) == 0 || buf[0] == '\n') {
-			pr_info(DRV_NAME
-				": %s: Setting active slave to None.\n",
+			pr_info("%s: Setting active slave to None.\n",
 				bond->dev->name);
 			bond->primary_slave = NULL;
 			bond_select_active_slave(bond);
 		} else {
-			pr_info(DRV_NAME ": %s: Unable to set %.*s"
-				" as active slave as it is not a slave.\n",
+			pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n",
 				bond->dev->name, (int)strlen(buf) - 1, buf);
 		}
 	}
@@ -1600,8 +1528,7 @@
 		/* Is someone being kinky and naming a device bonding_master? */
 		if (__dev_get_by_name(&init_net,
 				      class_attr_bonding_masters.attr.name))
-			pr_err("network device named %s already "
-			       "exists in sysfs",
+			pr_err("network device named %s already exists in sysfs",
 			       class_attr_bonding_masters.attr.name);
 		ret = 0;
 	}
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 8c485aa..05b7517 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -50,7 +50,7 @@
 
 config CAN_MCP251X
 	tristate "Microchip MCP251x SPI CAN controllers"
-	depends on CAN_DEV && SPI
+	depends on CAN_DEV && SPI && HAS_DMA
 	---help---
 	  Driver for the Microchip MCP251x SPI CAN controllers.
 
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index cbe3fce..d0ec178 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -474,7 +474,7 @@
 	reg_msr = at91_read(priv, AT91_MSR(mb));
 	if (reg_msr & AT91_MSR_MRTR)
 		cf->can_id |= CAN_RTR_FLAG;
-	cf->can_dlc = min_t(__u8, (reg_msr >> 16) & 0xf, 8);
+	cf->can_dlc = get_can_dlc((reg_msr >> 16) & 0xf);
 
 	*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
 	*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index c7fc1de..0ec1524 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -392,7 +392,7 @@
 		cf->can_id |= CAN_RTR_FLAG;
 
 	/* get data length code */
-	cf->can_dlc = bfin_read16(&reg->chl[obj].dlc);
+	cf->can_dlc = get_can_dlc(bfin_read16(&reg->chl[obj].dlc) & 0xF);
 
 	/* get payload */
 	for (i = 0; i < 8; i += 2) {
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index 78b1b69..9c5a153 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -403,9 +403,8 @@
 
 		for (i = 1; i < RXBDAT_OFF; i++)
 			buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);
-		len = buf[RXBDLC_OFF] & RXBDLC_LEN_MASK;
-		if (len > 8)
-			len = 8;
+
+		len = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);
 		for (; i < (RXBDAT_OFF + len); i++)
 			buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i);
 	} else {
@@ -455,13 +454,7 @@
 			(buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT);
 	}
 	/* Data length */
-	frame->can_dlc = buf[RXBDLC_OFF] & RXBDLC_LEN_MASK;
-	if (frame->can_dlc > 8) {
-		dev_warn(&spi->dev, "invalid frame recevied\n");
-		priv->net->stats.rx_errors++;
-		dev_kfree_skb(skb);
-		return;
-	}
+	frame->can_dlc = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);
 	memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc);
 
 	priv->net->stats.rx_packets++;
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index bb06dfb..07346f88 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -297,7 +297,8 @@
 	frame->can_id |= can_id >> 1;
 	if (can_id & 1)
 		frame->can_id |= CAN_RTR_FLAG;
-	frame->can_dlc = in_8(&regs->rx.dlr) & 0xf;
+
+	frame->can_dlc = get_can_dlc(in_8(&regs->rx.dlr) & 0xf);
 
 	if (!(frame->can_id & CAN_RTR_FLAG)) {
 		void __iomem *data = &regs->rx.dsr1_0;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index b4ba88a..542a4f7 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -293,15 +293,14 @@
 	uint8_t fi;
 	uint8_t dreg;
 	canid_t id;
-	uint8_t dlc;
 	int i;
 
+	/* create zero'ed CAN frame buffer */
 	skb = alloc_can_skb(dev, &cf);
 	if (skb == NULL)
 		return;
 
 	fi = priv->read_reg(priv, REG_FI);
-	dlc = fi & 0x0F;
 
 	if (fi & FI_FF) {
 		/* extended frame format (EFF) */
@@ -318,16 +317,15 @@
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
 
-	if (fi & FI_RTR)
+	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
+	} else {
+		cf->can_dlc = get_can_dlc(fi & 0x0F);
+		for (i = 0; i < cf->can_dlc; i++)
+			cf->data[i] = priv->read_reg(priv, dreg++);
+	}
 
 	cf->can_id = id;
-	cf->can_dlc = dlc;
-	for (i = 0; i < dlc; i++)
-		cf->data[i] = priv->read_reg(priv, dreg++);
-
-	while (i < 8)
-		cf->data[i++] = 0;
 
 	/* release receive buffer */
 	priv->write_reg(priv, REG_CMR, CMD_RRB);
@@ -335,7 +333,7 @@
 	netif_rx(skb);
 
 	stats->rx_packets++;
-	stats->rx_bytes += dlc;
+	stats->rx_bytes += cf->can_dlc;
 }
 
 static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index 07e8016..5c993c2 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -552,7 +552,7 @@
 	data = hecc_read_mbx(priv, mbxno, HECC_CANMCF);
 	if (data & HECC_CANMCF_RTR)
 		cf->can_id |= CAN_RTR_FLAG;
-	cf->can_dlc = data & 0xF;
+	cf->can_dlc = get_can_dlc(data & 0xF);
 	data = hecc_read_mbx(priv, mbxno, HECC_CANMDL);
 	*(u32 *)(cf->data) = cpu_to_be32(data);
 	if (cf->can_dlc > 4) {
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 591eb0eb..efbb05c7 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -316,7 +316,7 @@
 		return;
 
 	cf->can_id = le32_to_cpu(msg->msg.can_msg.id);
-	cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8);
+	cf->can_dlc = get_can_dlc(msg->msg.can_msg.length & 0xF);
 
 	if (msg->type == CPC_MSG_TYPE_EXT_CAN_FRAME ||
 	    msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 6782223..8d0be26 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1163,7 +1163,7 @@
 	priv->dev = dev;
 	priv->ring_size = 64;
 	priv->msg_enable = netif_msg_init(debug_level, 0xff);
-	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
+	memcpy(dev->dev_addr, pdata->dev_addr, sizeof(pdata->dev_addr));
 
 	snprintf(priv->phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
 
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index e2d5343..204177d 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -510,6 +510,40 @@
 }
 
 /**
+ *  ixgbe_validate_link_ready - Function looks for phy link
+ *  @hw: pointer to hardware structure
+ *
+ *  Function indicates success when phy link is available. If phy is not ready
+ *  within 5 seconds of MAC indicating link, the function returns error.
+ **/
+static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw)
+{
+	u32 timeout;
+	u16 an_reg;
+
+	if (hw->device_id != IXGBE_DEV_ID_82598AT2)
+		return 0;
+
+	for (timeout = 0;
+	     timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) {
+		hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, &an_reg);
+
+		if ((an_reg & MDIO_AN_STAT1_COMPLETE) &&
+		    (an_reg & MDIO_STAT1_LSTATUS))
+			break;
+
+		msleep(100);
+	}
+
+	if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
+		hw_dbg(hw, "Link was indicated but link is down\n");
+		return IXGBE_ERR_LINK_SETUP;
+	}
+
+	return 0;
+}
+
+/**
  *  ixgbe_check_mac_link_82598 - Get link/speed status
  *  @hw: pointer to hardware structure
  *  @speed: pointer to link speed
@@ -589,6 +623,10 @@
 	else
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
 
+	if ((hw->device_id == IXGBE_DEV_ID_82598AT2) && (*link_up == true) &&
+	    (ixgbe_validate_link_ready(hw) != 0))
+		*link_up = false;
+
 	/* if link is down, zero out the current_mode */
 	if (*link_up == false) {
 		hw->fc.current_mode = ixgbe_fc_none;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 35ea8c9..bd64387 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -4511,6 +4511,7 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	u64 total_mpc = 0;
 	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
+	u64 non_eop_descs = 0, restart_queue = 0;
 
 	if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
 		u64 rsc_count = 0;
@@ -4528,10 +4529,12 @@
 
 	/* gather some stats to the adapter struct that are per queue */
 	for (i = 0; i < adapter->num_tx_queues; i++)
-		adapter->restart_queue += adapter->tx_ring[i].restart_queue;
+		restart_queue += adapter->tx_ring[i].restart_queue;
+	adapter->restart_queue = restart_queue;
 
 	for (i = 0; i < adapter->num_rx_queues; i++)
-		adapter->non_eop_descs += adapter->tx_ring[i].non_eop_descs;
+		non_eop_descs += adapter->rx_ring[i].non_eop_descs;
+	adapter->non_eop_descs = non_eop_descs;
 
 	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
 	for (i = 0; i < 8; i++) {
@@ -5003,7 +5006,18 @@
 		                    IXGBE_ADVTXD_DTYP_CTXT);
 
 		if (skb->ip_summed == CHECKSUM_PARTIAL) {
-			switch (skb->protocol) {
+			__be16 protocol;
+
+			if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) {
+				const struct vlan_ethhdr *vhdr =
+					(const struct vlan_ethhdr *)skb->data;
+
+				protocol = vhdr->h_vlan_encapsulated_proto;
+			} else {
+				protocol = skb->protocol;
+			}
+
+			switch (protocol) {
 			case cpu_to_be16(ETH_P_IP):
 				type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
 				if (ip_hdr(skb)->protocol == IPPROTO_TCP)
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index f3e8d52..84650c6 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -841,6 +841,8 @@
 #define IXGBE_MPVC      0x04318
 #define IXGBE_SGMIIC    0x04314
 
+#define IXGBE_VALIDATE_LINK_READY_TIMEOUT 50
+
 /* Omer CORECTL */
 #define IXGBE_CORECTL           0x014F00
 /* BARCTRL */
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index ad95d5f..8c85156 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -72,35 +72,6 @@
 	mlx4_bitmap_free_range(bitmap, obj, 1);
 }
 
-static unsigned long find_aligned_range(unsigned long *bitmap,
-					u32 start, u32 nbits,
-					int len, int align)
-{
-	unsigned long end, i;
-
-again:
-	start = ALIGN(start, align);
-
-	while ((start < nbits) && test_bit(start, bitmap))
-		start += align;
-
-	if (start >= nbits)
-		return -1;
-
-	end = start+len;
-	if (end > nbits)
-		return -1;
-
-	for (i = start + 1; i < end; i++) {
-		if (test_bit(i, bitmap)) {
-			start = i + 1;
-			goto again;
-		}
-	}
-
-	return start;
-}
-
 u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
 {
 	u32 obj, i;
@@ -110,13 +81,13 @@
 
 	spin_lock(&bitmap->lock);
 
-	obj = find_aligned_range(bitmap->table, bitmap->last,
-				 bitmap->max, cnt, align);
+	obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max,
+				bitmap->last, cnt, align - 1);
 	if (obj >= bitmap->max) {
 		bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 				& bitmap->mask;
-		obj = find_aligned_range(bitmap->table, 0, bitmap->max,
-					 cnt, align);
+		obj = bitmap_find_next_zero_area(bitmap->table, bitmap->max,
+						0, cnt, align - 1);
 	}
 
 	if (obj < bitmap->max) {
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index 3c16602..04f42ae 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -90,6 +90,7 @@
 		[ 9] = "Q_Key violation counter",
 		[10] = "VMM",
 		[12] = "DPDP",
+		[15] = "Big LSO headers",
 		[16] = "MW support",
 		[17] = "APM support",
 		[18] = "Atomic ops support",
@@ -235,7 +236,7 @@
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MPT_OFFSET);
 	dev_cap->max_mpts = 1 << (field & 0x3f);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_EQ_OFFSET);
-	dev_cap->reserved_eqs = 1 << (field & 0xf);
+	dev_cap->reserved_eqs = field & 0xf;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_EQ_OFFSET);
 	dev_cap->max_eqs = 1 << (field & 0xf);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
diff --git a/drivers/net/mlx4/sense.c b/drivers/net/mlx4/sense.c
index f36ae69..015fbe78 100644
--- a/drivers/net/mlx4/sense.c
+++ b/drivers/net/mlx4/sense.c
@@ -53,7 +53,7 @@
 
 	if (out_param > 2) {
 		mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", out_param);
-		return EINVAL;
+		return -EINVAL;
 	}
 
 	*type = out_param;
diff --git a/drivers/net/octeon/Kconfig b/drivers/net/octeon/Kconfig
new file mode 100644
index 0000000..1e56bbf
--- /dev/null
+++ b/drivers/net/octeon/Kconfig
@@ -0,0 +1,10 @@
+config OCTEON_MGMT_ETHERNET
+	tristate "Octeon Management port ethernet driver (CN5XXX, CN6XXX)"
+	depends on  CPU_CAVIUM_OCTEON
+	select PHYLIB
+	select MDIO_OCTEON
+	default y
+	help
+	  This option enables the ethernet driver for the management
+	  port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
+	  CN54XX, CN52XX, and CN6XXX chips.
diff --git a/drivers/net/octeon/Makefile b/drivers/net/octeon/Makefile
new file mode 100644
index 0000000..906edeca
--- /dev/null
+++ b/drivers/net/octeon/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_OCTEON_MGMT_ETHERNET)	+= octeon_mgmt.o
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
new file mode 100644
index 0000000..050538b
--- /dev/null
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -0,0 +1,1176 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Cavium Networks
+ */
+
+#include <linux/capability.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/phy.h>
+#include <linux/spinlock.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-mixx-defs.h>
+#include <asm/octeon/cvmx-agl-defs.h>
+
+#define DRV_NAME "octeon_mgmt"
+#define DRV_VERSION "2.0"
+#define DRV_DESCRIPTION \
+	"Cavium Networks Octeon MII (management) port Network Driver"
+
+#define OCTEON_MGMT_NAPI_WEIGHT 16
+
+/*
+ * Ring sizes that are powers of two allow for more efficient modulo
+ * opertions.
+ */
+#define OCTEON_MGMT_RX_RING_SIZE 512
+#define OCTEON_MGMT_TX_RING_SIZE 128
+
+/* Allow 8 bytes for vlan and FCS. */
+#define OCTEON_MGMT_RX_HEADROOM (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN)
+
+union mgmt_port_ring_entry {
+	u64 d64;
+	struct {
+		u64    reserved_62_63:2;
+		/* Length of the buffer/packet in bytes */
+		u64    len:14;
+		/* For TX, signals that the packet should be timestamped */
+		u64    tstamp:1;
+		/* The RX error code */
+		u64    code:7;
+#define RING_ENTRY_CODE_DONE 0xf
+#define RING_ENTRY_CODE_MORE 0x10
+		/* Physical address of the buffer */
+		u64    addr:40;
+	} s;
+};
+
+struct octeon_mgmt {
+	struct net_device *netdev;
+	int port;
+	int irq;
+	u64 *tx_ring;
+	dma_addr_t tx_ring_handle;
+	unsigned int tx_next;
+	unsigned int tx_next_clean;
+	unsigned int tx_current_fill;
+	/* The tx_list lock also protects the ring related variables */
+	struct sk_buff_head tx_list;
+
+	/* RX variables only touched in napi_poll.  No locking necessary. */
+	u64 *rx_ring;
+	dma_addr_t rx_ring_handle;
+	unsigned int rx_next;
+	unsigned int rx_next_fill;
+	unsigned int rx_current_fill;
+	struct sk_buff_head rx_list;
+
+	spinlock_t lock;
+	unsigned int last_duplex;
+	unsigned int last_link;
+	struct device *dev;
+	struct napi_struct napi;
+	struct tasklet_struct tx_clean_tasklet;
+	struct phy_device *phydev;
+};
+
+static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
+{
+	int port = p->port;
+	union cvmx_mixx_intena mix_intena;
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+	mix_intena.s.ithena = enable ? 1 : 0;
+	cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
+{
+	int port = p->port;
+	union cvmx_mixx_intena mix_intena;
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port));
+	mix_intena.s.othena = enable ? 1 : 0;
+	cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static inline void octeon_mgmt_enable_rx_irq(struct octeon_mgmt *p)
+{
+	octeon_mgmt_set_rx_irq(p, 1);
+}
+
+static inline void octeon_mgmt_disable_rx_irq(struct octeon_mgmt *p)
+{
+	octeon_mgmt_set_rx_irq(p, 0);
+}
+
+static inline void octeon_mgmt_enable_tx_irq(struct octeon_mgmt *p)
+{
+	octeon_mgmt_set_tx_irq(p, 1);
+}
+
+static inline void octeon_mgmt_disable_tx_irq(struct octeon_mgmt *p)
+{
+	octeon_mgmt_set_tx_irq(p, 0);
+}
+
+static unsigned int ring_max_fill(unsigned int ring_size)
+{
+	return ring_size - 8;
+}
+
+static unsigned int ring_size_to_bytes(unsigned int ring_size)
+{
+	return ring_size * sizeof(union mgmt_port_ring_entry);
+}
+
+static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+
+	while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
+		unsigned int size;
+		union mgmt_port_ring_entry re;
+		struct sk_buff *skb;
+
+		/* CN56XX pass 1 needs 8 bytes of padding.  */
+		size = netdev->mtu + OCTEON_MGMT_RX_HEADROOM + 8 + NET_IP_ALIGN;
+
+		skb = netdev_alloc_skb(netdev, size);
+		if (!skb)
+			break;
+		skb_reserve(skb, NET_IP_ALIGN);
+		__skb_queue_tail(&p->rx_list, skb);
+
+		re.d64 = 0;
+		re.s.len = size;
+		re.s.addr = dma_map_single(p->dev, skb->data,
+					   size,
+					   DMA_FROM_DEVICE);
+
+		/* Put it in the ring.  */
+		p->rx_ring[p->rx_next_fill] = re.d64;
+		dma_sync_single_for_device(p->dev, p->rx_ring_handle,
+					   ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+					   DMA_BIDIRECTIONAL);
+		p->rx_next_fill =
+			(p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
+		p->rx_current_fill++;
+		/* Ring the bell.  */
+		cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
+	}
+}
+
+static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
+{
+	int port = p->port;
+	union cvmx_mixx_orcnt mix_orcnt;
+	union mgmt_port_ring_entry re;
+	struct sk_buff *skb;
+	int cleaned = 0;
+	unsigned long flags;
+
+	mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+	while (mix_orcnt.s.orcnt) {
+		dma_sync_single_for_cpu(p->dev, p->tx_ring_handle,
+					ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+					DMA_BIDIRECTIONAL);
+
+		spin_lock_irqsave(&p->tx_list.lock, flags);
+
+		re.d64 = p->tx_ring[p->tx_next_clean];
+		p->tx_next_clean =
+			(p->tx_next_clean + 1) % OCTEON_MGMT_TX_RING_SIZE;
+		skb = __skb_dequeue(&p->tx_list);
+
+		mix_orcnt.u64 = 0;
+		mix_orcnt.s.orcnt = 1;
+
+		/* Acknowledge to hardware that we have the buffer.  */
+		cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64);
+		p->tx_current_fill--;
+
+		spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+		dma_unmap_single(p->dev, re.s.addr, re.s.len,
+				 DMA_TO_DEVICE);
+		dev_kfree_skb_any(skb);
+		cleaned++;
+
+		mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port));
+	}
+
+	if (cleaned && netif_queue_stopped(p->netdev))
+		netif_wake_queue(p->netdev);
+}
+
+static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
+{
+	struct octeon_mgmt *p = (struct octeon_mgmt *)arg;
+	octeon_mgmt_clean_tx_buffers(p);
+	octeon_mgmt_enable_tx_irq(p);
+}
+
+static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	unsigned long flags;
+	u64 drop, bad;
+
+	/* These reads also clear the count registers.  */
+	drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port));
+	bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port));
+
+	if (drop || bad) {
+		/* Do an atomic update. */
+		spin_lock_irqsave(&p->lock, flags);
+		netdev->stats.rx_errors += bad;
+		netdev->stats.rx_dropped += drop;
+		spin_unlock_irqrestore(&p->lock, flags);
+	}
+}
+
+static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	unsigned long flags;
+
+	union cvmx_agl_gmx_txx_stat0 s0;
+	union cvmx_agl_gmx_txx_stat1 s1;
+
+	/* These reads also clear the count registers.  */
+	s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port));
+	s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port));
+
+	if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
+		/* Do an atomic update. */
+		spin_lock_irqsave(&p->lock, flags);
+		netdev->stats.tx_errors += s0.s.xsdef + s0.s.xscol;
+		netdev->stats.collisions += s1.s.scol + s1.s.mcol;
+		spin_unlock_irqrestore(&p->lock, flags);
+	}
+}
+
+/*
+ * Dequeue a receive skb and its corresponding ring entry.  The ring
+ * entry is returned, *pskb is updated to point to the skb.
+ */
+static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
+					 struct sk_buff **pskb)
+{
+	union mgmt_port_ring_entry re;
+
+	dma_sync_single_for_cpu(p->dev, p->rx_ring_handle,
+				ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+				DMA_BIDIRECTIONAL);
+
+	re.d64 = p->rx_ring[p->rx_next];
+	p->rx_next = (p->rx_next + 1) % OCTEON_MGMT_RX_RING_SIZE;
+	p->rx_current_fill--;
+	*pskb = __skb_dequeue(&p->rx_list);
+
+	dma_unmap_single(p->dev, re.s.addr,
+			 ETH_FRAME_LEN + OCTEON_MGMT_RX_HEADROOM,
+			 DMA_FROM_DEVICE);
+
+	return re.d64;
+}
+
+
+static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
+{
+	int port = p->port;
+	struct net_device *netdev = p->netdev;
+	union cvmx_mixx_ircnt mix_ircnt;
+	union mgmt_port_ring_entry re;
+	struct sk_buff *skb;
+	struct sk_buff *skb2;
+	struct sk_buff *skb_new;
+	union mgmt_port_ring_entry re2;
+	int rc = 1;
+
+
+	re.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb);
+	if (likely(re.s.code == RING_ENTRY_CODE_DONE)) {
+		/* A good packet, send it up. */
+		skb_put(skb, re.s.len);
+good:
+		skb->protocol = eth_type_trans(skb, netdev);
+		netdev->stats.rx_packets++;
+		netdev->stats.rx_bytes += skb->len;
+		netdev->last_rx = jiffies;
+		netif_receive_skb(skb);
+		rc = 0;
+	} else if (re.s.code == RING_ENTRY_CODE_MORE) {
+		/*
+		 * Packet split across skbs.  This can happen if we
+		 * increase the MTU.  Buffers that are already in the
+		 * rx ring can then end up being too small.  As the rx
+		 * ring is refilled, buffers sized for the new MTU
+		 * will be used and we should go back to the normal
+		 * non-split case.
+		 */
+		skb_put(skb, re.s.len);
+		do {
+			re2.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb2);
+			if (re2.s.code != RING_ENTRY_CODE_MORE
+				&& re2.s.code != RING_ENTRY_CODE_DONE)
+				goto split_error;
+			skb_put(skb2,  re2.s.len);
+			skb_new = skb_copy_expand(skb, 0, skb2->len,
+						  GFP_ATOMIC);
+			if (!skb_new)
+				goto split_error;
+			if (skb_copy_bits(skb2, 0, skb_tail_pointer(skb_new),
+					  skb2->len))
+				goto split_error;
+			skb_put(skb_new, skb2->len);
+			dev_kfree_skb_any(skb);
+			dev_kfree_skb_any(skb2);
+			skb = skb_new;
+		} while (re2.s.code == RING_ENTRY_CODE_MORE);
+		goto good;
+	} else {
+		/* Some other error, discard it. */
+		dev_kfree_skb_any(skb);
+		/*
+		 * Error statistics are accumulated in
+		 * octeon_mgmt_update_rx_stats.
+		 */
+	}
+	goto done;
+split_error:
+	/* Discard the whole mess. */
+	dev_kfree_skb_any(skb);
+	dev_kfree_skb_any(skb2);
+	while (re2.s.code == RING_ENTRY_CODE_MORE) {
+		re2.d64 = octeon_mgmt_dequeue_rx_buffer(p, &skb2);
+		dev_kfree_skb_any(skb2);
+	}
+	netdev->stats.rx_errors++;
+
+done:
+	/* Tell the hardware we processed a packet.  */
+	mix_ircnt.u64 = 0;
+	mix_ircnt.s.ircnt = 1;
+	cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64);
+	return rc;
+
+}
+
+static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
+{
+	int port = p->port;
+	unsigned int work_done = 0;
+	union cvmx_mixx_ircnt mix_ircnt;
+	int rc;
+
+
+	mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+	while (work_done < budget && mix_ircnt.s.ircnt) {
+
+		rc = octeon_mgmt_receive_one(p);
+		if (!rc)
+			work_done++;
+
+		/* Check for more packets. */
+		mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
+	}
+
+	octeon_mgmt_rx_fill_ring(p->netdev);
+
+	return work_done;
+}
+
+static int octeon_mgmt_napi_poll(struct napi_struct *napi, int budget)
+{
+	struct octeon_mgmt *p = container_of(napi, struct octeon_mgmt, napi);
+	struct net_device *netdev = p->netdev;
+	unsigned int work_done = 0;
+
+	work_done = octeon_mgmt_receive_packets(p, budget);
+
+	if (work_done < budget) {
+		/* We stopped because no more packets were available. */
+		napi_complete(napi);
+		octeon_mgmt_enable_rx_irq(p);
+	}
+	octeon_mgmt_update_rx_stats(netdev);
+
+	return work_done;
+}
+
+/* Reset the hardware to clean state.  */
+static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
+{
+	union cvmx_mixx_ctl mix_ctl;
+	union cvmx_mixx_bist mix_bist;
+	union cvmx_agl_gmx_bist agl_gmx_bist;
+
+	mix_ctl.u64 = 0;
+	cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+	do {
+		mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+	} while (mix_ctl.s.busy);
+	mix_ctl.s.reset = 1;
+	cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64);
+	cvmx_read_csr(CVMX_MIXX_CTL(p->port));
+	cvmx_wait(64);
+
+	mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port));
+	if (mix_bist.u64)
+		dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
+			(unsigned long long)mix_bist.u64);
+
+	agl_gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST);
+	if (agl_gmx_bist.u64)
+		dev_warn(p->dev, "AGL failed BIST (0x%016llx)\n",
+			 (unsigned long long)agl_gmx_bist.u64);
+}
+
+struct octeon_mgmt_cam_state {
+	u64 cam[6];
+	u64 cam_mask;
+	int cam_index;
+};
+
+static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
+				      unsigned char *addr)
+{
+	int i;
+
+	for (i = 0; i < 6; i++)
+		cs->cam[i] |= (u64)addr[i] << (8 * (cs->cam_index));
+	cs->cam_mask |= (1ULL << cs->cam_index);
+	cs->cam_index++;
+}
+
+static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	int i;
+	union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
+	union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
+	unsigned long flags;
+	unsigned int prev_packet_enable;
+	unsigned int cam_mode = 1; /* 1 - Accept on CAM match */
+	unsigned int multicast_mode = 1; /* 1 - Reject all multicast.  */
+	struct octeon_mgmt_cam_state cam_state;
+	struct dev_addr_list *list;
+	struct list_head *pos;
+	int available_cam_entries;
+
+	memset(&cam_state, 0, sizeof(cam_state));
+
+	if ((netdev->flags & IFF_PROMISC) || netdev->dev_addrs.count > 7) {
+		cam_mode = 0;
+		available_cam_entries = 8;
+	} else {
+		/*
+		 * One CAM entry for the primary address, leaves seven
+		 * for the secondary addresses.
+		 */
+		available_cam_entries = 7 - netdev->dev_addrs.count;
+	}
+
+	if (netdev->flags & IFF_MULTICAST) {
+		if (cam_mode == 0 || (netdev->flags & IFF_ALLMULTI)
+		    || netdev->mc_count  > available_cam_entries)
+			multicast_mode = 2; /* 1 - Accept all multicast.  */
+		else
+			multicast_mode = 0; /* 0 - Use CAM.  */
+	}
+
+	if (cam_mode == 1) {
+		/* Add primary address. */
+		octeon_mgmt_cam_state_add(&cam_state, netdev->dev_addr);
+		list_for_each(pos, &netdev->dev_addrs.list) {
+			struct netdev_hw_addr *hw_addr;
+			hw_addr = list_entry(pos, struct netdev_hw_addr, list);
+			octeon_mgmt_cam_state_add(&cam_state, hw_addr->addr);
+			list = list->next;
+		}
+	}
+	if (multicast_mode == 0) {
+		i = netdev->mc_count;
+		list = netdev->mc_list;
+		while (i--) {
+			octeon_mgmt_cam_state_add(&cam_state, list->da_addr);
+			list = list->next;
+		}
+	}
+
+
+	spin_lock_irqsave(&p->lock, flags);
+
+	/* Disable packet I/O. */
+	agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+	prev_packet_enable = agl_gmx_prtx.s.en;
+	agl_gmx_prtx.s.en = 0;
+	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+
+
+	adr_ctl.u64 = 0;
+	adr_ctl.s.cam_mode = cam_mode;
+	adr_ctl.s.mcst = multicast_mode;
+	adr_ctl.s.bcst = 1;     /* Allow broadcast */
+
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64);
+
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask);
+
+	/* Restore packet I/O. */
+	agl_gmx_prtx.s.en = prev_packet_enable;
+	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
+
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
+{
+	struct sockaddr *sa = addr;
+
+	if (!is_valid_ether_addr(sa->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(netdev->dev_addr, sa->sa_data, ETH_ALEN);
+
+	octeon_mgmt_set_rx_filtering(netdev);
+
+	return 0;
+}
+
+static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
+
+	/*
+	 * Limit the MTU to make sure the ethernet packets are between
+	 * 64 bytes and 16383 bytes.
+	 */
+	if (size_without_fcs < 64 || size_without_fcs > 16383) {
+		dev_warn(p->dev, "MTU must be between %d and %d.\n",
+			 64 - OCTEON_MGMT_RX_HEADROOM,
+			 16383 - OCTEON_MGMT_RX_HEADROOM);
+		return -EINVAL;
+	}
+
+	netdev->mtu = new_mtu;
+
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
+		       (size_without_fcs + 7) & 0xfff8);
+
+	return 0;
+}
+
+static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
+{
+	struct net_device *netdev = dev_id;
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	union cvmx_mixx_isr mixx_isr;
+
+	mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port));
+
+	/* Clear any pending interrupts */
+	cvmx_write_csr(CVMX_MIXX_ISR(port),
+		       cvmx_read_csr(CVMX_MIXX_ISR(port)));
+	cvmx_read_csr(CVMX_MIXX_ISR(port));
+
+	if (mixx_isr.s.irthresh) {
+		octeon_mgmt_disable_rx_irq(p);
+		napi_schedule(&p->napi);
+	}
+	if (mixx_isr.s.orthresh) {
+		octeon_mgmt_disable_tx_irq(p);
+		tasklet_schedule(&p->tx_clean_tasklet);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int octeon_mgmt_ioctl(struct net_device *netdev,
+			     struct ifreq *rq, int cmd)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	if (!netif_running(netdev))
+		return -EINVAL;
+
+	if (!p->phydev)
+		return -EINVAL;
+
+	return phy_mii_ioctl(p->phydev, if_mii(rq), cmd);
+}
+
+static void octeon_mgmt_adjust_link(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+	unsigned long flags;
+	int link_changed = 0;
+
+	spin_lock_irqsave(&p->lock, flags);
+	if (p->phydev->link) {
+		if (!p->last_link)
+			link_changed = 1;
+		if (p->last_duplex != p->phydev->duplex) {
+			p->last_duplex = p->phydev->duplex;
+			prtx_cfg.u64 =
+				cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+			prtx_cfg.s.duplex = p->phydev->duplex;
+			cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
+				       prtx_cfg.u64);
+		}
+	} else {
+		if (p->last_link)
+			link_changed = -1;
+	}
+	p->last_link = p->phydev->link;
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	if (link_changed != 0) {
+		if (link_changed > 0) {
+			netif_carrier_on(netdev);
+			pr_info("%s: Link is up - %d/%s\n", netdev->name,
+				p->phydev->speed,
+				DUPLEX_FULL == p->phydev->duplex ?
+				"Full" : "Half");
+		} else {
+			netif_carrier_off(netdev);
+			pr_info("%s: Link is down\n", netdev->name);
+		}
+	}
+}
+
+static int octeon_mgmt_init_phy(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	char phy_id[20];
+
+	if (octeon_is_simulation()) {
+		/* No PHYs in the simulator. */
+		netif_carrier_on(netdev);
+		return 0;
+	}
+
+	snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", p->port);
+
+	p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0,
+				PHY_INTERFACE_MODE_MII);
+
+	if (IS_ERR(p->phydev)) {
+		p->phydev = NULL;
+		return -1;
+	}
+
+	phy_start_aneg(p->phydev);
+
+	return 0;
+}
+
+static int octeon_mgmt_open(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	union cvmx_mixx_ctl mix_ctl;
+	union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode;
+	union cvmx_mixx_oring1 oring1;
+	union cvmx_mixx_iring1 iring1;
+	union cvmx_agl_gmx_prtx_cfg prtx_cfg;
+	union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl;
+	union cvmx_mixx_irhwm mix_irhwm;
+	union cvmx_mixx_orhwm mix_orhwm;
+	union cvmx_mixx_intena mix_intena;
+	struct sockaddr sa;
+
+	/* Allocate ring buffers.  */
+	p->tx_ring = kzalloc(ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+			     GFP_KERNEL);
+	if (!p->tx_ring)
+		return -ENOMEM;
+	p->tx_ring_handle =
+		dma_map_single(p->dev, p->tx_ring,
+			       ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+			       DMA_BIDIRECTIONAL);
+	p->tx_next = 0;
+	p->tx_next_clean = 0;
+	p->tx_current_fill = 0;
+
+
+	p->rx_ring = kzalloc(ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+			     GFP_KERNEL);
+	if (!p->rx_ring)
+		goto err_nomem;
+	p->rx_ring_handle =
+		dma_map_single(p->dev, p->rx_ring,
+			       ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+			       DMA_BIDIRECTIONAL);
+
+	p->rx_next = 0;
+	p->rx_next_fill = 0;
+	p->rx_current_fill = 0;
+
+	octeon_mgmt_reset_hw(p);
+
+	mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+
+	/* Bring it out of reset if needed. */
+	if (mix_ctl.s.reset) {
+		mix_ctl.s.reset = 0;
+		cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+		do {
+			mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
+		} while (mix_ctl.s.reset);
+	}
+
+	agl_gmx_inf_mode.u64 = 0;
+	agl_gmx_inf_mode.s.en = 1;
+	cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+
+	oring1.u64 = 0;
+	oring1.s.obase = p->tx_ring_handle >> 3;
+	oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
+	cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
+
+	iring1.u64 = 0;
+	iring1.s.ibase = p->rx_ring_handle >> 3;
+	iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
+	cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
+
+	/* Disable packet I/O. */
+	prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+	prtx_cfg.s.en = 0;
+	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+
+	memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
+	octeon_mgmt_set_mac_address(netdev, &sa);
+
+	octeon_mgmt_change_mtu(netdev, netdev->mtu);
+
+	/*
+	 * Enable the port HW. Packets are not allowed until
+	 * cvmx_mgmt_port_enable() is called.
+	 */
+	mix_ctl.u64 = 0;
+	mix_ctl.s.crc_strip = 1;    /* Strip the ending CRC */
+	mix_ctl.s.en = 1;           /* Enable the port */
+	mix_ctl.s.nbtarb = 0;       /* Arbitration mode */
+	/* MII CB-request FIFO programmable high watermark */
+	mix_ctl.s.mrq_hwm = 1;
+	cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
+
+	if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
+	    || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
+		/*
+		 * Force compensation values, as they are not
+		 * determined properly by HW
+		 */
+		union cvmx_agl_gmx_drv_ctl drv_ctl;
+
+		drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL);
+		if (port) {
+			drv_ctl.s.byp_en1 = 1;
+			drv_ctl.s.nctl1 = 6;
+			drv_ctl.s.pctl1 = 6;
+		} else {
+			drv_ctl.s.byp_en = 1;
+			drv_ctl.s.nctl = 6;
+			drv_ctl.s.pctl = 6;
+		}
+		cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64);
+	}
+
+	octeon_mgmt_rx_fill_ring(netdev);
+
+	/* Clear statistics. */
+	/* Clear on read. */
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0);
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0);
+
+	cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1);
+	cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0);
+	cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0);
+
+	/* Clear any pending interrupts */
+	cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port)));
+
+	if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
+			netdev)) {
+		dev_err(p->dev, "request_irq(%d) failed.\n", p->irq);
+		goto err_noirq;
+	}
+
+	/* Interrupt every single RX packet */
+	mix_irhwm.u64 = 0;
+	mix_irhwm.s.irhwm = 0;
+	cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64);
+
+	/* Interrupt when we have 5 or more packets to clean.  */
+	mix_orhwm.u64 = 0;
+	mix_orhwm.s.orhwm = 5;
+	cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64);
+
+	/* Enable receive and transmit interrupts */
+	mix_intena.u64 = 0;
+	mix_intena.s.ithena = 1;
+	mix_intena.s.othena = 1;
+	cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64);
+
+
+	/* Enable packet I/O. */
+
+	rxx_frm_ctl.u64 = 0;
+	rxx_frm_ctl.s.pre_align = 1;
+	/*
+	 * When set, disables the length check for non-min sized pkts
+	 * with padding in the client data.
+	 */
+	rxx_frm_ctl.s.pad_len = 1;
+	/* When set, disables the length check for VLAN pkts */
+	rxx_frm_ctl.s.vlan_len = 1;
+	/* When set, PREAMBLE checking is  less strict */
+	rxx_frm_ctl.s.pre_free = 1;
+	/* Control Pause Frames can match station SMAC */
+	rxx_frm_ctl.s.ctl_smac = 0;
+	/* Control Pause Frames can match globally assign Multicast address */
+	rxx_frm_ctl.s.ctl_mcst = 1;
+	/* Forward pause information to TX block */
+	rxx_frm_ctl.s.ctl_bck = 1;
+	/* Drop Control Pause Frames */
+	rxx_frm_ctl.s.ctl_drp = 1;
+	/* Strip off the preamble */
+	rxx_frm_ctl.s.pre_strp = 1;
+	/*
+	 * This port is configured to send PREAMBLE+SFD to begin every
+	 * frame.  GMX checks that the PREAMBLE is sent correctly.
+	 */
+	rxx_frm_ctl.s.pre_chk = 1;
+	cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
+
+	/* Enable the AGL block */
+	agl_gmx_inf_mode.u64 = 0;
+	agl_gmx_inf_mode.s.en = 1;
+	cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
+
+	/* Configure the port duplex and enables */
+	prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
+	prtx_cfg.s.tx_en = 1;
+	prtx_cfg.s.rx_en = 1;
+	prtx_cfg.s.en = 1;
+	p->last_duplex = 1;
+	prtx_cfg.s.duplex = p->last_duplex;
+	cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64);
+
+	p->last_link = 0;
+	netif_carrier_off(netdev);
+
+	if (octeon_mgmt_init_phy(netdev)) {
+		dev_err(p->dev, "Cannot initialize PHY.\n");
+		goto err_noirq;
+	}
+
+	netif_wake_queue(netdev);
+	napi_enable(&p->napi);
+
+	return 0;
+err_noirq:
+	octeon_mgmt_reset_hw(p);
+	dma_unmap_single(p->dev, p->rx_ring_handle,
+			 ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+			 DMA_BIDIRECTIONAL);
+	kfree(p->rx_ring);
+err_nomem:
+	dma_unmap_single(p->dev, p->tx_ring_handle,
+			 ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+			 DMA_BIDIRECTIONAL);
+	kfree(p->tx_ring);
+	return -ENOMEM;
+}
+
+static int octeon_mgmt_stop(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	napi_disable(&p->napi);
+	netif_stop_queue(netdev);
+
+	if (p->phydev)
+		phy_disconnect(p->phydev);
+
+	netif_carrier_off(netdev);
+
+	octeon_mgmt_reset_hw(p);
+
+
+	free_irq(p->irq, netdev);
+
+	/* dma_unmap is a nop on Octeon, so just free everything.  */
+	skb_queue_purge(&p->tx_list);
+	skb_queue_purge(&p->rx_list);
+
+	dma_unmap_single(p->dev, p->rx_ring_handle,
+			 ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
+			 DMA_BIDIRECTIONAL);
+	kfree(p->rx_ring);
+
+	dma_unmap_single(p->dev, p->tx_ring_handle,
+			 ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+			 DMA_BIDIRECTIONAL);
+	kfree(p->tx_ring);
+
+
+	return 0;
+}
+
+static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+	int port = p->port;
+	union mgmt_port_ring_entry re;
+	unsigned long flags;
+
+	re.d64 = 0;
+	re.s.len = skb->len;
+	re.s.addr = dma_map_single(p->dev, skb->data,
+				   skb->len,
+				   DMA_TO_DEVICE);
+
+	spin_lock_irqsave(&p->tx_list.lock, flags);
+
+	if (unlikely(p->tx_current_fill >=
+		     ring_max_fill(OCTEON_MGMT_TX_RING_SIZE))) {
+		spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+		dma_unmap_single(p->dev, re.s.addr, re.s.len,
+				 DMA_TO_DEVICE);
+
+		netif_stop_queue(netdev);
+		return NETDEV_TX_BUSY;
+	}
+
+	__skb_queue_tail(&p->tx_list, skb);
+
+	/* Put it in the ring.  */
+	p->tx_ring[p->tx_next] = re.d64;
+	p->tx_next = (p->tx_next + 1) % OCTEON_MGMT_TX_RING_SIZE;
+	p->tx_current_fill++;
+
+	spin_unlock_irqrestore(&p->tx_list.lock, flags);
+
+	dma_sync_single_for_device(p->dev, p->tx_ring_handle,
+				   ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE),
+				   DMA_BIDIRECTIONAL);
+
+	netdev->stats.tx_packets++;
+	netdev->stats.tx_bytes += skb->len;
+
+	/* Ring the bell.  */
+	cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+
+	netdev->trans_start = jiffies;
+	octeon_mgmt_clean_tx_buffers(p);
+	octeon_mgmt_update_tx_stats(netdev);
+	return NETDEV_TX_OK;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void octeon_mgmt_poll_controller(struct net_device *netdev)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	octeon_mgmt_receive_packets(p, 16);
+	octeon_mgmt_update_rx_stats(netdev);
+	return;
+}
+#endif
+
+static void octeon_mgmt_get_drvinfo(struct net_device *netdev,
+				    struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, DRV_NAME, sizeof(info->driver));
+	strncpy(info->version, DRV_VERSION, sizeof(info->version));
+	strncpy(info->fw_version, "N/A", sizeof(info->fw_version));
+	strncpy(info->bus_info, "N/A", sizeof(info->bus_info));
+	info->n_stats = 0;
+	info->testinfo_len = 0;
+	info->regdump_len = 0;
+	info->eedump_len = 0;
+}
+
+static int octeon_mgmt_get_settings(struct net_device *netdev,
+				    struct ethtool_cmd *cmd)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	if (p->phydev)
+		return phy_ethtool_gset(p->phydev, cmd);
+
+	return -EINVAL;
+}
+
+static int octeon_mgmt_set_settings(struct net_device *netdev,
+				    struct ethtool_cmd *cmd)
+{
+	struct octeon_mgmt *p = netdev_priv(netdev);
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (p->phydev)
+		return phy_ethtool_sset(p->phydev, cmd);
+
+	return -EINVAL;
+}
+
+static const struct ethtool_ops octeon_mgmt_ethtool_ops = {
+	.get_drvinfo = octeon_mgmt_get_drvinfo,
+	.get_link = ethtool_op_get_link,
+	.get_settings = octeon_mgmt_get_settings,
+	.set_settings = octeon_mgmt_set_settings
+};
+
+static const struct net_device_ops octeon_mgmt_ops = {
+	.ndo_open =			octeon_mgmt_open,
+	.ndo_stop =			octeon_mgmt_stop,
+	.ndo_start_xmit =		octeon_mgmt_xmit,
+	.ndo_set_rx_mode = 		octeon_mgmt_set_rx_filtering,
+	.ndo_set_multicast_list =	octeon_mgmt_set_rx_filtering,
+	.ndo_set_mac_address =		octeon_mgmt_set_mac_address,
+	.ndo_do_ioctl = 		octeon_mgmt_ioctl,
+	.ndo_change_mtu =		octeon_mgmt_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_poll_controller =		octeon_mgmt_poll_controller,
+#endif
+};
+
+static int __init octeon_mgmt_probe(struct platform_device *pdev)
+{
+	struct resource *res_irq;
+	struct net_device *netdev;
+	struct octeon_mgmt *p;
+	int i;
+
+	netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
+	if (netdev == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&pdev->dev, netdev);
+	p = netdev_priv(netdev);
+	netif_napi_add(netdev, &p->napi, octeon_mgmt_napi_poll,
+		       OCTEON_MGMT_NAPI_WEIGHT);
+
+	p->netdev = netdev;
+	p->dev = &pdev->dev;
+
+	p->port = pdev->id;
+	snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
+
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res_irq)
+		goto err;
+
+	p->irq = res_irq->start;
+	spin_lock_init(&p->lock);
+
+	skb_queue_head_init(&p->tx_list);
+	skb_queue_head_init(&p->rx_list);
+	tasklet_init(&p->tx_clean_tasklet,
+		     octeon_mgmt_clean_tx_tasklet, (unsigned long)p);
+
+	netdev->netdev_ops = &octeon_mgmt_ops;
+	netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
+
+
+	/* The mgmt ports get the first N MACs.  */
+	for (i = 0; i < 6; i++)
+		netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i];
+	netdev->dev_addr[5] += p->port;
+
+	if (p->port >= octeon_bootinfo->mac_addr_count)
+		dev_err(&pdev->dev,
+			"Error %s: Using MAC outside of the assigned range: "
+			"%02x:%02x:%02x:%02x:%02x:%02x\n", netdev->name,
+			netdev->dev_addr[0], netdev->dev_addr[1],
+			netdev->dev_addr[2], netdev->dev_addr[3],
+			netdev->dev_addr[4], netdev->dev_addr[5]);
+
+	if (register_netdev(netdev))
+		goto err;
+
+	dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+	return 0;
+err:
+	free_netdev(netdev);
+	return -ENOENT;
+}
+
+static int __exit octeon_mgmt_remove(struct platform_device *pdev)
+{
+	struct net_device *netdev = dev_get_drvdata(&pdev->dev);
+
+	unregister_netdev(netdev);
+	free_netdev(netdev);
+	return 0;
+}
+
+static struct platform_driver octeon_mgmt_driver = {
+	.driver = {
+		.name		= "octeon_mgmt",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= octeon_mgmt_probe,
+	.remove		= __exit_p(octeon_mgmt_remove),
+};
+
+extern void octeon_mdiobus_force_mod_depencency(void);
+
+static int __init octeon_mgmt_mod_init(void)
+{
+	/* Force our mdiobus driver module to be loaded first. */
+	octeon_mdiobus_force_mod_depencency();
+	return platform_driver_register(&octeon_mgmt_driver);
+}
+
+static void __exit octeon_mgmt_mod_exit(void)
+{
+	platform_driver_unregister(&octeon_mgmt_driver);
+}
+
+module_init(octeon_mgmt_mod_init);
+module_exit(octeon_mgmt_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 17a2722..98938ea 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -912,7 +912,11 @@
 	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) {
 		if (!lp->fast_poll)
 			printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
+
+		local_irq_save(flags);
 		el3_interrupt(dev->irq, dev);
+		local_irq_restore(flags);
+
 		lp->fast_poll = HZ;
 	}
 	if (lp->fast_poll) {
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 6f8d7e2..322e11d 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -711,7 +711,11 @@
 	(inb(ioaddr + EL3_TIMER) == 0xff)) {
 	if (!lp->fast_poll)
 	    printk(KERN_WARNING "%s: interrupt(s) dropped!\n", dev->name);
+
+	local_irq_save(flags);
 	el3_interrupt(dev->irq, dev);
+	local_irq_restore(flags);
+
 	lp->fast_poll = HZ;
     }
     if (lp->fast_poll) {
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d5d8e1c..fc5938ba 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -115,4 +115,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called mdio-gpio.
 
+config MDIO_OCTEON
+	tristate "Support for MDIO buses on Octeon SOCs"
+	depends on  CPU_CAVIUM_OCTEON
+	default y
+	help
+
+	  This module provides a driver for the Octeon MDIO busses.
+	  It is required by the Octeon Ethernet device drivers.
+
+	  If in doubt, say Y.
+
 endif # PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index edfaac4..1342585 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o
 obj-$(CONFIG_NATIONAL_PHY)	+= national.o
 obj-$(CONFIG_STE10XP)		+= ste10Xp.o
+obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
new file mode 100644
index 0000000..61a4461
--- /dev/null
+++ b/drivers/net/phy/mdio-octeon.c
@@ -0,0 +1,180 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Cavium Networks
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-smix-defs.h>
+
+#define DRV_VERSION "1.0"
+#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
+
+struct octeon_mdiobus {
+	struct mii_bus *mii_bus;
+	int unit;
+	int phy_irq[PHY_MAX_ADDR];
+};
+
+static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
+{
+	struct octeon_mdiobus *p = bus->priv;
+	union cvmx_smix_cmd smi_cmd;
+	union cvmx_smix_rd_dat smi_rd;
+	int timeout = 1000;
+
+	smi_cmd.u64 = 0;
+	smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
+	smi_cmd.s.phy_adr = phy_id;
+	smi_cmd.s.reg_adr = regnum;
+	cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+
+	do {
+		/*
+		 * Wait 1000 clocks so we don't saturate the RSL bus
+		 * doing reads.
+		 */
+		cvmx_wait(1000);
+		smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit));
+	} while (smi_rd.s.pending && --timeout);
+
+	if (smi_rd.s.val)
+		return smi_rd.s.dat;
+	else
+		return -EIO;
+}
+
+static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
+				int regnum, u16 val)
+{
+	struct octeon_mdiobus *p = bus->priv;
+	union cvmx_smix_cmd smi_cmd;
+	union cvmx_smix_wr_dat smi_wr;
+	int timeout = 1000;
+
+	smi_wr.u64 = 0;
+	smi_wr.s.dat = val;
+	cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64);
+
+	smi_cmd.u64 = 0;
+	smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
+	smi_cmd.s.phy_adr = phy_id;
+	smi_cmd.s.reg_adr = regnum;
+	cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64);
+
+	do {
+		/*
+		 * Wait 1000 clocks so we don't saturate the RSL bus
+		 * doing reads.
+		 */
+		cvmx_wait(1000);
+		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit));
+	} while (smi_wr.s.pending && --timeout);
+
+	if (timeout <= 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int __init octeon_mdiobus_probe(struct platform_device *pdev)
+{
+	struct octeon_mdiobus *bus;
+	int i;
+	int err = -ENOENT;
+
+	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+	if (!bus)
+		return -ENOMEM;
+
+	/* The platform_device id is our unit number.  */
+	bus->unit = pdev->id;
+
+	bus->mii_bus = mdiobus_alloc();
+
+	if (!bus->mii_bus)
+		goto err;
+
+	/*
+	 * Standard Octeon evaluation boards don't support phy
+	 * interrupts, we need to poll.
+	 */
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		bus->phy_irq[i] = PHY_POLL;
+
+	bus->mii_bus->priv = bus;
+	bus->mii_bus->irq = bus->phy_irq;
+	bus->mii_bus->name = "mdio-octeon";
+	snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
+	bus->mii_bus->parent = &pdev->dev;
+
+	bus->mii_bus->read = octeon_mdiobus_read;
+	bus->mii_bus->write = octeon_mdiobus_write;
+
+	dev_set_drvdata(&pdev->dev, bus);
+
+	err = mdiobus_register(bus->mii_bus);
+	if (err)
+		goto err_register;
+
+	dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
+
+	return 0;
+err_register:
+	mdiobus_free(bus->mii_bus);
+
+err:
+	devm_kfree(&pdev->dev, bus);
+	return err;
+}
+
+static int __exit octeon_mdiobus_remove(struct platform_device *pdev)
+{
+	struct octeon_mdiobus *bus;
+
+	bus = dev_get_drvdata(&pdev->dev);
+
+	mdiobus_unregister(bus->mii_bus);
+	mdiobus_free(bus->mii_bus);
+	return 0;
+}
+
+static struct platform_driver octeon_mdiobus_driver = {
+	.driver = {
+		.name		= "mdio-octeon",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= octeon_mdiobus_probe,
+	.remove		= __exit_p(octeon_mdiobus_remove),
+};
+
+void octeon_mdiobus_force_mod_depencency(void)
+{
+	/* Let ethernet drivers force us to be loaded.  */
+}
+EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
+
+static int __init octeon_mdiobus_mod_init(void)
+{
+	return platform_driver_register(&octeon_mdiobus_driver);
+}
+
+static void __exit octeon_mdiobus_mod_exit(void)
+{
+	platform_driver_unregister(&octeon_mdiobus_driver);
+}
+
+module_init(octeon_mdiobus_mod_init);
+module_exit(octeon_mdiobus_mod_exit);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("David Daney");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 14949bb..af39335 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -47,7 +47,7 @@
 	0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b,
 };
 
-static const char *payload_msg =
+static const char payload_msg[] =
 	"Hello world! This is an Efx loopback test in progress!";
 
 /**
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index c88bc10..ca62850 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -84,6 +84,8 @@
 	.mpr		= 1,
 	.tpauser	= 1,
 	.hw_swap	= 1,
+	.rpadir		= 1,
+	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
 };
 
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
@@ -175,7 +177,6 @@
 	.tpauser	= 1,
 	.bculr		= 1,
 	.hw_swap	= 1,
-	.rpadir		= 1,
 	.no_trimd	= 1,
 	.no_ade		= 1,
 };
@@ -501,6 +502,8 @@
 	 */
 	mdp->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ :
 			  (((ndev->mtu + 26 + 7) & ~7) + 2 + 16));
+	if (mdp->cd->rpadir)
+		mdp->rx_buf_sz += NET_IP_ALIGN;
 
 	/* Allocate RX and TX skb rings */
 	mdp->rx_skbuff = kmalloc(sizeof(*mdp->rx_skbuff) * RX_RING_SIZE,
@@ -715,6 +718,8 @@
 					pkt_len + 2);
 			skb = mdp->rx_skbuff[entry];
 			mdp->rx_skbuff[entry] = NULL;
+			if (mdp->cd->rpadir)
+				skb_reserve(skb, NET_IP_ALIGN);
 			skb_put(skb, pkt_len);
 			skb->protocol = eth_type_trans(skb, ndev);
 			netif_rx(skb);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 89a05d6..1c01b96 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -644,7 +644,6 @@
 {
 	u32 reg1;
 
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
 	reg1 &= ~phy_power[port];
 
@@ -652,7 +651,6 @@
 		reg1 |= coma_mode[port];
 
 	sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 	sky2_pci_read32(hw, PCI_DEV_REG1);
 
 	if (hw->chip_id == CHIP_ID_YUKON_FE)
@@ -709,11 +707,9 @@
 		gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN);
 	}
 
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
 	reg1 |= phy_power[port];		/* set PHY to PowerDown/COMA Mode */
 	sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
 /* Force a renegotiation */
@@ -2152,9 +2148,7 @@
 
 	/* reset PHY Link Detect */
 	phy = sky2_pci_read16(hw, PSM_CONFIG_REG4);
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 	sky2_pci_write16(hw, PSM_CONFIG_REG4, phy | 1);
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
 	sky2_link_up(sky2);
 }
@@ -2645,7 +2639,6 @@
 	if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
 		u16 pci_err;
 
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 		pci_err = sky2_pci_read16(hw, PCI_STATUS);
 		if (net_ratelimit())
 			dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
@@ -2653,14 +2646,12 @@
 
 		sky2_pci_write16(hw, PCI_STATUS,
 				      pci_err | PCI_STATUS_ERROR_BITS);
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 	}
 
 	if (status & Y2_IS_PCI_EXP) {
 		/* PCI-Express uncorrectable Error occurred */
 		u32 err;
 
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 		err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
 		sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
 			     0xfffffffful);
@@ -2668,7 +2659,6 @@
 			dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
 
 		sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 	}
 
 	if (status & Y2_HWE_L1_MASK)
@@ -3047,7 +3037,6 @@
 	}
 
 	sky2_power_on(hw);
-	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
 	for (i = 0; i < hw->ports; i++) {
 		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
@@ -3084,7 +3073,6 @@
 		reg <<= PSM_CONFIG_REG4_TIMER_PHY_LINK_DETECT_BASE;
 
 		/* reset PHY Link Detect */
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 		sky2_pci_write16(hw, PSM_CONFIG_REG4,
 				 reg | PSM_CONFIG_REG4_RST_PHY_LINK_DETECT);
 		sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
@@ -3102,7 +3090,6 @@
 			/* restore the PCIe Link Control register */
 			sky2_pci_write16(hw, cap + PCI_EXP_LNKCTL, reg);
 		}
-		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 
 		/* re-enable PEX PM in PEX PHY debug reg. 8 (clear bit 12) */
 		sky2_write32(hw, Y2_PEX_PHY_DATA, PEX_DB_ACCESS | (0x08UL << 16));
@@ -4530,7 +4517,7 @@
 		"Optima",	/* 0xbc */
 	};
 
-	if (chipid >= CHIP_ID_YUKON_XL && chipid < CHIP_ID_YUKON_OPT)
+	if (chipid >= CHIP_ID_YUKON_XL && chipid <= CHIP_ID_YUKON_OPT)
 		strncpy(buf, name[chipid - CHIP_ID_YUKON_XL], sz);
 	else
 		snprintf(buf, sz, "(chip %#x)", chipid);
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index b091e20..f14d225 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -324,7 +324,7 @@
 		dbg("%02X:", netdev->dev_addr[i]);
 	dbg("%02X\n", netdev->dev_addr[i]);
 	/* Set the IDR registers. */
-	set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr);
+	set_registers(dev, IDR, netdev->addr_len, netdev->dev_addr);
 #ifdef EEPROM_WRITE
 	{
 	u8 cr;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 675b7df..27ca859 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -63,7 +63,7 @@
 #ifndef __iwl_core_h__
 #define __iwl_core_h__
 
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 /************************
  * forward declarations *
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index d69bde6..c542c7bb 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -354,7 +354,7 @@
 }
 
 static struct irq_chip dino_interrupt_type = {
-	.typename	= "GSC-PCI",
+	.name		= "GSC-PCI",
 	.startup	= dino_startup_irq,
 	.shutdown	= dino_disable_irq,
 	.enable		= dino_enable_irq, 
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 5122074..46f503f 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -189,7 +189,7 @@
 }
 
 static struct irq_chip eisa_interrupt_type = {
-	.typename =	"EISA",
+	.name	 =	"EISA",
 	.startup =	eisa_startup_irq,
 	.shutdown =	eisa_disable_irq,
 	.enable =	eisa_enable_irq,
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index 647adc9..c4e1f3c 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -149,7 +149,7 @@
 }
 
 static struct irq_chip gsc_asic_interrupt_type = {
-	.typename =	"GSC-ASIC",
+	.name	 =	"GSC-ASIC",
 	.startup =	gsc_asic_startup_irq,
 	.shutdown =	gsc_asic_disable_irq,
 	.enable =	gsc_asic_enable_irq,
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 88e3335..c768367 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -730,7 +730,7 @@
 #endif
 
 static struct irq_chip iosapic_interrupt_type = {
-	.typename =	"IO-SAPIC-level",
+	.name	 =	"IO-SAPIC-level",
 	.startup =	iosapic_startup_irq,
 	.shutdown =	iosapic_disable_irq,
 	.enable =	iosapic_enable_irq,
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 79caf1c..188bc84 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -38,6 +38,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/reboot.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/ctype.h>
 #include <linux/blkdev.h>
 #include <linux/workqueue.h>
@@ -147,41 +148,34 @@
 static void (*led_func_ptr) (unsigned char) __read_mostly;
 
 #ifdef CONFIG_PROC_FS
-static int led_proc_read(char *page, char **start, off_t off, int count, 
-	int *eof, void *data)
+static int led_proc_show(struct seq_file *m, void *v)
 {
-	char *out = page;
-	int len;
-
-	switch ((long)data)
+	switch ((long)m->private)
 	{
 	case LED_NOLCD:
-		out += sprintf(out, "Heartbeat: %d\n", led_heartbeat);
-		out += sprintf(out, "Disk IO: %d\n", led_diskio);
-		out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx);
+		seq_printf(m, "Heartbeat: %d\n", led_heartbeat);
+		seq_printf(m, "Disk IO: %d\n", led_diskio);
+		seq_printf(m, "LAN Rx/Tx: %d\n", led_lanrxtx);
 		break;
 	case LED_HASLCD:
-		out += sprintf(out, "%s\n", lcd_text);
+		seq_printf(m, "%s\n", lcd_text);
 		break;
 	default:
-		*eof = 1;
 		return 0;
 	}
-
-	len = out - page - off;
-	if (len < count) {
-		*eof = 1;
-		if (len <= 0) return 0;
-	} else {
-		len = count;
-	}
-	*start = page + off;
-	return len;
+	return 0;
 }
 
-static int led_proc_write(struct file *file, const char *buf, 
-	unsigned long count, void *data)
+static int led_proc_open(struct inode *inode, struct file *file)
 {
+	return single_open(file, led_proc_show, PDE(inode)->data);
+}
+
+
+static ssize_t led_proc_write(struct file *file, const char *buf,
+	size_t count, loff_t *pos)
+{
+	void *data = PDE(file->f_path.dentry->d_inode)->data;
 	char *cur, lbuf[count + 1];
 	int d;
 
@@ -234,6 +228,15 @@
 	return -EINVAL;
 }
 
+static const struct file_operations led_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= led_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= led_proc_write,
+};
+
 static int __init led_create_procfs(void)
 {
 	struct proc_dir_entry *proc_pdc_root = NULL;
@@ -243,19 +246,15 @@
 
 	proc_pdc_root = proc_mkdir("pdc", 0);
 	if (!proc_pdc_root) return -1;
-	ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+	ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root,
+				&led_proc_fops, (void *)LED_NOLCD); /* LED */
 	if (!ent) return -1;
-	ent->data = (void *)LED_NOLCD; /* LED */
-	ent->read_proc = led_proc_read;
-	ent->write_proc = led_proc_write;
 
 	if (led_type == LED_HASLCD)
 	{
-		ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+		ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root,
+					&led_proc_fops, (void *)LED_HASLCD); /* LCD */
 		if (!ent) return -1;
-		ent->data = (void *)LED_HASLCD; /* LCD */
-		ent->read_proc = led_proc_read;
-		ent->write_proc = led_proc_write;
 	}
 
 	return 0;
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 675f04e..a35c9c5 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -326,7 +326,7 @@
 }
 
 static struct irq_chip superio_interrupt_type = {
-	.typename =	SUPERIO,
+	.name	 =	SUPERIO,
 	.startup =	superio_startup_irq,
 	.shutdown =	superio_disable_irq,
 	.enable =	superio_enable_irq,
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 2597145..ad113b0 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -3403,7 +3403,7 @@
 		*val = automatic;
 	else if (!strncmp(s, "none", 4))
 		*val = none;
-	else if (nofifo && !strncmp(s, "nofifo", 4))
+	else if (nofifo && !strncmp(s, "nofifo", 6))
 		*val = nofifo;
 	else {
 		char *ep;
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 6cdc931..83aae47 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -339,6 +339,35 @@
 }
 #endif
 
+#ifdef CONFIG_ACPI_NUMA
+static int __init
+dmar_parse_one_rhsa(struct acpi_dmar_header *header)
+{
+	struct acpi_dmar_rhsa *rhsa;
+	struct dmar_drhd_unit *drhd;
+
+	rhsa = (struct acpi_dmar_rhsa *)header;
+	for_each_drhd_unit(drhd) {
+		if (drhd->reg_base_addr == rhsa->base_address) {
+			int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
+
+			if (!node_online(node))
+				node = -1;
+			drhd->iommu->node = node;
+			return 0;
+		}
+	}
+	WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
+	     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+	     drhd->reg_base_addr,
+	     dmi_get_system_info(DMI_BIOS_VENDOR),
+	     dmi_get_system_info(DMI_BIOS_VERSION),
+	     dmi_get_system_info(DMI_PRODUCT_VERSION));
+
+	return 0;
+}
+#endif
+
 static void __init
 dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
 {
@@ -458,7 +487,9 @@
 #endif
 			break;
 		case ACPI_DMAR_HARDWARE_AFFINITY:
-			/* We don't do anything with RHSA (yet?) */
+#ifdef CONFIG_ACPI_NUMA
+			ret = dmar_parse_one_rhsa(entry_header);
+#endif
 			break;
 		default:
 			printk(KERN_WARNING PREFIX
@@ -582,6 +613,8 @@
 	return 0;
 }
 
+static int bios_warned;
+
 int __init check_zero_address(void)
 {
 	struct acpi_table_dmar *dmar;
@@ -601,6 +634,9 @@
 		}
 
 		if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
+			void __iomem *addr;
+			u64 cap, ecap;
+
 			drhd = (void *)entry_header;
 			if (!drhd->address) {
 				/* Promote an attitude of violence to a BIOS engineer today */
@@ -609,17 +645,40 @@
 				     dmi_get_system_info(DMI_BIOS_VENDOR),
 				     dmi_get_system_info(DMI_BIOS_VERSION),
 				     dmi_get_system_info(DMI_PRODUCT_VERSION));
-#ifdef CONFIG_DMAR
-				dmar_disabled = 1;
-#endif
-				return 0;
+				bios_warned = 1;
+				goto failed;
 			}
-			break;
+
+			addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
+			if (!addr ) {
+				printk("IOMMU: can't validate: %llx\n", drhd->address);
+				goto failed;
+			}
+			cap = dmar_readq(addr + DMAR_CAP_REG);
+			ecap = dmar_readq(addr + DMAR_ECAP_REG);
+			early_iounmap(addr, VTD_PAGE_SIZE);
+			if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
+				/* Promote an attitude of violence to a BIOS engineer today */
+				WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+				     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+				      drhd->address,
+				      dmi_get_system_info(DMI_BIOS_VENDOR),
+				      dmi_get_system_info(DMI_BIOS_VERSION),
+				      dmi_get_system_info(DMI_PRODUCT_VERSION));
+				bios_warned = 1;
+				goto failed;
+			}
 		}
 
 		entry_header = ((void *)entry_header + entry_header->length);
 	}
 	return 1;
+
+failed:
+#ifdef CONFIG_DMAR
+	dmar_disabled = 1;
+#endif
+	return 0;
 }
 
 void __init detect_intel_iommu(void)
@@ -670,6 +729,18 @@
 	int agaw = 0;
 	int msagaw = 0;
 
+	if (!drhd->reg_base_addr) {
+		if (!bios_warned) {
+			WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
+			     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			     dmi_get_system_info(DMI_BIOS_VENDOR),
+			     dmi_get_system_info(DMI_BIOS_VERSION),
+			     dmi_get_system_info(DMI_PRODUCT_VERSION));
+			bios_warned = 1;
+		}
+		return -EINVAL;
+	}
+
 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
 	if (!iommu)
 		return -ENOMEM;
@@ -686,13 +757,16 @@
 	iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
 
 	if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-		/* Promote an attitude of violence to a BIOS engineer today */
-		WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
-		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		     drhd->reg_base_addr,
-		     dmi_get_system_info(DMI_BIOS_VENDOR),
-		     dmi_get_system_info(DMI_BIOS_VERSION),
-		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		if (!bios_warned) {
+			/* Promote an attitude of violence to a BIOS engineer today */
+			WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
+			     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			     drhd->reg_base_addr,
+			     dmi_get_system_info(DMI_BIOS_VENDOR),
+			     dmi_get_system_info(DMI_BIOS_VERSION),
+			     dmi_get_system_info(DMI_PRODUCT_VERSION));
+			bios_warned = 1;
+		}
 		goto err_unmap;
 	}
 
@@ -715,6 +789,8 @@
 	iommu->agaw = agaw;
 	iommu->msagaw = msagaw;
 
+	iommu->node = -1;
+
 	/* the registers might be more than one page */
 	map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
 		cap_max_fault_reg_offset(iommu->cap));
@@ -1056,6 +1132,7 @@
 int dmar_enable_qi(struct intel_iommu *iommu)
 {
 	struct q_inval *qi;
+	struct page *desc_page;
 
 	if (!ecap_qis(iommu->ecap))
 		return -ENOENT;
@@ -1072,13 +1149,16 @@
 
 	qi = iommu->qi;
 
-	qi->desc = (void *)(get_zeroed_page(GFP_ATOMIC));
-	if (!qi->desc) {
+
+	desc_page = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, 0);
+	if (!desc_page) {
 		kfree(qi);
 		iommu->qi = 0;
 		return -ENOMEM;
 	}
 
+	qi->desc = page_address(desc_page);
+
 	qi->desc_status = kmalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
 	if (!qi->desc_status) {
 		free_page((unsigned long) qi->desc);
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 8d61594..e56f9be 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -277,6 +277,7 @@
 
 struct dmar_domain {
 	int	id;			/* domain id */
+	int	nid;			/* node id */
 	unsigned long iommu_bmp;	/* bitmap of iommus this domain uses*/
 
 	struct list_head devices; 	/* all devices' list */
@@ -386,30 +387,14 @@
 static struct kmem_cache *iommu_devinfo_cache;
 static struct kmem_cache *iommu_iova_cache;
 
-static inline void *iommu_kmem_cache_alloc(struct kmem_cache *cachep)
+static inline void *alloc_pgtable_page(int node)
 {
-	unsigned int flags;
-	void *vaddr;
+	struct page *page;
+	void *vaddr = NULL;
 
-	/* trying to avoid low memory issues */
-	flags = current->flags & PF_MEMALLOC;
-	current->flags |= PF_MEMALLOC;
-	vaddr = kmem_cache_alloc(cachep, GFP_ATOMIC);
-	current->flags &= (~PF_MEMALLOC | flags);
-	return vaddr;
-}
-
-
-static inline void *alloc_pgtable_page(void)
-{
-	unsigned int flags;
-	void *vaddr;
-
-	/* trying to avoid low memory issues */
-	flags = current->flags & PF_MEMALLOC;
-	current->flags |= PF_MEMALLOC;
-	vaddr = (void *)get_zeroed_page(GFP_ATOMIC);
-	current->flags &= (~PF_MEMALLOC | flags);
+	page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
+	if (page)
+		vaddr = page_address(page);
 	return vaddr;
 }
 
@@ -420,7 +405,7 @@
 
 static inline void *alloc_domain_mem(void)
 {
-	return iommu_kmem_cache_alloc(iommu_domain_cache);
+	return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
 }
 
 static void free_domain_mem(void *vaddr)
@@ -430,7 +415,7 @@
 
 static inline void * alloc_devinfo_mem(void)
 {
-	return iommu_kmem_cache_alloc(iommu_devinfo_cache);
+	return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
 }
 
 static inline void free_devinfo_mem(void *vaddr)
@@ -440,7 +425,7 @@
 
 struct iova *alloc_iova_mem(void)
 {
-	return iommu_kmem_cache_alloc(iommu_iova_cache);
+	return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
 }
 
 void free_iova_mem(struct iova *iova)
@@ -589,7 +574,8 @@
 	root = &iommu->root_entry[bus];
 	context = get_context_addr_from_root(root);
 	if (!context) {
-		context = (struct context_entry *)alloc_pgtable_page();
+		context = (struct context_entry *)
+				alloc_pgtable_page(iommu->node);
 		if (!context) {
 			spin_unlock_irqrestore(&iommu->lock, flags);
 			return NULL;
@@ -732,7 +718,7 @@
 		if (!dma_pte_present(pte)) {
 			uint64_t pteval;
 
-			tmp_page = alloc_pgtable_page();
+			tmp_page = alloc_pgtable_page(domain->nid);
 
 			if (!tmp_page)
 				return NULL;
@@ -868,7 +854,7 @@
 	struct root_entry *root;
 	unsigned long flags;
 
-	root = (struct root_entry *)alloc_pgtable_page();
+	root = (struct root_entry *)alloc_pgtable_page(iommu->node);
 	if (!root)
 		return -ENOMEM;
 
@@ -1263,6 +1249,7 @@
 	if (!domain)
 		return NULL;
 
+	domain->nid = -1;
 	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
 	domain->flags = 0;
 
@@ -1420,9 +1407,10 @@
 		domain->iommu_snooping = 0;
 
 	domain->iommu_count = 1;
+	domain->nid = iommu->node;
 
 	/* always allocate the top pgd */
-	domain->pgd = (struct dma_pte *)alloc_pgtable_page();
+	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
 	if (!domain->pgd)
 		return -ENOMEM;
 	__iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
@@ -1523,12 +1511,15 @@
 
 		/* Skip top levels of page tables for
 		 * iommu which has less agaw than default.
+		 * Unnecessary for PT mode.
 		 */
-		for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
-			pgd = phys_to_virt(dma_pte_addr(pgd));
-			if (!dma_pte_present(pgd)) {
-				spin_unlock_irqrestore(&iommu->lock, flags);
-				return -ENOMEM;
+		if (translation != CONTEXT_TT_PASS_THROUGH) {
+			for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+				pgd = phys_to_virt(dma_pte_addr(pgd));
+				if (!dma_pte_present(pgd)) {
+					spin_unlock_irqrestore(&iommu->lock, flags);
+					return -ENOMEM;
+				}
 			}
 		}
 	}
@@ -1577,6 +1568,8 @@
 	spin_lock_irqsave(&domain->iommu_lock, flags);
 	if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
 		domain->iommu_count++;
+		if (domain->iommu_count == 1)
+			domain->nid = iommu->node;
 		domain_update_iommu_cap(domain);
 	}
 	spin_unlock_irqrestore(&domain->iommu_lock, flags);
@@ -1991,6 +1984,16 @@
 	       "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
 	       pci_name(pdev), start, end);
 	
+	if (end < start) {
+		WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
+			"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+			dmi_get_system_info(DMI_BIOS_VENDOR),
+			dmi_get_system_info(DMI_BIOS_VERSION),
+		     dmi_get_system_info(DMI_PRODUCT_VERSION));
+		ret = -EIO;
+		goto error;
+	}
+
 	if (end >> agaw_to_width(domain->agaw)) {
 		WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
 		     "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
@@ -3228,6 +3231,9 @@
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct dmar_domain *domain;
 
+	if (iommu_no_mapping(dev))
+		return 0;
+
 	domain = find_domain(pdev);
 	if (!domain)
 		return 0;
@@ -3455,6 +3461,7 @@
 		return NULL;
 
 	domain->id = vm_domid++;
+	domain->nid = -1;
 	memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
 	domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
 
@@ -3481,9 +3488,10 @@
 	domain->iommu_coherency = 0;
 	domain->iommu_snooping = 0;
 	domain->max_addr = 0;
+	domain->nid = -1;
 
 	/* always allocate the top pgd */
-	domain->pgd = (struct dma_pte *)alloc_pgtable_page();
+	domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
 	if (!domain->pgd)
 		return -ENOMEM;
 	domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 1487bf2..8b65a48 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -590,7 +590,8 @@
 	if (!iommu->ir_table)
 		return -ENOMEM;
 
-	pages = alloc_pages(GFP_ATOMIC | __GFP_ZERO, INTR_REMAP_PAGE_ORDER);
+	pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
+				 INTR_REMAP_PAGE_ORDER);
 
 	if (!pages) {
 		printk(KERN_ERR "failed to allocate pages of order %d\n",
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 3aabf1e..76e640b 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -291,7 +291,7 @@
 		skt->nr = ops->first + i;
 		skt->ops = ops;
 		skt->socket.owner = ops->owner;
-		skt->socket.dev.parent = dev;
+		skt->socket.dev.parent = &dev->dev;
 		skt->socket.pci_irq = NO_IRQ;
 
 		ret = pxa2xx_drv_pcmcia_add_one(skt);
@@ -304,8 +304,8 @@
 			soc_pcmcia_remove_one(&sinfo->skt[i]);
 		kfree(sinfo);
 	} else {
-		pxa2xx_configure_sockets(dev);
-		dev_set_drvdata(dev, sinfo);
+		pxa2xx_configure_sockets(&dev->dev);
+		dev_set_drvdata(&dev->dev, sinfo);
 	}
 
 	return ret;
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 55ca39d..fc5bf9d 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -334,6 +334,8 @@
 	depends on HOTPLUG_PCI
 	select BACKLIGHT_CLASS_DEVICE
 	select HWMON
+	select LEDS_CLASS
+	select NEW_LEDS
 	---help---
 	  This driver supports the Fn-Fx keys on Eee PC laptops.
 
@@ -365,6 +367,18 @@
 	  It is safe to enable this driver even if your DSDT doesn't define
 	  any ACPI-WMI devices.
 
+config MSI_WMI
+	tristate "MSI WMI extras"
+	depends on ACPI_WMI
+	depends on INPUT
+	depends on BACKLIGHT_CLASS_DEVICE
+	select INPUT_SPARSEKMAP
+	help
+	 Say Y here if you want to support WMI-based hotkeys on MSI laptops.
+
+	 To compile this driver as a module, choose M here: the module will
+	 be called msi-wmi.
+
 config ACPI_ASUS
 	tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
 	depends on ACPI
@@ -435,4 +449,19 @@
 
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
+
+config TOSHIBA_BT_RFKILL
+	tristate "Toshiba Bluetooth RFKill switch support"
+	depends on ACPI
+	---help---
+	  This driver adds support for Bluetooth events for the RFKill
+	  switch on modern Toshiba laptops with full ACPI support and
+	  an RFKill switch.
+
+	  This driver handles RFKill events for the TOS6205 Bluetooth,
+	  and re-enables it when the switch is set back to the 'on'
+	  position.
+
+	  If you have a modern Toshiba laptop with a Bluetooth and an
+	  RFKill switch (such as the Portege R500), say Y.
 endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index d1c1621..b7474b6 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -18,6 +18,8 @@
 obj-$(CONFIG_PANASONIC_LAPTOP)	+= panasonic-laptop.o
 obj-$(CONFIG_INTEL_MENLOW)	+= intel_menlow.o
 obj-$(CONFIG_ACPI_WMI)		+= wmi.o
+obj-$(CONFIG_MSI_WMI)		+= msi-wmi.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_TOPSTAR_LAPTOP)	+= topstar-laptop.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
+obj-$(CONFIG_TOSHIBA_BT_RFKILL)	+= toshiba_bluetooth.o
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index be27aa4..79b15b9 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
  */
 #undef START_IN_KERNEL_MODE
 
-#define DRV_VER "0.5.18"
+#define DRV_VER "0.5.20"
 
 /*
  * According to the Atom N270 datasheet,
@@ -112,12 +112,14 @@
 MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
 
 /*
- * cmd_off: to switch the fan completely off / to check if the fan is off
+ * cmd_off: to switch the fan completely off
+ * chk_off: to check if the fan is off
  *	cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then
  *		the fan speed depending on the temperature
  */
 struct fancmd {
 	u8 cmd_off;
+	u8 chk_off;
 	u8 cmd_auto;
 };
 
@@ -134,32 +136,41 @@
 /* Register addresses and values for different BIOS versions */
 static const struct bios_settings_t bios_tbl[] = {
 	/* AOA110 */
-	{"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
-	{"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
-	{"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} },
-	{"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
-	{"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
-	{"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
+	{"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
+	{"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
+	{"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} },
 	/* AOA150 */
-	{"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
-	{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	/* Acer 1410 */
+	{"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} },
 	/* special BIOS / other */
-	{"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
-	{"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
-	{"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
+	{"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3103 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3201 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Gateway         ", "LT31            ", "v1.3302 ", 0x55, 0x58,
+		{0x10, 0x0f, 0x00} },
+	{"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
+	{"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} },
+	{"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
 	/* pewpew-terminator */
-	{"", "", "", 0, 0, {0, 0} }
+	{"", "", "", 0, 0, {0, 0, 0} }
 };
 
 static const struct bios_settings_t *bios_cfg __read_mostly;
@@ -183,7 +194,7 @@
 	if (ec_read(bios_cfg->fanreg, &fan))
 		return -EINVAL;
 
-	if (fan != bios_cfg->cmd.cmd_off)
+	if (fan != bios_cfg->cmd.chk_off)
 		*state = ACERHDF_FAN_AUTO;
 	else
 		*state = ACERHDF_FAN_OFF;
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b39d2bb..61a1c75 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -221,6 +221,7 @@
  */
 static const struct acpi_device_id asus_device_ids[] = {
 	{"ATK0100", 0},
+	{"ATK0101", 0},
 	{"", 0},
 };
 MODULE_DEVICE_TABLE(acpi, asus_device_ids);
@@ -232,6 +233,7 @@
 static struct acpi_driver asus_hotk_driver = {
 	.name = ASUS_HOTK_NAME,
 	.class = ASUS_HOTK_CLASS,
+	.owner = THIS_MODULE,
 	.ids = asus_device_ids,
 	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
 	.ops = {
@@ -293,6 +295,11 @@
 enum { KE_KEY, KE_END };
 
 static struct key_entry asus_keymap[] = {
+	{KE_KEY, 0x02, KEY_SCREENLOCK},
+	{KE_KEY, 0x05, KEY_WLAN},
+	{KE_KEY, 0x08, KEY_F13},
+	{KE_KEY, 0x17, KEY_ZOOM},
+	{KE_KEY, 0x1f, KEY_BATTERY},
 	{KE_KEY, 0x30, KEY_VOLUMEUP},
 	{KE_KEY, 0x31, KEY_VOLUMEDOWN},
 	{KE_KEY, 0x32, KEY_MUTE},
@@ -312,8 +319,11 @@
 	{KE_KEY, 0x5F, KEY_WLAN},
 	{KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
 	{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
+	{KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
+	{KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
 	{KE_KEY, 0x82, KEY_CAMERA},
+	{KE_KEY, 0x88, KEY_WLAN },
 	{KE_KEY, 0x8A, KEY_PROG1},
 	{KE_KEY, 0x95, KEY_MEDIA},
 	{KE_KEY, 0x99, KEY_PHONE},
@@ -1240,9 +1250,6 @@
 {
 	int result;
 
-	if (!device)
-		return -EINVAL;
-
 	pr_notice("Asus Laptop Support version %s\n",
 	       ASUS_LAPTOP_VERSION);
 
@@ -1283,8 +1290,8 @@
 	hotk->ledd_status = 0xFFF;
 
 	/* Set initial values of light sensor and level */
-	hotk->light_switch = 1;	/* Default to light sensor disabled */
-	hotk->light_level = 0;	/* level 5 for sensor sensitivity */
+	hotk->light_switch = 0;	/* Default to light sensor disabled */
+	hotk->light_level = 5;	/* level 5 for sensor sensitivity */
 
 	if (ls_switch_handle)
 		set_light_sens_switch(hotk->light_switch);
@@ -1306,9 +1313,6 @@
 
 static int asus_hotk_remove(struct acpi_device *device, int type)
 {
-	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
-
 	kfree(hotk->name);
 	kfree(hotk);
 
@@ -1444,9 +1448,6 @@
 {
 	int result;
 
-	if (acpi_disabled)
-		return -ENODEV;
-
 	result = acpi_bus_register_driver(&asus_hotk_driver);
 	if (result < 0)
 		return result;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ddf5240..0c9c531 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -466,6 +466,7 @@
 static struct acpi_driver asus_hotk_driver = {
 	.name = "asus_acpi",
 	.class = ACPI_HOTK_CLASS,
+	.owner = THIS_MODULE,
 	.ids = asus_device_ids,
 	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
 	.ops = {
@@ -1334,9 +1335,6 @@
 	acpi_status status = AE_OK;
 	int result;
 
-	if (!device)
-		return -EINVAL;
-
 	printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
 	       ASUS_ACPI_VERSION);
 
@@ -1392,9 +1390,6 @@
 
 static int asus_hotk_remove(struct acpi_device *device, int type)
 {
-	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
-
 	asus_hotk_remove_fs(device);
 
 	kfree(hotk);
@@ -1422,21 +1417,17 @@
 {
 	int result;
 
-	if (acpi_disabled)
-		return -ENODEV;
+	result = acpi_bus_register_driver(&asus_hotk_driver);
+	if (result < 0)
+		return result;
 
 	asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
 	if (!asus_proc_dir) {
 		printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
+		acpi_bus_unregister_driver(&asus_hotk_driver);
 		return -ENODEV;
 	}
 
-	result = acpi_bus_register_driver(&asus_hotk_driver);
-	if (result < 0) {
-		remove_proc_entry(PROC_ASUS, acpi_root_dir);
-		return result;
-	}
-
 	/*
 	 * This is a bit of a kludge.  We only want this module loaded
 	 * for ASUS systems, but there's currently no way to probe the
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 11003bb..1a387e7 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -51,7 +51,6 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
-#include <linux/autoconf.h>
 
 #define COMPAL_DRIVER_VERSION "0.2.6"
 
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 74909c4..3780994 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -58,6 +58,14 @@
 static int da_num_tokens;
 static struct calling_interface_token *da_tokens;
 
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = "dell-laptop",
+		.owner = THIS_MODULE,
+	}
+};
+
+static struct platform_device *platform_device;
 static struct backlight_device *dell_backlight_device;
 static struct rfkill *wifi_rfkill;
 static struct rfkill *bluetooth_rfkill;
@@ -74,7 +82,7 @@
 	{ }
 };
 
-static void parse_da_table(const struct dmi_header *dm)
+static void __init parse_da_table(const struct dmi_header *dm)
 {
 	/* Final token is a terminator, so we don't want to copy it */
 	int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
@@ -103,7 +111,7 @@
 	da_num_tokens += tokens;
 }
 
-static void find_tokens(const struct dmi_header *dm, void *dummy)
+static void __init find_tokens(const struct dmi_header *dm, void *dummy)
 {
 	switch (dm->type) {
 	case 0xd4: /* Indexed IO */
@@ -197,8 +205,8 @@
 	dell_send_request(&buffer, 17, 11);
 	status = buffer.output[1];
 
-	if (status & BIT(bit))
-		rfkill_set_hw_state(rfkill, !!(status & BIT(16)));
+	rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
+	rfkill_set_hw_state(rfkill, !(status & BIT(16)));
 }
 
 static const struct rfkill_ops dell_rfkill_ops = {
@@ -206,7 +214,7 @@
 	.query = dell_rfkill_query,
 };
 
-static int dell_setup_rfkill(void)
+static int __init dell_setup_rfkill(void)
 {
 	struct calling_interface_buffer buffer;
 	int status;
@@ -217,7 +225,8 @@
 	status = buffer.output[1];
 
 	if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
-		wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN,
+		wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
+					   RFKILL_TYPE_WLAN,
 					   &dell_rfkill_ops, (void *) 1);
 		if (!wifi_rfkill) {
 			ret = -ENOMEM;
@@ -229,7 +238,8 @@
 	}
 
 	if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
-		bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL,
+		bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
+						&platform_device->dev,
 						RFKILL_TYPE_BLUETOOTH,
 						&dell_rfkill_ops, (void *) 2);
 		if (!bluetooth_rfkill) {
@@ -242,7 +252,9 @@
 	}
 
 	if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
-		wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN,
+		wwan_rfkill = rfkill_alloc("dell-wwan",
+					   &platform_device->dev,
+					   RFKILL_TYPE_WWAN,
 					   &dell_rfkill_ops, (void *) 3);
 		if (!wwan_rfkill) {
 			ret = -ENOMEM;
@@ -268,6 +280,22 @@
 	return ret;
 }
 
+static void dell_cleanup_rfkill(void)
+{
+	if (wifi_rfkill) {
+		rfkill_unregister(wifi_rfkill);
+		rfkill_destroy(wifi_rfkill);
+	}
+	if (bluetooth_rfkill) {
+		rfkill_unregister(bluetooth_rfkill);
+		rfkill_destroy(bluetooth_rfkill);
+	}
+	if (wwan_rfkill) {
+		rfkill_unregister(wwan_rfkill);
+		rfkill_destroy(wwan_rfkill);
+	}
+}
+
 static int dell_send_intensity(struct backlight_device *bd)
 {
 	struct calling_interface_buffer buffer;
@@ -326,11 +354,23 @@
 		return -ENODEV;
 	}
 
+	ret = platform_driver_register(&platform_driver);
+	if (ret)
+		goto fail_platform_driver;
+	platform_device = platform_device_alloc("dell-laptop", -1);
+	if (!platform_device) {
+		ret = -ENOMEM;
+		goto fail_platform_device1;
+	}
+	ret = platform_device_add(platform_device);
+	if (ret)
+		goto fail_platform_device2;
+
 	ret = dell_setup_rfkill();
 
 	if (ret) {
 		printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n");
-		goto out;
+		goto fail_rfkill;
 	}
 
 #ifdef CONFIG_ACPI
@@ -352,13 +392,13 @@
 	if (max_intensity) {
 		dell_backlight_device = backlight_device_register(
 			"dell_backlight",
-			NULL, NULL,
+			&platform_device->dev, NULL,
 			&dell_ops);
 
 		if (IS_ERR(dell_backlight_device)) {
 			ret = PTR_ERR(dell_backlight_device);
 			dell_backlight_device = NULL;
-			goto out;
+			goto fail_backlight;
 		}
 
 		dell_backlight_device->props.max_brightness = max_intensity;
@@ -368,13 +408,16 @@
 	}
 
 	return 0;
-out:
-	if (wifi_rfkill)
-		rfkill_unregister(wifi_rfkill);
-	if (bluetooth_rfkill)
-		rfkill_unregister(bluetooth_rfkill);
-	if (wwan_rfkill)
-		rfkill_unregister(wwan_rfkill);
+
+fail_backlight:
+	dell_cleanup_rfkill();
+fail_rfkill:
+	platform_device_del(platform_device);
+fail_platform_device2:
+	platform_device_put(platform_device);
+fail_platform_device1:
+	platform_driver_unregister(&platform_driver);
+fail_platform_driver:
 	kfree(da_tokens);
 	return ret;
 }
@@ -382,12 +425,7 @@
 static void __exit dell_exit(void)
 {
 	backlight_device_unregister(dell_backlight_device);
-	if (wifi_rfkill)
-		rfkill_unregister(wifi_rfkill);
-	if (bluetooth_rfkill)
-		rfkill_unregister(bluetooth_rfkill);
-	if (wwan_rfkill)
-		rfkill_unregister(wwan_rfkill);
+	dell_cleanup_rfkill();
 }
 
 module_init(dell_init);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 0f900cc..67f3fe7 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -31,6 +31,7 @@
 #include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
+#include <linux/dmi.h>
 
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
@@ -38,6 +39,8 @@
 
 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
 
+static int acpi_video;
+
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
 struct key_entry {
@@ -54,7 +57,7 @@
  * via the keyboard controller so should not be sent again.
  */
 
-static struct key_entry dell_wmi_keymap[] = {
+static struct key_entry dell_legacy_wmi_keymap[] = {
 	{KE_KEY, 0xe045, KEY_PROG1},
 	{KE_KEY, 0xe009, KEY_EJECTCD},
 
@@ -72,7 +75,7 @@
 
 	/* The next device is at offset 6, the active devices are at
 	   offset 8 and the attached devices at offset 10 */
-	{KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE},
+	{KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
 
 	{KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
 
@@ -96,6 +99,47 @@
 	{KE_END, 0}
 };
 
+static bool dell_new_hk_type;
+
+struct dell_new_keymap_entry {
+	u16 scancode;
+	u16 keycode;
+};
+
+struct dell_hotkey_table {
+	struct dmi_header header;
+	struct dell_new_keymap_entry keymap[];
+
+};
+
+static struct key_entry *dell_new_wmi_keymap;
+
+static u16 bios_to_linux_keycode[256] = {
+
+	KEY_MEDIA,	KEY_NEXTSONG,	KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
+	KEY_STOPCD,	KEY_UNKNOWN,	KEY_UNKNOWN,	KEY_UNKNOWN,
+	KEY_WWW,	KEY_UNKNOWN,	KEY_VOLUMEDOWN, KEY_MUTE,
+	KEY_VOLUMEUP,	KEY_UNKNOWN,	KEY_BATTERY,	KEY_EJECTCD,
+	KEY_UNKNOWN,	KEY_SLEEP,	KEY_PROG1, KEY_BRIGHTNESSDOWN,
+	KEY_BRIGHTNESSUP,	KEY_UNKNOWN,	KEY_KBDILLUMTOGGLE,
+	KEY_UNKNOWN,	KEY_SWITCHVIDEOMODE,	KEY_UNKNOWN, KEY_UNKNOWN,
+	KEY_SWITCHVIDEOMODE,	KEY_UNKNOWN,	KEY_UNKNOWN, KEY_PROG2,
+	KEY_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	KEY_PROG3
+};
+
+
+static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
+
 static struct input_dev *dell_wmi_input_dev;
 
 static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
@@ -164,24 +208,78 @@
 	obj = (union acpi_object *)response.pointer;
 
 	if (obj && obj->type == ACPI_TYPE_BUFFER) {
-		int *buffer = (int *)obj->buffer.pointer;
-		/*
-		 *  The upper bytes of the event may contain
-		 *  additional information, so mask them off for the
-		 *  scancode lookup
-		 */
-		key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF);
-		if (key) {
+		int reported_key;
+		u16 *buffer_entry = (u16 *)obj->buffer.pointer;
+		if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
+			printk(KERN_INFO "dell-wmi: Received unknown WMI event"
+					 " (0x%x)\n", buffer_entry[1]);
+			return;
+		}
+
+		if (dell_new_hk_type)
+			reported_key = (int)buffer_entry[2];
+		else
+			reported_key = (int)buffer_entry[1] & 0xffff;
+
+		key = dell_wmi_get_entry_by_scancode(reported_key);
+
+		if (!key) {
+			printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
+				reported_key);
+		} else if ((key->keycode == KEY_BRIGHTNESSUP ||
+			    key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) {
+			/* Don't report brightness notifications that will also
+			 * come via ACPI */
+			return;
+		} else {
 			input_report_key(dell_wmi_input_dev, key->keycode, 1);
 			input_sync(dell_wmi_input_dev);
 			input_report_key(dell_wmi_input_dev, key->keycode, 0);
 			input_sync(dell_wmi_input_dev);
-		} else if (buffer[1] & 0xFFFF)
-			printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
-			       buffer[1] & 0xFFFF);
+		}
 	}
 }
 
+
+static void setup_new_hk_map(const struct dmi_header *dm)
+{
+
+	int i;
+	int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
+	struct dell_hotkey_table *table =
+		container_of(dm, struct dell_hotkey_table, header);
+
+	dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
+				      sizeof(struct key_entry), GFP_KERNEL);
+
+	for (i = 0; i < hotkey_num; i++) {
+		dell_new_wmi_keymap[i].type = KE_KEY;
+		dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
+		dell_new_wmi_keymap[i].keycode =
+			(table->keymap[i].keycode > 255) ? 0 :
+			bios_to_linux_keycode[table->keymap[i].keycode];
+	}
+
+	dell_new_wmi_keymap[i].type = KE_END;
+	dell_new_wmi_keymap[i].code = 0;
+	dell_new_wmi_keymap[i].keycode = 0;
+
+	dell_wmi_keymap = dell_new_wmi_keymap;
+
+}
+
+
+static void find_hk_type(const struct dmi_header *dm, void *dummy)
+{
+
+	if ((dm->type == 0xb2) && (dm->length > 6)) {
+		dell_new_hk_type = true;
+		setup_new_hk_map(dm);
+	}
+
+}
+
+
 static int __init dell_wmi_input_setup(void)
 {
 	struct key_entry *key;
@@ -226,6 +324,9 @@
 	int err;
 
 	if (wmi_has_guid(DELL_EVENT_GUID)) {
+
+		dmi_walk(find_hk_type, NULL);
+
 		err = dell_wmi_input_setup();
 
 		if (err)
@@ -240,6 +341,8 @@
 			return err;
 		}
 
+		acpi_video = acpi_video_backlight_support();
+
 	} else
 		printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
 
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index e647a85..5838c69 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1,5 +1,5 @@
 /*
- *  eepc-laptop.c - Asus Eee PC extras
+ *  eeepc-laptop.c - Asus Eee PC extras
  *
  *  Based on asus_acpi.c as patched for the Eee PC by Asus:
  *  ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
@@ -34,20 +34,23 @@
 #include <linux/rfkill.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
+#include <linux/leds.h>
 
 #define EEEPC_LAPTOP_VERSION	"0.1"
+#define EEEPC_LAPTOP_NAME	"Eee PC Hotkey Driver"
+#define EEEPC_LAPTOP_FILE	"eeepc"
 
-#define EEEPC_HOTK_NAME		"Eee PC Hotkey Driver"
-#define EEEPC_HOTK_FILE		"eeepc"
-#define EEEPC_HOTK_CLASS	"hotkey"
-#define EEEPC_HOTK_DEVICE_NAME	"Hotkey"
-#define EEEPC_HOTK_HID		"ASUS010"
+#define EEEPC_ACPI_CLASS	"hotkey"
+#define EEEPC_ACPI_DEVICE_NAME	"Hotkey"
+#define EEEPC_ACPI_HID		"ASUS010"
 
+MODULE_AUTHOR("Corentin Chary, Eric Cooper");
+MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
+MODULE_LICENSE("GPL");
 
 /*
  * Definitions for Asus EeePC
  */
-#define	NOTIFY_WLAN_ON	0x10
 #define NOTIFY_BRN_MIN	0x20
 #define NOTIFY_BRN_MAX	0x2f
 
@@ -117,58 +120,6 @@
 	NULL, NULL, "PBPS", "TPDS"
 };
 
-#define EEEPC_EC	"\\_SB.PCI0.SBRG.EC0."
-
-#define EEEPC_EC_FAN_PWM	EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
-#define EEEPC_EC_SC02		0x63
-#define EEEPC_EC_FAN_HRPM	EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
-#define EEEPC_EC_FAN_LRPM	EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
-#define EEEPC_EC_FAN_CTRL	EEEPC_EC "SFB3" /* Byte containing SF25  */
-#define EEEPC_EC_SFB3		0xD3
-
-/*
- * This is the main structure, we can use it to store useful information
- * about the hotk device
- */
-struct eeepc_hotk {
-	struct acpi_device *device;	/* the device we are in */
-	acpi_handle handle;		/* the handle of the hotk device */
-	u32 cm_supported;		/* the control methods supported
-					   by this BIOS */
-	uint init_flag;			/* Init flags */
-	u16 event_count[128];		/* count for each event */
-	struct input_dev *inputdev;
-	u16 *keycode_map;
-	struct rfkill *wlan_rfkill;
-	struct rfkill *bluetooth_rfkill;
-	struct rfkill *wwan3g_rfkill;
-	struct rfkill *wimax_rfkill;
-	struct hotplug_slot *hotplug_slot;
-	struct mutex hotplug_lock;
-};
-
-/* The actual device the driver binds to */
-static struct eeepc_hotk *ehotk;
-
-/* Platform device/driver */
-static int eeepc_hotk_thaw(struct device *device);
-static int eeepc_hotk_restore(struct device *device);
-
-static const struct dev_pm_ops eeepc_pm_ops = {
-	.thaw = eeepc_hotk_thaw,
-	.restore = eeepc_hotk_restore,
-};
-
-static struct platform_driver platform_driver = {
-	.driver = {
-		.name = EEEPC_HOTK_FILE,
-		.owner = THIS_MODULE,
-		.pm = &eeepc_pm_ops,
-	}
-};
-
-static struct platform_device *platform_device;
-
 struct key_entry {
 	char type;
 	u8 code;
@@ -177,7 +128,7 @@
 
 enum { KE_KEY, KE_END };
 
-static struct key_entry eeepc_keymap[] = {
+static const struct key_entry eeepc_keymap[] = {
 	/* Sleep already handled via generic ACPI code */
 	{KE_KEY, 0x10, KEY_WLAN },
 	{KE_KEY, 0x11, KEY_WLAN },
@@ -185,77 +136,56 @@
 	{KE_KEY, 0x13, KEY_MUTE },
 	{KE_KEY, 0x14, KEY_VOLUMEDOWN },
 	{KE_KEY, 0x15, KEY_VOLUMEUP },
+	{KE_KEY, 0x16, KEY_DISPLAY_OFF },
 	{KE_KEY, 0x1a, KEY_COFFEE },
 	{KE_KEY, 0x1b, KEY_ZOOM },
 	{KE_KEY, 0x1c, KEY_PROG2 },
 	{KE_KEY, 0x1d, KEY_PROG3 },
-	{KE_KEY, NOTIFY_BRN_MIN,     KEY_BRIGHTNESSDOWN },
-	{KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
+	{KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
+	{KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
 	{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
 	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
+	{KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
+	{KE_KEY, 0x38, KEY_F14 },
 	{KE_END, 0},
 };
 
-/*
- * The hotkey driver declaration
- */
-static int eeepc_hotk_add(struct acpi_device *device);
-static int eeepc_hotk_remove(struct acpi_device *device, int type);
-static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id eeepc_device_ids[] = {
-	{EEEPC_HOTK_HID, 0},
-	{"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
-
-static struct acpi_driver eeepc_hotk_driver = {
-	.name = EEEPC_HOTK_NAME,
-	.class = EEEPC_HOTK_CLASS,
-	.ids = eeepc_device_ids,
-	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-	.ops = {
-		.add = eeepc_hotk_add,
-		.remove = eeepc_hotk_remove,
-		.notify = eeepc_hotk_notify,
-	},
-};
-
-/* PCI hotplug ops */
-static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
-
-static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
-	.owner = THIS_MODULE,
-	.get_adapter_status = eeepc_get_adapter_status,
-	.get_power_status = eeepc_get_adapter_status,
-};
-
-/* The backlight device /sys/class/backlight */
-static struct backlight_device *eeepc_backlight_device;
-
-/* The hwmon device */
-static struct device *eeepc_hwmon_device;
 
 /*
- * The backlight class declaration
+ * This is the main structure, we can use it to store useful information
  */
-static int read_brightness(struct backlight_device *bd);
-static int update_bl_status(struct backlight_device *bd);
-static struct backlight_ops eeepcbl_ops = {
-	.get_brightness = read_brightness,
-	.update_status = update_bl_status,
-};
+struct eeepc_laptop {
+	acpi_handle handle;		/* the handle of the acpi device */
+	u32 cm_supported;		/* the control methods supported
+					   by this BIOS */
+	u16 event_count[128];		/* count for each event */
 
-MODULE_AUTHOR("Corentin Chary, Eric Cooper");
-MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
-MODULE_LICENSE("GPL");
+	struct platform_device *platform_device;
+	struct device *hwmon_device;
+	struct backlight_device *backlight_device;
+
+	struct input_dev *inputdev;
+	struct key_entry *keymap;
+
+	struct rfkill *wlan_rfkill;
+	struct rfkill *bluetooth_rfkill;
+	struct rfkill *wwan3g_rfkill;
+	struct rfkill *wimax_rfkill;
+
+	struct hotplug_slot *hotplug_slot;
+	struct mutex hotplug_lock;
+
+	struct led_classdev tpd_led;
+	int tpd_led_wk;
+	struct workqueue_struct *led_workqueue;
+	struct work_struct tpd_led_work;
+};
 
 /*
  * ACPI Helpers
  */
-static int write_acpi_int(acpi_handle handle, const char *method, int val,
-			  struct acpi_buffer *output)
+static int write_acpi_int(acpi_handle handle, const char *method, int val)
 {
 	struct acpi_object_list params;
 	union acpi_object in_obj;
@@ -266,7 +196,7 @@
 	in_obj.type = ACPI_TYPE_INTEGER;
 	in_obj.integer.value = val;
 
-	status = acpi_evaluate_object(handle, (char *)method, &params, output);
+	status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
 	return (status == AE_OK ? 0 : -1);
 }
 
@@ -285,80 +215,55 @@
 	}
 }
 
-static int set_acpi(int cm, int value)
+static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
 {
-	if (ehotk->cm_supported & (0x1 << cm)) {
-		const char *method = cm_setv[cm];
-		if (method == NULL)
-			return -ENODEV;
-		if (write_acpi_int(ehotk->handle, method, value, NULL))
-			pr_warning("Error writing %s\n", method);
+	const char *method = cm_setv[cm];
+
+	if (method == NULL)
+		return -ENODEV;
+	if ((eeepc->cm_supported & (0x1 << cm)) == 0)
+		return -ENODEV;
+
+	if (write_acpi_int(eeepc->handle, method, value))
+		pr_warning("Error writing %s\n", method);
+	return 0;
+}
+
+static int get_acpi(struct eeepc_laptop *eeepc, int cm)
+{
+	const char *method = cm_getv[cm];
+	int value;
+
+	if (method == NULL)
+		return -ENODEV;
+	if ((eeepc->cm_supported & (0x1 << cm)) == 0)
+		return -ENODEV;
+
+	if (read_acpi_int(eeepc->handle, method, &value))
+		pr_warning("Error reading %s\n", method);
+	return value;
+}
+
+static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
+			      acpi_handle *handle)
+{
+	const char *method = cm_setv[cm];
+	acpi_status status;
+
+	if (method == NULL)
+		return -ENODEV;
+	if ((eeepc->cm_supported & (0x1 << cm)) == 0)
+		return -ENODEV;
+
+	status = acpi_get_handle(eeepc->handle, (char *)method,
+				 handle);
+	if (status != AE_OK) {
+		pr_warning("Error finding %s\n", method);
+		return -ENODEV;
 	}
 	return 0;
 }
 
-static int get_acpi(int cm)
-{
-	int value = -ENODEV;
-	if ((ehotk->cm_supported & (0x1 << cm))) {
-		const char *method = cm_getv[cm];
-		if (method == NULL)
-			return -ENODEV;
-		if (read_acpi_int(ehotk->handle, method, &value))
-			pr_warning("Error reading %s\n", method);
-	}
-	return value;
-}
-
-/*
- * Backlight
- */
-static int read_brightness(struct backlight_device *bd)
-{
-	return get_acpi(CM_ASL_PANELBRIGHT);
-}
-
-static int set_brightness(struct backlight_device *bd, int value)
-{
-	value = max(0, min(15, value));
-	return set_acpi(CM_ASL_PANELBRIGHT, value);
-}
-
-static int update_bl_status(struct backlight_device *bd)
-{
-	return set_brightness(bd, bd->props.brightness);
-}
-
-/*
- * Rfkill helpers
- */
-
-static bool eeepc_wlan_rfkill_blocked(void)
-{
-	if (get_acpi(CM_ASL_WLAN) == 1)
-		return false;
-	return true;
-}
-
-static int eeepc_rfkill_set(void *data, bool blocked)
-{
-	unsigned long asl = (unsigned long)data;
-	return set_acpi(asl, !blocked);
-}
-
-static const struct rfkill_ops eeepc_rfkill_ops = {
-	.set_block = eeepc_rfkill_set,
-};
-
-static void __devinit eeepc_enable_camera(void)
-{
-	/*
-	 * If the following call to set_acpi() fails, it's because there's no
-	 * camera so we can ignore the error.
-	 */
-	if (get_acpi(CM_ASL_CAMERA) == 0)
-		set_acpi(CM_ASL_CAMERA, 1);
-}
 
 /*
  * Sys helpers
@@ -372,60 +277,63 @@
 	return count;
 }
 
-static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
+static ssize_t store_sys_acpi(struct device *dev, int cm,
+			      const char *buf, size_t count)
 {
+	struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 	int rv, value;
 
 	rv = parse_arg(buf, count, &value);
 	if (rv > 0)
-		value = set_acpi(cm, value);
+		value = set_acpi(eeepc, cm, value);
 	if (value < 0)
-		return value;
+		return -EIO;
 	return rv;
 }
 
-static ssize_t show_sys_acpi(int cm, char *buf)
+static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
 {
-	int value = get_acpi(cm);
+	struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
+	int value = get_acpi(eeepc, cm);
 
 	if (value < 0)
-		return value;
+		return -EIO;
 	return sprintf(buf, "%d\n", value);
 }
 
-#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm)				\
+#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm)			\
 	static ssize_t show_##_name(struct device *dev,			\
 				    struct device_attribute *attr,	\
 				    char *buf)				\
 	{								\
-		return show_sys_acpi(_cm, buf);				\
+		return show_sys_acpi(dev, _cm, buf);			\
 	}								\
 	static ssize_t store_##_name(struct device *dev,		\
 				     struct device_attribute *attr,	\
 				     const char *buf, size_t count)	\
 	{								\
-		return store_sys_acpi(_cm, buf, count);			\
+		return store_sys_acpi(dev, _cm, buf, count);		\
 	}								\
 	static struct device_attribute dev_attr_##_name = {		\
 		.attr = {						\
 			.name = __stringify(_name),			\
-			.mode = 0644 },					\
+			.mode = _mode },				\
 		.show   = show_##_name,					\
 		.store  = store_##_name,				\
 	}
 
-EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
-EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
-EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
+EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
+EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
+EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
 
 struct eeepc_cpufv {
 	int num;
 	int cur;
 };
 
-static int get_cpufv(struct eeepc_cpufv *c)
+static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
 {
-	c->cur = get_acpi(CM_ASL_CPUFV);
+	c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
 	c->num = (c->cur >> 8) & 0xff;
 	c->cur &= 0xff;
 	if (c->cur < 0 || c->num <= 0 || c->num > 12)
@@ -437,11 +345,12 @@
 				    struct device_attribute *attr,
 				    char *buf)
 {
+	struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 	struct eeepc_cpufv c;
 	int i;
 	ssize_t len = 0;
 
-	if (get_cpufv(&c))
+	if (get_cpufv(eeepc, &c))
 		return -ENODEV;
 	for (i = 0; i < c.num; i++)
 		len += sprintf(buf + len, "%d ", i);
@@ -453,9 +362,10 @@
 			  struct device_attribute *attr,
 			  char *buf)
 {
+	struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 	struct eeepc_cpufv c;
 
-	if (get_cpufv(&c))
+	if (get_cpufv(eeepc, &c))
 		return -ENODEV;
 	return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
 }
@@ -464,17 +374,18 @@
 			   struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
+	struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
 	struct eeepc_cpufv c;
 	int rv, value;
 
-	if (get_cpufv(&c))
+	if (get_cpufv(eeepc, &c))
 		return -ENODEV;
 	rv = parse_arg(buf, count, &value);
 	if (rv < 0)
 		return rv;
 	if (!rv || value < 0 || value >= c.num)
 		return -EINVAL;
-	set_acpi(CM_ASL_CPUFV, value);
+	set_acpi(eeepc, CM_ASL_CPUFV, value);
 	return rv;
 }
 
@@ -506,156 +417,125 @@
 	.attrs = platform_attributes
 };
 
-/*
- * Hotkey functions
- */
-static struct key_entry *eepc_get_entry_by_scancode(int code)
+static int eeepc_platform_init(struct eeepc_laptop *eeepc)
 {
-	struct key_entry *key;
-
-	for (key = eeepc_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *eepc_get_entry_by_keycode(int code)
-{
-	struct key_entry *key;
-
-	for (key = eeepc_keymap; key->type != KE_END; key++)
-		if (code == key->keycode && key->type == KE_KEY)
-			return key;
-
-	return NULL;
-}
-
-static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct key_entry *key = eepc_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = eepc_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!eepc_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static void cmsg_quirk(int cm, const char *name)
-{
-	int dummy;
-
-	/* Some BIOSes do not report cm although it is avaliable.
-	   Check if cm_getv[cm] works and, if yes, assume cm should be set. */
-	if (!(ehotk->cm_supported & (1 << cm))
-	    && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
-		pr_info("%s (%x) not reported by BIOS,"
-			" enabling anyway\n", name, 1 << cm);
-		ehotk->cm_supported |= 1 << cm;
-	}
-}
-
-static void cmsg_quirks(void)
-{
-	cmsg_quirk(CM_ASL_LID, "LID");
-	cmsg_quirk(CM_ASL_TYPE, "TYPE");
-	cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
-	cmsg_quirk(CM_ASL_TPD, "TPD");
-}
-
-static int eeepc_hotk_check(void)
-{
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	int result;
 
-	result = acpi_bus_get_status(ehotk->device);
+	eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
+	if (!eeepc->platform_device)
+		return -ENOMEM;
+	platform_set_drvdata(eeepc->platform_device, eeepc);
+
+	result = platform_device_add(eeepc->platform_device);
 	if (result)
-		return result;
-	if (ehotk->device->status.present) {
-		if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
-				    &buffer)) {
-			pr_err("Hotkey initialization failed\n");
-			return -ENODEV;
-		} else {
-			pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
-		}
-		/* get control methods supported */
-		if (read_acpi_int(ehotk->handle, "CMSG"
-				   , &ehotk->cm_supported)) {
-			pr_err("Get control methods supported failed\n");
-			return -ENODEV;
-		} else {
-			cmsg_quirks();
-			pr_info("Get control methods supported: 0x%x\n",
-				ehotk->cm_supported);
-		}
-	} else {
-		pr_err("Hotkey device not present, aborting\n");
-		return -EINVAL;
-	}
+		goto fail_platform_device;
+
+	result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
+				    &platform_attribute_group);
+	if (result)
+		goto fail_sysfs;
 	return 0;
+
+fail_sysfs:
+	platform_device_del(eeepc->platform_device);
+fail_platform_device:
+	platform_device_put(eeepc->platform_device);
+	return result;
 }
 
-static int notify_brn(void)
+static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
 {
-	/* returns the *previous* brightness, or -1 */
-	struct backlight_device *bd = eeepc_backlight_device;
-	if (bd) {
-		int old = bd->props.brightness;
-		backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
-		return old;
+	sysfs_remove_group(&eeepc->platform_device->dev.kobj,
+			   &platform_attribute_group);
+	platform_device_unregister(eeepc->platform_device);
+}
+
+/*
+ * LEDs
+ */
+/*
+ * These functions actually update the LED's, and are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
+static void tpd_led_update(struct work_struct *work)
+ {
+	struct eeepc_laptop *eeepc;
+
+	eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
+
+	set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
+}
+
+static void tpd_led_set(struct led_classdev *led_cdev,
+			enum led_brightness value)
+{
+	struct eeepc_laptop *eeepc;
+
+	eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
+
+	eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
+	queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
+}
+
+static int eeepc_led_init(struct eeepc_laptop *eeepc)
+{
+	int rv;
+
+	if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
+		return 0;
+
+	eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
+	if (!eeepc->led_workqueue)
+		return -ENOMEM;
+	INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
+
+	eeepc->tpd_led.name = "eeepc::touchpad";
+	eeepc->tpd_led.brightness_set = tpd_led_set;
+	eeepc->tpd_led.max_brightness = 1;
+
+	rv = led_classdev_register(&eeepc->platform_device->dev,
+				   &eeepc->tpd_led);
+	if (rv) {
+		destroy_workqueue(eeepc->led_workqueue);
+		return rv;
 	}
-	return -1;
-}
-
-static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
-				    u8 *value)
-{
-	int val = get_acpi(CM_ASL_WLAN);
-
-	if (val == 1 || val == 0)
-		*value = val;
-	else
-		return -EINVAL;
 
 	return 0;
 }
 
-static void eeepc_rfkill_hotplug(void)
+static void eeepc_led_exit(struct eeepc_laptop *eeepc)
+{
+	if (eeepc->tpd_led.dev)
+		led_classdev_unregister(&eeepc->tpd_led);
+	if (eeepc->led_workqueue)
+		destroy_workqueue(eeepc->led_workqueue);
+}
+
+
+/*
+ * PCI hotplug (for wlan rfkill)
+ */
+static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
+{
+	if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
+		return false;
+	return true;
+}
+
+static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
 {
 	struct pci_dev *dev;
 	struct pci_bus *bus;
-	bool blocked = eeepc_wlan_rfkill_blocked();
+	bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
 
-	if (ehotk->wlan_rfkill)
-		rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
+	if (eeepc->wlan_rfkill)
+		rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
 
-	mutex_lock(&ehotk->hotplug_lock);
+	mutex_lock(&eeepc->hotplug_lock);
 
-	if (ehotk->hotplug_slot) {
+	if (eeepc->hotplug_slot) {
 		bus = pci_find_bus(0, 1);
 		if (!bus) {
 			pr_warning("Unable to find PCI bus 1?\n");
@@ -685,69 +565,23 @@
 	}
 
 out_unlock:
-	mutex_unlock(&ehotk->hotplug_lock);
+	mutex_unlock(&eeepc->hotplug_lock);
 }
 
 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 {
+	struct eeepc_laptop *eeepc = data;
+
 	if (event != ACPI_NOTIFY_BUS_CHECK)
 		return;
 
-	eeepc_rfkill_hotplug();
+	eeepc_rfkill_hotplug(eeepc);
 }
 
-static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
+static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
+					  char *node)
 {
-	static struct key_entry *key;
-	u16 count;
-	int brn = -ENODEV;
-
-	if (!ehotk)
-		return;
-	if (event > ACPI_MAX_SYS_NOTIFY)
-		return;
-	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
-		brn = notify_brn();
-	count = ehotk->event_count[event % 128]++;
-	acpi_bus_generate_proc_event(ehotk->device, event, count);
-	acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
-					dev_name(&ehotk->device->dev), event,
-					count);
-	if (ehotk->inputdev) {
-		if (brn != -ENODEV) {
-			/* brightness-change events need special
-			 * handling for conversion to key events
-			 */
-			if (brn < 0)
-				brn = event;
-			else
-				brn += NOTIFY_BRN_MIN;
-			if (event < brn)
-				event = NOTIFY_BRN_MIN; /* brightness down */
-			else if (event > brn)
-				event = NOTIFY_BRN_MIN + 2; /* ... up */
-			else
-				event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
-		}
-		key = eepc_get_entry_by_scancode(event);
-		if (key) {
-			switch (key->type) {
-			case KE_KEY:
-				input_report_key(ehotk->inputdev, key->keycode,
-						 1);
-				input_sync(ehotk->inputdev);
-				input_report_key(ehotk->inputdev, key->keycode,
-						 0);
-				input_sync(ehotk->inputdev);
-				break;
-			}
-		}
-	}
-}
-
-static int eeepc_register_rfkill_notifier(char *node)
-{
-	acpi_status status = AE_OK;
+	acpi_status status;
 	acpi_handle handle;
 
 	status = acpi_get_handle(NULL, node, &handle);
@@ -756,7 +590,7 @@
 		status = acpi_install_notify_handler(handle,
 						     ACPI_SYSTEM_NOTIFY,
 						     eeepc_rfkill_notify,
-						     NULL);
+						     eeepc);
 		if (ACPI_FAILURE(status))
 			pr_warning("Failed to register notify on %s\n", node);
 	} else
@@ -765,7 +599,8 @@
 	return 0;
 }
 
-static void eeepc_unregister_rfkill_notifier(char *node)
+static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
+					     char *node)
 {
 	acpi_status status = AE_OK;
 	acpi_handle handle;
@@ -782,13 +617,33 @@
 	}
 }
 
+static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
+				    u8 *value)
+{
+	struct eeepc_laptop *eeepc = hotplug_slot->private;
+	int val = get_acpi(eeepc, CM_ASL_WLAN);
+
+	if (val == 1 || val == 0)
+		*value = val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
 {
 	kfree(hotplug_slot->info);
 	kfree(hotplug_slot);
 }
 
-static int eeepc_setup_pci_hotplug(void)
+static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
+	.owner = THIS_MODULE,
+	.get_adapter_status = eeepc_get_adapter_status,
+	.get_power_status = eeepc_get_adapter_status,
+};
+
+static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
 {
 	int ret = -ENOMEM;
 	struct pci_bus *bus = pci_find_bus(0, 1);
@@ -798,22 +653,22 @@
 		return -ENODEV;
 	}
 
-	ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
-	if (!ehotk->hotplug_slot)
+	eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+	if (!eeepc->hotplug_slot)
 		goto error_slot;
 
-	ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+	eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
 					    GFP_KERNEL);
-	if (!ehotk->hotplug_slot->info)
+	if (!eeepc->hotplug_slot->info)
 		goto error_info;
 
-	ehotk->hotplug_slot->private = ehotk;
-	ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
-	ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
-	eeepc_get_adapter_status(ehotk->hotplug_slot,
-				 &ehotk->hotplug_slot->info->adapter_status);
+	eeepc->hotplug_slot->private = eeepc;
+	eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
+	eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
+	eeepc_get_adapter_status(eeepc->hotplug_slot,
+				 &eeepc->hotplug_slot->info->adapter_status);
 
-	ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
+	ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
 	if (ret) {
 		pr_err("Unable to register hotplug slot - %d\n", ret);
 		goto error_register;
@@ -822,17 +677,156 @@
 	return 0;
 
 error_register:
-	kfree(ehotk->hotplug_slot->info);
+	kfree(eeepc->hotplug_slot->info);
 error_info:
-	kfree(ehotk->hotplug_slot);
-	ehotk->hotplug_slot = NULL;
+	kfree(eeepc->hotplug_slot);
+	eeepc->hotplug_slot = NULL;
 error_slot:
 	return ret;
 }
 
+/*
+ * Rfkill devices
+ */
+static int eeepc_rfkill_set(void *data, bool blocked)
+{
+	acpi_handle handle = data;
+
+	return write_acpi_int(handle, NULL, !blocked);
+}
+
+static const struct rfkill_ops eeepc_rfkill_ops = {
+	.set_block = eeepc_rfkill_set,
+};
+
+static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
+			    struct rfkill **rfkill,
+			    const char *name,
+			    enum rfkill_type type, int cm)
+{
+	acpi_handle handle;
+	int result;
+
+	result = acpi_setter_handle(eeepc, cm, &handle);
+	if (result < 0)
+		return result;
+
+	*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
+			       &eeepc_rfkill_ops, handle);
+
+	if (!*rfkill)
+		return -EINVAL;
+
+	rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
+	result = rfkill_register(*rfkill);
+	if (result) {
+		rfkill_destroy(*rfkill);
+		*rfkill = NULL;
+		return result;
+	}
+	return 0;
+}
+
+static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
+{
+	eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
+	eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
+	eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
+	if (eeepc->wlan_rfkill) {
+		rfkill_unregister(eeepc->wlan_rfkill);
+		rfkill_destroy(eeepc->wlan_rfkill);
+		eeepc->wlan_rfkill = NULL;
+	}
+	/*
+	 * Refresh pci hotplug in case the rfkill state was changed after
+	 * eeepc_unregister_rfkill_notifier()
+	 */
+	eeepc_rfkill_hotplug(eeepc);
+	if (eeepc->hotplug_slot)
+		pci_hp_deregister(eeepc->hotplug_slot);
+
+	if (eeepc->bluetooth_rfkill) {
+		rfkill_unregister(eeepc->bluetooth_rfkill);
+		rfkill_destroy(eeepc->bluetooth_rfkill);
+		eeepc->bluetooth_rfkill = NULL;
+	}
+	if (eeepc->wwan3g_rfkill) {
+		rfkill_unregister(eeepc->wwan3g_rfkill);
+		rfkill_destroy(eeepc->wwan3g_rfkill);
+		eeepc->wwan3g_rfkill = NULL;
+	}
+	if (eeepc->wimax_rfkill) {
+		rfkill_unregister(eeepc->wimax_rfkill);
+		rfkill_destroy(eeepc->wimax_rfkill);
+		eeepc->wimax_rfkill = NULL;
+	}
+}
+
+static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
+{
+	int result = 0;
+
+	mutex_init(&eeepc->hotplug_lock);
+
+	result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
+				  "eeepc-wlan", RFKILL_TYPE_WLAN,
+				  CM_ASL_WLAN);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
+				  "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
+				  CM_ASL_BLUETOOTH);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
+				  "eeepc-wwan3g", RFKILL_TYPE_WWAN,
+				  CM_ASL_3G);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
+				  "eeepc-wimax", RFKILL_TYPE_WIMAX,
+				  CM_ASL_WIMAX);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = eeepc_setup_pci_hotplug(eeepc);
+	/*
+	 * If we get -EBUSY then something else is handling the PCI hotplug -
+	 * don't fail in this case
+	 */
+	if (result == -EBUSY)
+		result = 0;
+
+	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
+	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
+	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
+	/*
+	 * Refresh pci hotplug in case the rfkill state was changed during
+	 * setup.
+	 */
+	eeepc_rfkill_hotplug(eeepc);
+
+exit:
+	if (result && result != -ENODEV)
+		eeepc_rfkill_exit(eeepc);
+	return result;
+}
+
+/*
+ * Platform driver - hibernate/resume callbacks
+ */
 static int eeepc_hotk_thaw(struct device *device)
 {
-	if (ehotk->wlan_rfkill) {
+	struct eeepc_laptop *eeepc = dev_get_drvdata(device);
+
+	if (eeepc->wlan_rfkill) {
 		bool wlan;
 
 		/*
@@ -840,8 +834,8 @@
 		 * during suspend.  Normally it restores it on resume, but
 		 * we should kick it ourselves in case hibernation is aborted.
 		 */
-		wlan = get_acpi(CM_ASL_WLAN);
-		set_acpi(CM_ASL_WLAN, wlan);
+		wlan = get_acpi(eeepc, CM_ASL_WLAN);
+		set_acpi(eeepc, CM_ASL_WLAN, wlan);
 	}
 
 	return 0;
@@ -849,70 +843,96 @@
 
 static int eeepc_hotk_restore(struct device *device)
 {
-	/* Refresh both wlan rfkill state and pci hotplug */
-	if (ehotk->wlan_rfkill)
-		eeepc_rfkill_hotplug();
+	struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 
-	if (ehotk->bluetooth_rfkill)
-		rfkill_set_sw_state(ehotk->bluetooth_rfkill,
-				    get_acpi(CM_ASL_BLUETOOTH) != 1);
-	if (ehotk->wwan3g_rfkill)
-		rfkill_set_sw_state(ehotk->wwan3g_rfkill,
-				    get_acpi(CM_ASL_3G) != 1);
-	if (ehotk->wimax_rfkill)
-		rfkill_set_sw_state(ehotk->wimax_rfkill,
-				    get_acpi(CM_ASL_WIMAX) != 1);
+	/* Refresh both wlan rfkill state and pci hotplug */
+	if (eeepc->wlan_rfkill)
+		eeepc_rfkill_hotplug(eeepc);
+
+	if (eeepc->bluetooth_rfkill)
+		rfkill_set_sw_state(eeepc->bluetooth_rfkill,
+				    get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
+	if (eeepc->wwan3g_rfkill)
+		rfkill_set_sw_state(eeepc->wwan3g_rfkill,
+				    get_acpi(eeepc, CM_ASL_3G) != 1);
+	if (eeepc->wimax_rfkill)
+		rfkill_set_sw_state(eeepc->wimax_rfkill,
+				    get_acpi(eeepc, CM_ASL_WIMAX) != 1);
 
 	return 0;
 }
 
+static const struct dev_pm_ops eeepc_pm_ops = {
+	.thaw = eeepc_hotk_thaw,
+	.restore = eeepc_hotk_restore,
+};
+
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = EEEPC_LAPTOP_FILE,
+		.owner = THIS_MODULE,
+		.pm = &eeepc_pm_ops,
+	}
+};
+
 /*
- * Hwmon
+ * Hwmon device
  */
+
+#define EEEPC_EC_SC00      0x61
+#define EEEPC_EC_FAN_PWM   (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
+#define EEEPC_EC_FAN_HRPM  (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
+#define EEEPC_EC_FAN_LRPM  (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
+
+#define EEEPC_EC_SFB0      0xD0
+#define EEEPC_EC_FAN_CTRL  (EEEPC_EC_SFB0 + 3) /* Byte containing SF25  */
+
 static int eeepc_get_fan_pwm(void)
 {
-	int value = 0;
+	u8 value = 0;
 
-	read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value);
-	value = value * 255 / 100;
-	return (value);
+	ec_read(EEEPC_EC_FAN_PWM, &value);
+	return value * 255 / 100;
 }
 
 static void eeepc_set_fan_pwm(int value)
 {
 	value = SENSORS_LIMIT(value, 0, 255);
 	value = value * 100 / 255;
-	ec_write(EEEPC_EC_SC02, value);
+	ec_write(EEEPC_EC_FAN_PWM, value);
 }
 
 static int eeepc_get_fan_rpm(void)
 {
-	int high = 0;
-	int low = 0;
+	u8 high = 0;
+	u8 low = 0;
 
-	read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high);
-	read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low);
-	return (high << 8 | low);
+	ec_read(EEEPC_EC_FAN_HRPM, &high);
+	ec_read(EEEPC_EC_FAN_LRPM, &low);
+	return high << 8 | low;
 }
 
 static int eeepc_get_fan_ctrl(void)
 {
-	int value = 0;
+	u8 value = 0;
 
-	read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
-	return ((value & 0x02 ? 1 : 0));
+	ec_read(EEEPC_EC_FAN_CTRL, &value);
+	if (value & 0x02)
+		return 1; /* manual */
+	else
+		return 2; /* automatic */
 }
 
 static void eeepc_set_fan_ctrl(int manual)
 {
-	int value = 0;
+	u8 value = 0;
 
-	read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value);
-	if (manual)
+	ec_read(EEEPC_EC_FAN_CTRL, &value);
+	if (manual == 1)
 		value |= 0x02;
 	else
 		value &= ~0x02;
-	ec_write(EEEPC_EC_SFB3, value);
+	ec_write(EEEPC_EC_FAN_CTRL, value);
 }
 
 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
@@ -970,348 +990,485 @@
 	.attrs = hwmon_attributes
 };
 
-/*
- * exit/init
- */
-static void eeepc_backlight_exit(void)
-{
-	if (eeepc_backlight_device)
-		backlight_device_unregister(eeepc_backlight_device);
-	eeepc_backlight_device = NULL;
-}
-
-static void eeepc_rfkill_exit(void)
-{
-	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5");
-	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
-	eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
-	if (ehotk->wlan_rfkill) {
-		rfkill_unregister(ehotk->wlan_rfkill);
-		rfkill_destroy(ehotk->wlan_rfkill);
-		ehotk->wlan_rfkill = NULL;
-	}
-	/*
-	 * Refresh pci hotplug in case the rfkill state was changed after
-	 * eeepc_unregister_rfkill_notifier()
-	 */
-	eeepc_rfkill_hotplug();
-	if (ehotk->hotplug_slot)
-		pci_hp_deregister(ehotk->hotplug_slot);
-
-	if (ehotk->bluetooth_rfkill) {
-		rfkill_unregister(ehotk->bluetooth_rfkill);
-		rfkill_destroy(ehotk->bluetooth_rfkill);
-		ehotk->bluetooth_rfkill = NULL;
-	}
-	if (ehotk->wwan3g_rfkill) {
-		rfkill_unregister(ehotk->wwan3g_rfkill);
-		rfkill_destroy(ehotk->wwan3g_rfkill);
-		ehotk->wwan3g_rfkill = NULL;
-	}
-	if (ehotk->wimax_rfkill) {
-		rfkill_unregister(ehotk->wimax_rfkill);
-		rfkill_destroy(ehotk->wimax_rfkill);
-		ehotk->wimax_rfkill = NULL;
-	}
-}
-
-static void eeepc_input_exit(void)
-{
-	if (ehotk->inputdev)
-		input_unregister_device(ehotk->inputdev);
-}
-
-static void eeepc_hwmon_exit(void)
+static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc)
 {
 	struct device *hwmon;
 
-	hwmon = eeepc_hwmon_device;
+	hwmon = eeepc->hwmon_device;
 	if (!hwmon)
-		return ;
+		return;
 	sysfs_remove_group(&hwmon->kobj,
 			   &hwmon_attribute_group);
 	hwmon_device_unregister(hwmon);
-	eeepc_hwmon_device = NULL;
+	eeepc->hwmon_device = NULL;
 }
 
-static int eeepc_new_rfkill(struct rfkill **rfkill,
-			    const char *name, struct device *dev,
-			    enum rfkill_type type, int cm)
+static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
 {
+	struct device *hwmon;
 	int result;
 
-	result = get_acpi(cm);
-	if (result < 0)
-		return result;
-
-	*rfkill = rfkill_alloc(name, dev, type,
-			       &eeepc_rfkill_ops, (void *)(unsigned long)cm);
-
-	if (!*rfkill)
-		return -EINVAL;
-
-	rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
-	result = rfkill_register(*rfkill);
-	if (result) {
-		rfkill_destroy(*rfkill);
-		*rfkill = NULL;
-		return result;
+	hwmon = hwmon_device_register(&eeepc->platform_device->dev);
+	if (IS_ERR(hwmon)) {
+		pr_err("Could not register eeepc hwmon device\n");
+		eeepc->hwmon_device = NULL;
+		return PTR_ERR(hwmon);
 	}
-	return 0;
-}
-
-
-static int eeepc_rfkill_init(struct device *dev)
-{
-	int result = 0;
-
-	mutex_init(&ehotk->hotplug_lock);
-
-	result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
-				  "eeepc-wlan", dev,
-				  RFKILL_TYPE_WLAN, CM_ASL_WLAN);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
-				  "eeepc-bluetooth", dev,
-				  RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
-				  "eeepc-wwan3g", dev,
-				  RFKILL_TYPE_WWAN, CM_ASL_3G);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_new_rfkill(&ehotk->wimax_rfkill,
-				  "eeepc-wimax", dev,
-				  RFKILL_TYPE_WIMAX, CM_ASL_WIMAX);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_setup_pci_hotplug();
-	/*
-	 * If we get -EBUSY then something else is handling the PCI hotplug -
-	 * don't fail in this case
-	 */
-	if (result == -EBUSY)
-		result = 0;
-
-	eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5");
-	eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
-	eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
-	/*
-	 * Refresh pci hotplug in case the rfkill state was changed during
-	 * setup.
-	 */
-	eeepc_rfkill_hotplug();
-
-exit:
-	if (result && result != -ENODEV)
-		eeepc_rfkill_exit();
+	eeepc->hwmon_device = hwmon;
+	result = sysfs_create_group(&hwmon->kobj,
+				    &hwmon_attribute_group);
+	if (result)
+		eeepc_hwmon_exit(eeepc);
 	return result;
 }
 
-static int eeepc_backlight_init(struct device *dev)
+/*
+ * Backlight device
+ */
+static int read_brightness(struct backlight_device *bd)
+{
+	struct eeepc_laptop *eeepc = bl_get_data(bd);
+
+	return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
+}
+
+static int set_brightness(struct backlight_device *bd, int value)
+{
+	struct eeepc_laptop *eeepc = bl_get_data(bd);
+
+	return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+	return set_brightness(bd, bd->props.brightness);
+}
+
+static struct backlight_ops eeepcbl_ops = {
+	.get_brightness = read_brightness,
+	.update_status = update_bl_status,
+};
+
+static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
+{
+	struct backlight_device *bd = eeepc->backlight_device;
+	int old = bd->props.brightness;
+
+	backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
+
+	return old;
+}
+
+static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
 {
 	struct backlight_device *bd;
 
-	bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
-				       NULL, &eeepcbl_ops);
+	bd = backlight_device_register(EEEPC_LAPTOP_FILE,
+				       &eeepc->platform_device->dev,
+				       eeepc, &eeepcbl_ops);
 	if (IS_ERR(bd)) {
 		pr_err("Could not register eeepc backlight device\n");
-		eeepc_backlight_device = NULL;
+		eeepc->backlight_device = NULL;
 		return PTR_ERR(bd);
 	}
-	eeepc_backlight_device = bd;
+	eeepc->backlight_device = bd;
 	bd->props.max_brightness = 15;
-	bd->props.brightness = read_brightness(NULL);
+	bd->props.brightness = read_brightness(bd);
 	bd->props.power = FB_BLANK_UNBLANK;
 	backlight_update_status(bd);
 	return 0;
 }
 
-static int eeepc_hwmon_init(struct device *dev)
+static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
 {
-	struct device *hwmon;
-	int result;
-
-	hwmon = hwmon_device_register(dev);
-	if (IS_ERR(hwmon)) {
-		pr_err("Could not register eeepc hwmon device\n");
-		eeepc_hwmon_device = NULL;
-		return PTR_ERR(hwmon);
-	}
-	eeepc_hwmon_device = hwmon;
-	result = sysfs_create_group(&hwmon->kobj,
-				    &hwmon_attribute_group);
-	if (result)
-		eeepc_hwmon_exit();
-	return result;
+	if (eeepc->backlight_device)
+		backlight_device_unregister(eeepc->backlight_device);
+	eeepc->backlight_device = NULL;
 }
 
-static int eeepc_input_init(struct device *dev)
+
+/*
+ * Input device (i.e. hotkeys)
+ */
+static struct key_entry *eeepc_get_entry_by_scancode(
+	struct eeepc_laptop *eeepc,
+	int code)
+{
+	struct key_entry *key;
+
+	for (key = eeepc->keymap; key->type != KE_END; key++)
+		if (code == key->code)
+			return key;
+
+	return NULL;
+}
+
+static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
+{
+	static struct key_entry *key;
+
+	key = eeepc_get_entry_by_scancode(eeepc, event);
+	if (key) {
+		switch (key->type) {
+		case KE_KEY:
+			input_report_key(eeepc->inputdev, key->keycode,
+						1);
+			input_sync(eeepc->inputdev);
+			input_report_key(eeepc->inputdev, key->keycode,
+						0);
+			input_sync(eeepc->inputdev);
+			break;
+		}
+	}
+}
+
+static struct key_entry *eeepc_get_entry_by_keycode(
+	struct eeepc_laptop *eeepc, int code)
+{
+	struct key_entry *key;
+
+	for (key = eeepc->keymap; key->type != KE_END; key++)
+		if (code == key->keycode && key->type == KE_KEY)
+			return key;
+
+	return NULL;
+}
+
+static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+	struct eeepc_laptop *eeepc = input_get_drvdata(dev);
+	struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+	struct eeepc_laptop *eeepc = input_get_drvdata(dev);
+	struct key_entry *key;
+	int old_keycode;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	key = eeepc_get_entry_by_scancode(eeepc, scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int eeepc_input_init(struct eeepc_laptop *eeepc)
 {
 	const struct key_entry *key;
 	int result;
 
-	ehotk->inputdev = input_allocate_device();
-	if (!ehotk->inputdev) {
+	eeepc->inputdev = input_allocate_device();
+	if (!eeepc->inputdev) {
 		pr_info("Unable to allocate input device\n");
 		return -ENOMEM;
 	}
-	ehotk->inputdev->name = "Asus EeePC extra buttons";
-	ehotk->inputdev->dev.parent = dev;
-	ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
-	ehotk->inputdev->id.bustype = BUS_HOST;
-	ehotk->inputdev->getkeycode = eeepc_getkeycode;
-	ehotk->inputdev->setkeycode = eeepc_setkeycode;
+	eeepc->inputdev->name = "Asus EeePC extra buttons";
+	eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
+	eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
+	eeepc->inputdev->id.bustype = BUS_HOST;
+	eeepc->inputdev->getkeycode = eeepc_getkeycode;
+	eeepc->inputdev->setkeycode = eeepc_setkeycode;
+	input_set_drvdata(eeepc->inputdev, eeepc);
 
+	eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
+				GFP_KERNEL);
 	for (key = eeepc_keymap; key->type != KE_END; key++) {
 		switch (key->type) {
 		case KE_KEY:
-			set_bit(EV_KEY, ehotk->inputdev->evbit);
-			set_bit(key->keycode, ehotk->inputdev->keybit);
+			set_bit(EV_KEY, eeepc->inputdev->evbit);
+			set_bit(key->keycode, eeepc->inputdev->keybit);
 			break;
 		}
 	}
-	result = input_register_device(ehotk->inputdev);
+	result = input_register_device(eeepc->inputdev);
 	if (result) {
 		pr_info("Unable to register input device\n");
-		input_free_device(ehotk->inputdev);
+		input_free_device(eeepc->inputdev);
 		return result;
 	}
 	return 0;
 }
 
-static int __devinit eeepc_hotk_add(struct acpi_device *device)
+static void eeepc_input_exit(struct eeepc_laptop *eeepc)
 {
-	struct device *dev;
+	if (eeepc->inputdev) {
+		input_unregister_device(eeepc->inputdev);
+		kfree(eeepc->keymap);
+	}
+}
+
+/*
+ * ACPI driver
+ */
+static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
+{
+	struct eeepc_laptop *eeepc = acpi_driver_data(device);
+	u16 count;
+
+	if (event > ACPI_MAX_SYS_NOTIFY)
+		return;
+	count = eeepc->event_count[event % 128]++;
+	acpi_bus_generate_proc_event(device, event, count);
+	acpi_bus_generate_netlink_event(device->pnp.device_class,
+					dev_name(&device->dev), event,
+					count);
+
+	/* Brightness events are special */
+	if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
+
+		/* Ignore them completely if the acpi video driver is used */
+		if (eeepc->backlight_device != NULL) {
+			int old_brightness, new_brightness;
+
+			/* Update the backlight device. */
+			old_brightness = eeepc_backlight_notify(eeepc);
+
+			/* Convert event to keypress (obsolescent hack) */
+			new_brightness = event - NOTIFY_BRN_MIN;
+
+			if (new_brightness < old_brightness) {
+				event = NOTIFY_BRN_MIN; /* brightness down */
+			} else if (new_brightness > old_brightness) {
+				event = NOTIFY_BRN_MAX; /* brightness up */
+			} else {
+				/*
+				* no change in brightness - already at min/max,
+				* event will be desired value (or else ignored)
+				*/
+			}
+			eeepc_input_notify(eeepc, event);
+		}
+	} else {
+		/* Everything else is a bona-fide keypress event */
+		eeepc_input_notify(eeepc, event);
+	}
+}
+
+static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
+{
+	int dummy;
+
+	/* Some BIOSes do not report cm although it is avaliable.
+	   Check if cm_getv[cm] works and, if yes, assume cm should be set. */
+	if (!(eeepc->cm_supported & (1 << cm))
+	    && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
+		pr_info("%s (%x) not reported by BIOS,"
+			" enabling anyway\n", name, 1 << cm);
+		eeepc->cm_supported |= 1 << cm;
+	}
+}
+
+static void cmsg_quirks(struct eeepc_laptop *eeepc)
+{
+	cmsg_quirk(eeepc, CM_ASL_LID, "LID");
+	cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
+	cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
+	cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
+}
+
+static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
+			   struct acpi_device *device)
+{
+	unsigned int init_flags;
 	int result;
 
-	if (!device)
-		return -EINVAL;
-	pr_notice(EEEPC_HOTK_NAME "\n");
-	ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
-	if (!ehotk)
-		return -ENOMEM;
-	ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
-	ehotk->handle = device->handle;
-	strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
-	strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
-	device->driver_data = ehotk;
-	ehotk->device = device;
-
-	result = eeepc_hotk_check();
+	result = acpi_bus_get_status(device);
 	if (result)
-		goto fail_platform_driver;
-	eeepc_enable_camera();
-
-	/* Register platform stuff */
-	result = platform_driver_register(&platform_driver);
-	if (result)
-		goto fail_platform_driver;
-	platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1);
-	if (!platform_device) {
-		result = -ENOMEM;
-		goto fail_platform_device1;
+		return result;
+	if (!device->status.present) {
+		pr_err("Hotkey device not present, aborting\n");
+		return -ENODEV;
 	}
-	result = platform_device_add(platform_device);
-	if (result)
-		goto fail_platform_device2;
-	result = sysfs_create_group(&platform_device->dev.kobj,
-				    &platform_attribute_group);
-	if (result)
-		goto fail_sysfs;
 
-	dev = &platform_device->dev;
+	init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
+	pr_notice("Hotkey init flags 0x%x\n", init_flags);
+
+	if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
+		pr_err("Hotkey initialization failed\n");
+		return -ENODEV;
+	}
+
+	/* get control methods supported */
+	if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
+		pr_err("Get control methods supported failed\n");
+		return -ENODEV;
+	}
+	cmsg_quirks(eeepc);
+	pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
+
+	return 0;
+}
+
+static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
+{
+	/*
+	 * If the following call to set_acpi() fails, it's because there's no
+	 * camera so we can ignore the error.
+	 */
+	if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
+		set_acpi(eeepc, CM_ASL_CAMERA, 1);
+}
+
+static bool eeepc_device_present;
+
+static int __devinit eeepc_acpi_add(struct acpi_device *device)
+{
+	struct eeepc_laptop *eeepc;
+	int result;
+
+	pr_notice(EEEPC_LAPTOP_NAME "\n");
+	eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
+	if (!eeepc)
+		return -ENOMEM;
+	eeepc->handle = device->handle;
+	strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
+	strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
+	device->driver_data = eeepc;
+
+	result = eeepc_acpi_init(eeepc, device);
+	if (result)
+		goto fail_platform;
+	eeepc_enable_camera(eeepc);
+
+	/*
+	 * Register the platform device first.  It is used as a parent for the
+	 * sub-devices below.
+	 *
+	 * Note that if there are multiple instances of this ACPI device it
+	 * will bail out, because the platform device is registered with a
+	 * fixed name.  Of course it doesn't make sense to have more than one,
+	 * and machine-specific scripts find the fixed name convenient.  But
+	 * It's also good for us to exclude multiple instances because both
+	 * our hwmon and our wlan rfkill subdevice use global ACPI objects
+	 * (the EC and the wlan PCI slot respectively).
+	 */
+	result = eeepc_platform_init(eeepc);
+	if (result)
+		goto fail_platform;
 
 	if (!acpi_video_backlight_support()) {
-		result = eeepc_backlight_init(dev);
+		result = eeepc_backlight_init(eeepc);
 		if (result)
 			goto fail_backlight;
 	} else
-		pr_info("Backlight controlled by ACPI video "
-			"driver\n");
+		pr_info("Backlight controlled by ACPI video driver\n");
 
-	result = eeepc_input_init(dev);
+	result = eeepc_input_init(eeepc);
 	if (result)
 		goto fail_input;
 
-	result = eeepc_hwmon_init(dev);
+	result = eeepc_hwmon_init(eeepc);
 	if (result)
 		goto fail_hwmon;
 
-	result = eeepc_rfkill_init(dev);
+	result = eeepc_led_init(eeepc);
+	if (result)
+		goto fail_led;
+
+	result = eeepc_rfkill_init(eeepc);
 	if (result)
 		goto fail_rfkill;
 
+	eeepc_device_present = true;
 	return 0;
 
 fail_rfkill:
-	eeepc_hwmon_exit();
+	eeepc_led_exit(eeepc);
+fail_led:
+	eeepc_hwmon_exit(eeepc);
 fail_hwmon:
-	eeepc_input_exit();
+	eeepc_input_exit(eeepc);
 fail_input:
-	eeepc_backlight_exit();
+	eeepc_backlight_exit(eeepc);
 fail_backlight:
-	sysfs_remove_group(&platform_device->dev.kobj,
-			   &platform_attribute_group);
-fail_sysfs:
-	platform_device_del(platform_device);
-fail_platform_device2:
-	platform_device_put(platform_device);
-fail_platform_device1:
-	platform_driver_unregister(&platform_driver);
-fail_platform_driver:
-	kfree(ehotk);
+	eeepc_platform_exit(eeepc);
+fail_platform:
+	kfree(eeepc);
 
 	return result;
 }
 
-static int eeepc_hotk_remove(struct acpi_device *device, int type)
+static int eeepc_acpi_remove(struct acpi_device *device, int type)
 {
-	if (!device || !acpi_driver_data(device))
-		return -EINVAL;
+	struct eeepc_laptop *eeepc = acpi_driver_data(device);
 
-	eeepc_backlight_exit();
-	eeepc_rfkill_exit();
-	eeepc_input_exit();
-	eeepc_hwmon_exit();
-	sysfs_remove_group(&platform_device->dev.kobj,
-			   &platform_attribute_group);
-	platform_device_unregister(platform_device);
-	platform_driver_unregister(&platform_driver);
+	eeepc_backlight_exit(eeepc);
+	eeepc_rfkill_exit(eeepc);
+	eeepc_input_exit(eeepc);
+	eeepc_hwmon_exit(eeepc);
+	eeepc_led_exit(eeepc);
+	eeepc_platform_exit(eeepc);
 
-	kfree(ehotk);
+	kfree(eeepc);
 	return 0;
 }
 
+
+static const struct acpi_device_id eeepc_device_ids[] = {
+	{EEEPC_ACPI_HID, 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
+
+static struct acpi_driver eeepc_acpi_driver = {
+	.name = EEEPC_LAPTOP_NAME,
+	.class = EEEPC_ACPI_CLASS,
+	.owner = THIS_MODULE,
+	.ids = eeepc_device_ids,
+	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
+	.ops = {
+		.add = eeepc_acpi_add,
+		.remove = eeepc_acpi_remove,
+		.notify = eeepc_acpi_notify,
+	},
+};
+
+
 static int __init eeepc_laptop_init(void)
 {
 	int result;
 
-	if (acpi_disabled)
-		return -ENODEV;
-	result = acpi_bus_register_driver(&eeepc_hotk_driver);
+	result = platform_driver_register(&platform_driver);
 	if (result < 0)
 		return result;
-	if (!ehotk) {
-		acpi_bus_unregister_driver(&eeepc_hotk_driver);
-		return -ENODEV;
+
+	result = acpi_bus_register_driver(&eeepc_acpi_driver);
+	if (result < 0)
+		goto fail_acpi_driver;
+	if (!eeepc_device_present) {
+		result = -ENODEV;
+		goto fail_no_device;
 	}
 	return 0;
+
+fail_no_device:
+	acpi_bus_unregister_driver(&eeepc_acpi_driver);
+fail_acpi_driver:
+	platform_driver_unregister(&platform_driver);
+	return result;
 }
 
 static void __exit eeepc_laptop_exit(void)
 {
-	acpi_bus_unregister_driver(&eeepc_hotk_driver);
+	acpi_bus_unregister_driver(&eeepc_acpi_driver);
+	platform_driver_unregister(&platform_driver);
 }
 
 module_init(eeepc_laptop_init);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index f00a71c..63c3e65 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -51,6 +51,12 @@
 #define HPWMI_WIRELESS_QUERY 0x5
 #define HPWMI_HOTKEY_QUERY 0xc
 
+enum hp_wmi_radio {
+	HPWMI_WIFI = 0,
+	HPWMI_BLUETOOTH = 1,
+	HPWMI_WWAN = 2,
+};
+
 static int __init hp_wmi_bios_setup(struct platform_device *device);
 static int __exit hp_wmi_bios_remove(struct platform_device *device);
 static int hp_wmi_resume_handler(struct device *device);
@@ -175,8 +181,8 @@
 
 static int hp_wmi_set_block(void *data, bool blocked)
 {
-	unsigned long b = (unsigned long) data;
-	int query = BIT(b + 8) | ((!blocked) << b);
+	enum hp_wmi_radio r = (enum hp_wmi_radio) data;
+	int query = BIT(r + 8) | ((!blocked) << r);
 
 	return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
 }
@@ -185,31 +191,23 @@
 	.set_block = hp_wmi_set_block,
 };
 
-static bool hp_wmi_wifi_state(void)
+static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
 {
 	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+	int mask = 0x200 << (r * 8);
 
-	if (wireless & 0x100)
+	if (wireless & mask)
 		return false;
 	else
 		return true;
 }
 
-static bool hp_wmi_bluetooth_state(void)
+static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
 {
 	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+	int mask = 0x800 << (r * 8);
 
-	if (wireless & 0x10000)
-		return false;
-	else
-		return true;
-}
-
-static bool hp_wmi_wwan_state(void)
-{
-	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
-
-	if (wireless & 0x1000000)
+	if (wireless & mask)
 		return false;
 	else
 		return true;
@@ -334,49 +332,55 @@
 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
 	static struct key_entry *key;
 	union acpi_object *obj;
+	int eventcode;
 
 	wmi_get_event_data(value, &response);
 
 	obj = (union acpi_object *)response.pointer;
 
-	if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
-		int eventcode = *((u8 *) obj->buffer.pointer);
-		if (eventcode == 0x4)
-			eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
-							 0);
-		key = hp_wmi_get_entry_by_scancode(eventcode);
-		if (key) {
-			switch (key->type) {
-			case KE_KEY:
-				input_report_key(hp_wmi_input_dev,
-						 key->keycode, 1);
-				input_sync(hp_wmi_input_dev);
-				input_report_key(hp_wmi_input_dev,
-						 key->keycode, 0);
-				input_sync(hp_wmi_input_dev);
-				break;
-			}
-		} else if (eventcode == 0x1) {
-			input_report_switch(hp_wmi_input_dev, SW_DOCK,
-					    hp_wmi_dock_state());
-			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
-					    hp_wmi_tablet_state());
-			input_sync(hp_wmi_input_dev);
-		} else if (eventcode == 0x5) {
-			if (wifi_rfkill)
-				rfkill_set_sw_state(wifi_rfkill,
-						    hp_wmi_wifi_state());
-			if (bluetooth_rfkill)
-				rfkill_set_sw_state(bluetooth_rfkill,
-						    hp_wmi_bluetooth_state());
-			if (wwan_rfkill)
-				rfkill_set_sw_state(wwan_rfkill,
-						    hp_wmi_wwan_state());
-		} else
-			printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
-			       eventcode);
-	} else
+	if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
 		printk(KERN_INFO "HP WMI: Unknown response received\n");
+		return;
+	}
+
+	eventcode = *((u8 *) obj->buffer.pointer);
+	if (eventcode == 0x4)
+		eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
+						0);
+	key = hp_wmi_get_entry_by_scancode(eventcode);
+	if (key) {
+		switch (key->type) {
+		case KE_KEY:
+			input_report_key(hp_wmi_input_dev,
+					 key->keycode, 1);
+			input_sync(hp_wmi_input_dev);
+			input_report_key(hp_wmi_input_dev,
+					 key->keycode, 0);
+			input_sync(hp_wmi_input_dev);
+			break;
+		}
+	} else if (eventcode == 0x1) {
+		input_report_switch(hp_wmi_input_dev, SW_DOCK,
+				    hp_wmi_dock_state());
+		input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
+				    hp_wmi_tablet_state());
+		input_sync(hp_wmi_input_dev);
+	} else if (eventcode == 0x5) {
+		if (wifi_rfkill)
+			rfkill_set_states(wifi_rfkill,
+					  hp_wmi_get_sw_state(HPWMI_WIFI),
+					  hp_wmi_get_hw_state(HPWMI_WIFI));
+		if (bluetooth_rfkill)
+			rfkill_set_states(bluetooth_rfkill,
+					  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
+					  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
+		if (wwan_rfkill)
+			rfkill_set_states(wwan_rfkill,
+					  hp_wmi_get_sw_state(HPWMI_WWAN),
+					  hp_wmi_get_hw_state(HPWMI_WWAN));
+	} else
+		printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
+			eventcode);
 }
 
 static int __init hp_wmi_input_setup(void)
@@ -455,7 +459,11 @@
 		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
 					   RFKILL_TYPE_WLAN,
 					   &hp_wmi_rfkill_ops,
-					   (void *) 0);
+					   (void *) HPWMI_WIFI);
+		rfkill_init_sw_state(wifi_rfkill,
+				     hp_wmi_get_sw_state(HPWMI_WIFI));
+		rfkill_set_hw_state(wifi_rfkill,
+				    hp_wmi_get_hw_state(HPWMI_WIFI));
 		err = rfkill_register(wifi_rfkill);
 		if (err)
 			goto register_wifi_error;
@@ -465,7 +473,11 @@
 		bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
 						RFKILL_TYPE_BLUETOOTH,
 						&hp_wmi_rfkill_ops,
-						(void *) 1);
+						(void *) HPWMI_BLUETOOTH);
+		rfkill_init_sw_state(bluetooth_rfkill,
+				     hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
+		rfkill_set_hw_state(bluetooth_rfkill,
+				    hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
 		err = rfkill_register(bluetooth_rfkill);
 		if (err)
 			goto register_bluetooth_error;
@@ -475,7 +487,11 @@
 		wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
 					   RFKILL_TYPE_WWAN,
 					   &hp_wmi_rfkill_ops,
-					   (void *) 2);
+					   (void *) HPWMI_WWAN);
+		rfkill_init_sw_state(wwan_rfkill,
+				     hp_wmi_get_sw_state(HPWMI_WWAN));
+		rfkill_set_hw_state(wwan_rfkill,
+				    hp_wmi_get_hw_state(HPWMI_WWAN));
 		err = rfkill_register(wwan_rfkill);
 		if (err)
 			goto register_wwan_err;
@@ -533,6 +549,19 @@
 		input_sync(hp_wmi_input_dev);
 	}
 
+	if (wifi_rfkill)
+		rfkill_set_states(wifi_rfkill,
+				  hp_wmi_get_sw_state(HPWMI_WIFI),
+				  hp_wmi_get_hw_state(HPWMI_WIFI));
+	if (bluetooth_rfkill)
+		rfkill_set_states(bluetooth_rfkill,
+				  hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
+				  hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
+	if (wwan_rfkill)
+		rfkill_set_states(wwan_rfkill,
+				  hp_wmi_get_sw_state(HPWMI_WWAN),
+				  hp_wmi_get_hw_state(HPWMI_WWAN));
+
 	return 0;
 }
 
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
new file mode 100644
index 0000000..0c8fe14
--- /dev/null
+++ b/drivers/platform/x86/msi-wmi.c
@@ -0,0 +1,293 @@
+/*
+ * MSI WMI hotkeys
+ *
+ * Copyright (C) 2009 Novell <trenn@suse.de>
+ *
+ * Most stuff taken over from hp-wmi
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/acpi.h>
+#include <linux/backlight.h>
+
+MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
+MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver");
+MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
+MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
+
+/* Temporary workaround until the WMI sysfs interface goes in
+		{ "svn", DMI_SYS_VENDOR },
+		{ "pn",  DMI_PRODUCT_NAME },
+		{ "pvr", DMI_PRODUCT_VERSION },
+		{ "rvn", DMI_BOARD_VENDOR },
+		{ "rn",  DMI_BOARD_NAME },
+*/
+
+MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*");
+
+#define DRV_NAME "msi-wmi"
+#define DRV_PFX DRV_NAME ": "
+
+#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
+#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
+
+#define dprintk(msg...) pr_debug(DRV_PFX msg)
+
+#define KEYCODE_BASE 0xD0
+#define MSI_WMI_BRIGHTNESSUP   KEYCODE_BASE
+#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
+#define MSI_WMI_VOLUMEUP       (KEYCODE_BASE + 2)
+#define MSI_WMI_VOLUMEDOWN     (KEYCODE_BASE + 3)
+static struct key_entry msi_wmi_keymap[] = {
+	{ KE_KEY, MSI_WMI_BRIGHTNESSUP,   {KEY_BRIGHTNESSUP} },
+	{ KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
+	{ KE_KEY, MSI_WMI_VOLUMEUP,       {KEY_VOLUMEUP} },
+	{ KE_KEY, MSI_WMI_VOLUMEDOWN,     {KEY_VOLUMEDOWN} },
+	{ KE_END, 0}
+};
+static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
+
+struct backlight_device *backlight;
+
+static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
+
+static struct input_dev *msi_wmi_input_dev;
+
+static int msi_wmi_query_block(int instance, int *ret)
+{
+	acpi_status status;
+	union acpi_object *obj;
+
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	status = wmi_query_block(MSIWMI_BIOS_GUID, instance, &output);
+
+	obj = output.pointer;
+
+	if (!obj || obj->type != ACPI_TYPE_INTEGER) {
+		if (obj) {
+			printk(KERN_ERR DRV_PFX "query block returned object "
+			       "type: %d - buffer length:%d\n", obj->type,
+			       obj->type == ACPI_TYPE_BUFFER ?
+			       obj->buffer.length : 0);
+		}
+		kfree(obj);
+		return -EINVAL;
+	}
+	*ret = obj->integer.value;
+	kfree(obj);
+	return 0;
+}
+
+static int msi_wmi_set_block(int instance, int value)
+{
+	acpi_status status;
+
+	struct acpi_buffer input = { sizeof(int), &value };
+
+	dprintk("Going to set block of instance: %d - value: %d\n",
+		instance, value);
+
+	status = wmi_set_block(MSIWMI_BIOS_GUID, instance, &input);
+
+	return ACPI_SUCCESS(status) ? 0 : 1;
+}
+
+static int bl_get(struct backlight_device *bd)
+{
+	int level, err, ret;
+
+	/* Instance 1 is "get backlight", cmp with DSDT */
+	err = msi_wmi_query_block(1, &ret);
+	if (err) {
+		printk(KERN_ERR DRV_PFX "Could not query backlight: %d\n", err);
+		return -EINVAL;
+	}
+	dprintk("Get: Query block returned: %d\n", ret);
+	for (level = 0; level < ARRAY_SIZE(backlight_map); level++) {
+		if (backlight_map[level] == ret) {
+			dprintk("Current backlight level: 0x%X - index: %d\n",
+				backlight_map[level], level);
+			break;
+		}
+	}
+	if (level == ARRAY_SIZE(backlight_map)) {
+		printk(KERN_ERR DRV_PFX "get: Invalid brightness value: 0x%X\n",
+		       ret);
+		return -EINVAL;
+	}
+	return level;
+}
+
+static int bl_set_status(struct backlight_device *bd)
+{
+	int bright = bd->props.brightness;
+	if (bright >= ARRAY_SIZE(backlight_map) || bright < 0)
+		return -EINVAL;
+
+	/* Instance 0 is "set backlight" */
+	return msi_wmi_set_block(0, backlight_map[bright]);
+}
+
+static struct backlight_ops msi_backlight_ops = {
+	.get_brightness	= bl_get,
+	.update_status	= bl_set_status,
+};
+
+static void msi_wmi_notify(u32 value, void *context)
+{
+	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+	static struct key_entry *key;
+	union acpi_object *obj;
+	ktime_t cur;
+
+	wmi_get_event_data(value, &response);
+
+	obj = (union acpi_object *)response.pointer;
+
+	if (obj && obj->type == ACPI_TYPE_INTEGER) {
+		int eventcode = obj->integer.value;
+		dprintk("Eventcode: 0x%x\n", eventcode);
+		key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
+				eventcode);
+		if (key) {
+			ktime_t diff;
+			cur = ktime_get_real();
+			diff = ktime_sub(cur, last_pressed[key->code -
+					KEYCODE_BASE]);
+			/* Ignore event if the same event happened in a 50 ms
+			   timeframe -> Key press may result in 10-20 GPEs */
+			if (ktime_to_us(diff) < 1000 * 50) {
+				dprintk("Suppressed key event 0x%X - "
+					"Last press was %lld us ago\n",
+					 key->code, ktime_to_us(diff));
+				return;
+			}
+			last_pressed[key->code - KEYCODE_BASE] = cur;
+
+			if (key->type == KE_KEY &&
+			/* Brightness is served via acpi video driver */
+			(!acpi_video_backlight_support() ||
+			(key->code != MSI_WMI_BRIGHTNESSUP &&
+			key->code != MSI_WMI_BRIGHTNESSDOWN))) {
+				dprintk("Send key: 0x%X - "
+					"Input layer keycode: %d\n", key->code,
+					 key->keycode);
+				sparse_keymap_report_entry(msi_wmi_input_dev,
+						key, 1, true);
+			}
+		} else
+			printk(KERN_INFO "Unknown key pressed - %x\n",
+			       eventcode);
+	} else
+		printk(KERN_INFO DRV_PFX "Unknown event received\n");
+	kfree(response.pointer);
+}
+
+static int __init msi_wmi_input_setup(void)
+{
+	int err;
+
+	msi_wmi_input_dev = input_allocate_device();
+	if (!msi_wmi_input_dev)
+		return -ENOMEM;
+
+	msi_wmi_input_dev->name = "MSI WMI hotkeys";
+	msi_wmi_input_dev->phys = "wmi/input0";
+	msi_wmi_input_dev->id.bustype = BUS_HOST;
+
+	err = sparse_keymap_setup(msi_wmi_input_dev, msi_wmi_keymap, NULL);
+	if (err)
+		goto err_free_dev;
+
+	err = input_register_device(msi_wmi_input_dev);
+
+	if (err)
+		goto err_free_keymap;
+
+	memset(last_pressed, 0, sizeof(last_pressed));
+
+	return 0;
+
+err_free_keymap:
+	sparse_keymap_free(msi_wmi_input_dev);
+err_free_dev:
+	input_free_device(msi_wmi_input_dev);
+	return err;
+}
+
+static int __init msi_wmi_init(void)
+{
+	int err;
+
+	if (!wmi_has_guid(MSIWMI_EVENT_GUID)) {
+		printk(KERN_ERR
+		       "This machine doesn't have MSI-hotkeys through WMI\n");
+		return -ENODEV;
+	}
+	err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
+			msi_wmi_notify, NULL);
+	if (err)
+		return -EINVAL;
+
+	err = msi_wmi_input_setup();
+	if (err)
+		goto err_uninstall_notifier;
+
+	if (!acpi_video_backlight_support()) {
+		backlight = backlight_device_register(DRV_NAME,
+				NULL, NULL, &msi_backlight_ops);
+		if (IS_ERR(backlight))
+			goto err_free_input;
+
+		backlight->props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
+		err = bl_get(NULL);
+		if (err < 0)
+			goto err_free_backlight;
+
+		backlight->props.brightness = err;
+	}
+	dprintk("Event handler installed\n");
+
+	return 0;
+
+err_free_backlight:
+	backlight_device_unregister(backlight);
+err_free_input:
+	input_unregister_device(msi_wmi_input_dev);
+err_uninstall_notifier:
+	wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
+	return err;
+}
+
+static void __exit msi_wmi_exit(void)
+{
+	if (wmi_has_guid(MSIWMI_EVENT_GUID)) {
+		wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
+		sparse_keymap_free(msi_wmi_input_dev);
+		input_unregister_device(msi_wmi_input_dev);
+		backlight_device_unregister(backlight);
+	}
+}
+
+module_init(msi_wmi_init);
+module_exit(msi_wmi_exit);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cf61d6a..448c8ae 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,8 +21,8 @@
  *  02110-1301, USA.
  */
 
-#define TPACPI_VERSION "0.23"
-#define TPACPI_SYSFS_VERSION 0x020500
+#define TPACPI_VERSION "0.24"
+#define TPACPI_SYSFS_VERSION 0x020700
 
 /*
  *  Changelog:
@@ -61,6 +61,7 @@
 
 #include <linux/nvram.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/sysfs.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
@@ -76,6 +77,10 @@
 #include <linux/jiffies.h>
 #include <linux/workqueue.h>
 
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
 #include <acpi/acpi_drivers.h>
 
 #include <linux/pci_ids.h>
@@ -231,6 +236,7 @@
 #define TPACPI_DBG_HKEY		0x0008
 #define TPACPI_DBG_FAN		0x0010
 #define TPACPI_DBG_BRGHT	0x0020
+#define TPACPI_DBG_MIXER	0x0040
 
 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
 #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -256,7 +262,7 @@
 struct ibm_struct {
 	char *name;
 
-	int (*read) (char *);
+	int (*read) (struct seq_file *);
 	int (*write) (char *);
 	void (*exit) (void);
 	void (*resume) (void);
@@ -298,6 +304,7 @@
 	u32 fan_ctrl_status_undef:1;
 	u32 second_fan:1;
 	u32 beep_needs_two_args:1;
+	u32 mixer_no_level_control:1;
 	u32 input_device_registered:1;
 	u32 platform_drv_registered:1;
 	u32 platform_drv_attrs_registered:1;
@@ -309,6 +316,7 @@
 
 static struct {
 	u16 hotkey_mask_ff:1;
+	u16 volume_ctrl_forbidden:1;
 } tp_warned;
 
 struct thinkpad_id_data {
@@ -425,6 +433,12 @@
 	  .ec = TPACPI_MATCH_ANY,		\
 	  .quirks = (__quirk) }
 
+#define TPACPI_QEC_LNV(__id1, __id2, __quirk)	\
+	{ .vendor = PCI_VENDOR_ID_LENOVO,	\
+	  .bios = TPACPI_MATCH_ANY,		\
+	  .ec = TPID(__id1, __id2),		\
+	  .quirks = (__quirk) }
+
 struct tpacpi_quirk {
 	unsigned int vendor;
 	u16 bios;
@@ -776,36 +790,25 @@
  ****************************************************************************
  ****************************************************************************/
 
-static int dispatch_procfs_read(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
+static int dispatch_proc_show(struct seq_file *m, void *v)
 {
-	struct ibm_struct *ibm = data;
-	int len;
+	struct ibm_struct *ibm = m->private;
 
 	if (!ibm || !ibm->read)
 		return -EINVAL;
-
-	len = ibm->read(page);
-	if (len < 0)
-		return len;
-
-	if (len <= off + count)
-		*eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len > count)
-		len = count;
-	if (len < 0)
-		len = 0;
-
-	return len;
+	return ibm->read(m);
 }
 
-static int dispatch_procfs_write(struct file *file,
-			const char __user *userbuf,
-			unsigned long count, void *data)
+static int dispatch_proc_open(struct inode *inode, struct file *file)
 {
-	struct ibm_struct *ibm = data;
+	return single_open(file, dispatch_proc_show, PDE(inode)->data);
+}
+
+static ssize_t dispatch_proc_write(struct file *file,
+			const char __user *userbuf,
+			size_t count, loff_t *pos)
+{
+	struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
 	char *kernbuf;
 	int ret;
 
@@ -834,6 +837,15 @@
 	return ret;
 }
 
+static const struct file_operations dispatch_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= dispatch_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= dispatch_proc_write,
+};
+
 static char *next_cmd(char **cmds)
 {
 	char *start = *cmds;
@@ -1261,6 +1273,7 @@
 	struct tpacpi_rfk *atp_rfk;
 	int res;
 	bool sw_state = false;
+	bool hw_state;
 	int sw_status;
 
 	BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
@@ -1295,7 +1308,8 @@
 			rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
 		}
 	}
-	rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
+	hw_state = tpacpi_rfk_check_hwblock_state();
+	rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
 
 	res = rfkill_register(atp_rfk->rfkill);
 	if (res < 0) {
@@ -1308,6 +1322,9 @@
 	}
 
 	tpacpi_rfkill_switches[id] = atp_rfk;
+
+	printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
+		name, (sw_state || hw_state) ? "" : "un");
 	return 0;
 }
 
@@ -1380,12 +1397,10 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
+static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
 {
-	int len = 0;
-
 	if (id >= TPACPI_RFK_SW_MAX)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
 		int status;
 
@@ -1399,13 +1414,13 @@
 				return status;
 		}
 
-		len += sprintf(p + len, "status:\t\t%s\n",
+		seq_printf(m, "status:\t\t%s\n",
 				(status == TPACPI_RFK_RADIO_ON) ?
 					"enabled" : "disabled");
-		len += sprintf(p + len, "commands:\tenable, disable\n");
+		seq_printf(m, "commands:\tenable, disable\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
@@ -1776,7 +1791,7 @@
 
 	TPV_QL1('7', '9',  'E', '3',  '5', '0'), /* T60/p */
 	TPV_QL1('7', 'C',  'D', '2',  '2', '2'), /* R60, R60i */
-	TPV_QL0('7', 'E',  'D', '0'),		 /* R60e, R60i */
+	TPV_QL1('7', 'E',  'D', '0',  '1', '5'), /* R60e, R60i */
 
 	/*      BIOS FW    BIOS VERS  EC FW     EC VERS */
 	TPV_QI2('1', 'W',  '9', '0',  '1', 'V', '2', '8'), /* R50e (1) */
@@ -1792,8 +1807,8 @@
 	TPV_QI1('7', '4',  '6', '4',  '2', '7'), /* X41 (0) */
 	TPV_QI1('7', '5',  '6', '0',  '2', '0'), /* X41t (0) */
 
-	TPV_QL0('7', 'B',  'D', '7'),		 /* X60/s */
-	TPV_QL0('7', 'J',  '3', '0'),		 /* X60t */
+	TPV_QL1('7', 'B',  'D', '7',  '4', '0'), /* X60/s */
+	TPV_QL1('7', 'J',  '3', '0',  '1', '3'), /* X60t */
 
 	/* (0) - older versions lack DMI EC fw string and functionality */
 	/* (1) - older versions known to lack functionality */
@@ -1883,14 +1898,11 @@
 	return 0;
 }
 
-static int thinkpad_acpi_driver_read(char *p)
+static int thinkpad_acpi_driver_read(struct seq_file *m)
 {
-	int len = 0;
-
-	len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC);
-	len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
-
-	return len;
+	seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
+	seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
+	return 0;
 }
 
 static struct ibm_struct thinkpad_acpi_driver_data = {
@@ -2186,7 +2198,8 @@
 		       fwmask, hotkey_acpi_mask);
 	}
 
-	hotkey_mask_warn_incomplete_mask();
+	if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
+		hotkey_mask_warn_incomplete_mask();
 
 	return rc;
 }
@@ -3182,6 +3195,8 @@
 	int res, i;
 	int status;
 	int hkeyv;
+	bool radiosw_state  = false;
+	bool tabletsw_state = false;
 
 	unsigned long quirks;
 
@@ -3287,6 +3302,7 @@
 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
 	if (dbg_wlswemul) {
 		tp_features.hotkey_wlsw = 1;
+		radiosw_state = !!tpacpi_wlsw_emulstate;
 		printk(TPACPI_INFO
 			"radio switch emulation enabled\n");
 	} else
@@ -3294,6 +3310,7 @@
 	/* Not all thinkpads have a hardware radio switch */
 	if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
 		tp_features.hotkey_wlsw = 1;
+		radiosw_state = !!status;
 		printk(TPACPI_INFO
 			"radio switch found; radios are %s\n",
 			enabled(status, 0));
@@ -3305,11 +3322,11 @@
 	/* For X41t, X60t, X61t Tablets... */
 	if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
 		tp_features.hotkey_tablet = 1;
+		tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
 		printk(TPACPI_INFO
 			"possible tablet mode switch found; "
 			"ThinkPad in %s mode\n",
-			(status & TP_HOTKEY_TABLET_MASK)?
-				"tablet" : "laptop");
+			(tabletsw_state) ? "tablet" : "laptop");
 		res = add_to_attr_set(hotkey_dev_attributes,
 				&dev_attr_hotkey_tablet_mode.attr);
 	}
@@ -3344,16 +3361,14 @@
 			TPACPI_HOTKEY_MAP_SIZE);
 	}
 
-	set_bit(EV_KEY, tpacpi_inputdev->evbit);
-	set_bit(EV_MSC, tpacpi_inputdev->evbit);
-	set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
+	input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
 	tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
 	tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
 	tpacpi_inputdev->keycode = hotkey_keycode_map;
 	for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
 		if (hotkey_keycode_map[i] != KEY_RESERVED) {
-			set_bit(hotkey_keycode_map[i],
-				tpacpi_inputdev->keybit);
+			input_set_capability(tpacpi_inputdev, EV_KEY,
+						hotkey_keycode_map[i]);
 		} else {
 			if (i < sizeof(hotkey_reserved_mask)*8)
 				hotkey_reserved_mask |= 1 << i;
@@ -3361,12 +3376,14 @@
 	}
 
 	if (tp_features.hotkey_wlsw) {
-		set_bit(EV_SW, tpacpi_inputdev->evbit);
-		set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit);
+		input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
+		input_report_switch(tpacpi_inputdev,
+				    SW_RFKILL_ALL, radiosw_state);
 	}
 	if (tp_features.hotkey_tablet) {
-		set_bit(EV_SW, tpacpi_inputdev->evbit);
-		set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit);
+		input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
+		input_report_switch(tpacpi_inputdev,
+				    SW_TABLET_MODE, tabletsw_state);
 	}
 
 	/* Do not issue duplicate brightness change events to
@@ -3433,8 +3450,6 @@
 	tpacpi_inputdev->close = &hotkey_inputdev_close;
 
 	hotkey_poll_setup_safe(true);
-	tpacpi_send_radiosw_update();
-	tpacpi_input_send_tabletsw();
 
 	return 0;
 
@@ -3542,49 +3557,57 @@
 	}
 }
 
+static void thermal_dump_all_sensors(void);
+
 static bool hotkey_notify_thermal(const u32 hkey,
 				 bool *send_acpi_ev,
 				 bool *ignore_acpi_ev)
 {
+	bool known = true;
+
 	/* 0x6000-0x6FFF: thermal alarms */
 	*send_acpi_ev = true;
 	*ignore_acpi_ev = false;
 
 	switch (hkey) {
-	case TP_HKEY_EV_ALARM_BAT_HOT:
-		printk(TPACPI_CRIT
-			"THERMAL ALARM: battery is too hot!\n");
-		/* recommended action: warn user through gui */
-		return true;
-	case TP_HKEY_EV_ALARM_BAT_XHOT:
-		printk(TPACPI_ALERT
-			"THERMAL EMERGENCY: battery is extremely hot!\n");
-		/* recommended action: immediate sleep/hibernate */
-		return true;
-	case TP_HKEY_EV_ALARM_SENSOR_HOT:
-		printk(TPACPI_CRIT
-			"THERMAL ALARM: "
-			"a sensor reports something is too hot!\n");
-		/* recommended action: warn user through gui, that */
-		/* some internal component is too hot */
-		return true;
-	case TP_HKEY_EV_ALARM_SENSOR_XHOT:
-		printk(TPACPI_ALERT
-			"THERMAL EMERGENCY: "
-			"a sensor reports something is extremely hot!\n");
-		/* recommended action: immediate sleep/hibernate */
-		return true;
 	case TP_HKEY_EV_THM_TABLE_CHANGED:
 		printk(TPACPI_INFO
 			"EC reports that Thermal Table has changed\n");
 		/* recommended action: do nothing, we don't have
 		 * Lenovo ATM information */
 		return true;
+	case TP_HKEY_EV_ALARM_BAT_HOT:
+		printk(TPACPI_CRIT
+			"THERMAL ALARM: battery is too hot!\n");
+		/* recommended action: warn user through gui */
+		break;
+	case TP_HKEY_EV_ALARM_BAT_XHOT:
+		printk(TPACPI_ALERT
+			"THERMAL EMERGENCY: battery is extremely hot!\n");
+		/* recommended action: immediate sleep/hibernate */
+		break;
+	case TP_HKEY_EV_ALARM_SENSOR_HOT:
+		printk(TPACPI_CRIT
+			"THERMAL ALARM: "
+			"a sensor reports something is too hot!\n");
+		/* recommended action: warn user through gui, that */
+		/* some internal component is too hot */
+		break;
+	case TP_HKEY_EV_ALARM_SENSOR_XHOT:
+		printk(TPACPI_ALERT
+			"THERMAL EMERGENCY: "
+			"a sensor reports something is extremely hot!\n");
+		/* recommended action: immediate sleep/hibernate */
+		break;
 	default:
 		printk(TPACPI_ALERT
 			 "THERMAL ALERT: unknown thermal alarm received\n");
-		return false;
+		known = false;
 	}
+
+	thermal_dump_all_sensors();
+
+	return known;
 }
 
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3727,14 +3750,13 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int hotkey_read(char *p)
+static int hotkey_read(struct seq_file *m)
 {
 	int res, status;
-	int len = 0;
 
 	if (!tp_features.hotkey) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
 
 	if (mutex_lock_killable(&hotkey_mutex))
@@ -3746,17 +3768,16 @@
 	if (res)
 		return res;
 
-	len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
+	seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
 	if (hotkey_all_mask) {
-		len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask);
-		len += sprintf(p + len,
-			       "commands:\tenable, disable, reset, <mask>\n");
+		seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
+		seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
 	} else {
-		len += sprintf(p + len, "mask:\t\tnot supported\n");
-		len += sprintf(p + len, "commands:\tenable, disable, reset\n");
+		seq_printf(m, "mask:\t\tnot supported\n");
+		seq_printf(m, "commands:\tenable, disable, reset\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static void hotkey_enabledisable_warn(bool enable)
@@ -3863,15 +3884,6 @@
 
 #define TPACPI_RFK_BLUETOOTH_SW_NAME	"tpacpi_bluetooth_sw"
 
-static void bluetooth_suspend(pm_message_t state)
-{
-	/* Try to make sure radio will resume powered off */
-	if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
-		   TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
-		vdbg_printk(TPACPI_DBG_RFKILL,
-			"bluetooth power down on resume request failed\n");
-}
-
 static int bluetooth_get_status(void)
 {
 	int status;
@@ -3905,10 +3917,9 @@
 #endif
 
 	/* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
+	status = TP_ACPI_BLUETOOTH_RESUMECTRL;
 	if (state == TPACPI_RFK_RADIO_ON)
-		status = TP_ACPI_BLUETOOTH_RADIOSSW;
-	else
-		status = 0;
+		status |= TP_ACPI_BLUETOOTH_RADIOSSW;
 
 	if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
 		return -EIO;
@@ -4032,9 +4043,9 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int bluetooth_read(char *p)
+static int bluetooth_read(struct seq_file *m)
 {
-	return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p);
+	return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
 }
 
 static int bluetooth_write(char *buf)
@@ -4047,7 +4058,6 @@
 	.read = bluetooth_read,
 	.write = bluetooth_write,
 	.exit = bluetooth_exit,
-	.suspend = bluetooth_suspend,
 	.shutdown = bluetooth_shutdown,
 };
 
@@ -4065,15 +4075,6 @@
 
 #define TPACPI_RFK_WWAN_SW_NAME		"tpacpi_wwan_sw"
 
-static void wan_suspend(pm_message_t state)
-{
-	/* Try to make sure radio will resume powered off */
-	if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
-		   TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
-		vdbg_printk(TPACPI_DBG_RFKILL,
-			"WWAN power down on resume request failed\n");
-}
-
 static int wan_get_status(void)
 {
 	int status;
@@ -4106,11 +4107,10 @@
 	}
 #endif
 
-	/* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
+	/* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
+	status = TP_ACPI_WANCARD_RESUMECTRL;
 	if (state == TPACPI_RFK_RADIO_ON)
-		status = TP_ACPI_WANCARD_RADIOSSW;
-	else
-		status = 0;
+		status |= TP_ACPI_WANCARD_RADIOSSW;
 
 	if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
 		return -EIO;
@@ -4233,9 +4233,9 @@
 }
 
 /* procfs -------------------------------------------------------------- */
-static int wan_read(char *p)
+static int wan_read(struct seq_file *m)
 {
-	return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p);
+	return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
 }
 
 static int wan_write(char *buf)
@@ -4248,7 +4248,6 @@
 	.read = wan_read,
 	.write = wan_write,
 	.exit = wan_exit,
-	.suspend = wan_suspend,
 	.shutdown = wan_shutdown,
 };
 
@@ -4611,14 +4610,13 @@
 	/* not reached */
 }
 
-static int video_read(char *p)
+static int video_read(struct seq_file *m)
 {
 	int status, autosw;
-	int len = 0;
 
 	if (video_supported == TPACPI_VIDEO_NONE) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
 
 	status = video_outputsw_get();
@@ -4629,20 +4627,20 @@
 	if (autosw < 0)
 		return autosw;
 
-	len += sprintf(p + len, "status:\t\tsupported\n");
-	len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0));
-	len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1));
+	seq_printf(m, "status:\t\tsupported\n");
+	seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
+	seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
 	if (video_supported == TPACPI_VIDEO_NEW)
-		len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3));
-	len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0));
-	len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n");
-	len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n");
+		seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
+	seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
+	seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
+	seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
 	if (video_supported == TPACPI_VIDEO_NEW)
-		len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n");
-	len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n");
-	len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n");
+		seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
+	seq_printf(m, "commands:\tauto_enable, auto_disable\n");
+	seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
 
-	return len;
+	return 0;
 }
 
 static int video_write(char *buf)
@@ -4834,25 +4832,24 @@
 		flush_workqueue(tpacpi_wq);
 }
 
-static int light_read(char *p)
+static int light_read(struct seq_file *m)
 {
-	int len = 0;
 	int status;
 
 	if (!tp_features.light) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	} else if (!tp_features.light_status) {
-		len += sprintf(p + len, "status:\t\tunknown\n");
-		len += sprintf(p + len, "commands:\ton, off\n");
+		seq_printf(m, "status:\t\tunknown\n");
+		seq_printf(m, "commands:\ton, off\n");
 	} else {
 		status = light_get_status();
 		if (status < 0)
 			return status;
-		len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0));
-		len += sprintf(p + len, "commands:\ton, off\n");
+		seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
+		seq_printf(m, "commands:\ton, off\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int light_write(char *buf)
@@ -4930,20 +4927,18 @@
 	device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
 }
 
-static int cmos_read(char *p)
+static int cmos_read(struct seq_file *m)
 {
-	int len = 0;
-
 	/* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
 	   R30, R31, T20-22, X20-21 */
 	if (!cmos_handle)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
-		len += sprintf(p + len, "status:\t\tsupported\n");
-		len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n");
+		seq_printf(m, "status:\t\tsupported\n");
+		seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int cmos_write(char *buf)
@@ -5318,15 +5313,13 @@
 	((s) == TPACPI_LED_OFF ? "off" : \
 		((s) == TPACPI_LED_ON ? "on" : "blinking"))
 
-static int led_read(char *p)
+static int led_read(struct seq_file *m)
 {
-	int len = 0;
-
 	if (!led_supported) {
-		len += sprintf(p + len, "status:\t\tnot supported\n");
-		return len;
+		seq_printf(m, "status:\t\tnot supported\n");
+		return 0;
 	}
-	len += sprintf(p + len, "status:\t\tsupported\n");
+	seq_printf(m, "status:\t\tsupported\n");
 
 	if (led_supported == TPACPI_LED_570) {
 		/* 570 */
@@ -5335,15 +5328,15 @@
 			status = led_get_status(i);
 			if (status < 0)
 				return -EIO;
-			len += sprintf(p + len, "%d:\t\t%s\n",
+			seq_printf(m, "%d:\t\t%s\n",
 				       i, str_led_status(status));
 		}
 	}
 
-	len += sprintf(p + len, "commands:\t"
+	seq_printf(m, "commands:\t"
 		       "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
 
-	return len;
+	return 0;
 }
 
 static int led_write(char *buf)
@@ -5416,18 +5409,16 @@
 	return (beep_handle)? 0 : 1;
 }
 
-static int beep_read(char *p)
+static int beep_read(struct seq_file *m)
 {
-	int len = 0;
-
 	if (!beep_handle)
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	else {
-		len += sprintf(p + len, "status:\t\tsupported\n");
-		len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n");
+		seq_printf(m, "status:\t\tsupported\n");
+		seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
 	}
 
-	return len;
+	return 0;
 }
 
 static int beep_write(char *buf)
@@ -5480,8 +5471,11 @@
 	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
 	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
 	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
+
+	TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
 };
 
+
 #define TPACPI_MAX_THERMAL_SENSORS 16	/* Max thermal sensors supported */
 struct ibm_thermal_sensors_struct {
 	s32 temp[TPACPI_MAX_THERMAL_SENSORS];
@@ -5571,6 +5565,28 @@
 	return n;
 }
 
+static void thermal_dump_all_sensors(void)
+{
+	int n, i;
+	struct ibm_thermal_sensors_struct t;
+
+	n = thermal_get_sensors(&t);
+	if (n <= 0)
+		return;
+
+	printk(TPACPI_NOTICE
+		"temperatures (Celsius):");
+
+	for (i = 0; i < n; i++) {
+		if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
+			printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
+		else
+			printk(KERN_CONT " N/A");
+	}
+
+	printk(KERN_CONT "\n");
+}
+
 /* sysfs temp##_input -------------------------------------------------- */
 
 static ssize_t thermal_temp_input_show(struct device *dev,
@@ -5586,7 +5602,7 @@
 	res = thermal_get_sensor(idx, &value);
 	if (res)
 		return res;
-	if (value == TP_EC_THERMAL_TMP_NA * 1000)
+	if (value == TPACPI_THERMAL_SENSOR_NA)
 		return -ENXIO;
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", value);
@@ -5763,9 +5779,8 @@
 	}
 }
 
-static int thermal_read(char *p)
+static int thermal_read(struct seq_file *m)
 {
-	int len = 0;
 	int n, i;
 	struct ibm_thermal_sensors_struct t;
 
@@ -5773,16 +5788,16 @@
 	if (unlikely(n < 0))
 		return n;
 
-	len += sprintf(p + len, "temperatures:\t");
+	seq_printf(m, "temperatures:\t");
 
 	if (n > 0) {
 		for (i = 0; i < (n - 1); i++)
-			len += sprintf(p + len, "%d ", t.temp[i] / 1000);
-		len += sprintf(p + len, "%d\n", t.temp[i] / 1000);
+			seq_printf(m, "%d ", t.temp[i] / 1000);
+		seq_printf(m, "%d\n", t.temp[i] / 1000);
 	} else
-		len += sprintf(p + len, "not supported\n");
+		seq_printf(m, "not supported\n");
 
-	return len;
+	return 0;
 }
 
 static struct ibm_struct thermal_driver_data = {
@@ -5797,39 +5812,38 @@
 
 static u8 ecdump_regs[256];
 
-static int ecdump_read(char *p)
+static int ecdump_read(struct seq_file *m)
 {
-	int len = 0;
 	int i, j;
 	u8 v;
 
-	len += sprintf(p + len, "EC      "
+	seq_printf(m, "EC      "
 		       " +00 +01 +02 +03 +04 +05 +06 +07"
 		       " +08 +09 +0a +0b +0c +0d +0e +0f\n");
 	for (i = 0; i < 256; i += 16) {
-		len += sprintf(p + len, "EC 0x%02x:", i);
+		seq_printf(m, "EC 0x%02x:", i);
 		for (j = 0; j < 16; j++) {
 			if (!acpi_ec_read(i + j, &v))
 				break;
 			if (v != ecdump_regs[i + j])
-				len += sprintf(p + len, " *%02x", v);
+				seq_printf(m, " *%02x", v);
 			else
-				len += sprintf(p + len, "  %02x", v);
+				seq_printf(m, "  %02x", v);
 			ecdump_regs[i + j] = v;
 		}
-		len += sprintf(p + len, "\n");
+		seq_putc(m, '\n');
 		if (j != 16)
 			break;
 	}
 
 	/* These are way too dangerous to advertise openly... */
 #if 0
-	len += sprintf(p + len, "commands:\t0x<offset> 0x<value>"
+	seq_printf(m, "commands:\t0x<offset> 0x<value>"
 		       " (<offset> is 00-ff, <value> is 00-ff)\n");
-	len += sprintf(p + len, "commands:\t0x<offset> <value>  "
+	seq_printf(m, "commands:\t0x<offset> <value>  "
 		       " (<offset> is 00-ff, <value> is 0-255)\n");
 #endif
-	return len;
+	return 0;
 }
 
 static int ecdump_write(char *buf)
@@ -6092,6 +6106,12 @@
 	return status & TP_EC_BACKLIGHT_LVLMSK;
 }
 
+static void tpacpi_brightness_notify_change(void)
+{
+	backlight_force_update(ibm_backlight_device,
+			       BACKLIGHT_UPDATE_HOTKEY);
+}
+
 static struct backlight_ops ibm_backlight_data = {
 	.get_brightness = brightness_get,
 	.update_status  = brightness_update_status,
@@ -6120,8 +6140,8 @@
 
 	/* Models with Intel Extreme Graphics 2 */
 	TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
-	TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
-	TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+	TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+	TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
 
 	/* Models with Intel GMA900 */
 	TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC),	/* T43, R52 */
@@ -6246,6 +6266,12 @@
 	ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
 	backlight_update_status(ibm_backlight_device);
 
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
+			"brightness: registering brightness hotkeys "
+			"as change notification\n");
+	tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
+				| TP_ACPI_HKEY_BRGHTUP_MASK
+				| TP_ACPI_HKEY_BRGHTDWN_MASK);;
 	return 0;
 }
 
@@ -6270,23 +6296,22 @@
 	tpacpi_brightness_checkpoint_nvram();
 }
 
-static int brightness_read(char *p)
+static int brightness_read(struct seq_file *m)
 {
-	int len = 0;
 	int level;
 
 	level = brightness_get(NULL);
 	if (level < 0) {
-		len += sprintf(p + len, "level:\t\tunreadable\n");
+		seq_printf(m, "level:\t\tunreadable\n");
 	} else {
-		len += sprintf(p + len, "level:\t\t%d\n", level);
-		len += sprintf(p + len, "commands:\tup, down\n");
-		len += sprintf(p + len, "commands:\tlevel <level>"
+		seq_printf(m, "level:\t\t%d\n", level);
+		seq_printf(m, "commands:\tup, down\n");
+		seq_printf(m, "commands:\tlevel <level>"
 			       " (<level> is 0-%d)\n",
 			       (tp_features.bright_16levels) ? 15 : 7);
 	}
 
-	return len;
+	return 0;
 }
 
 static int brightness_write(char *buf)
@@ -6322,6 +6347,9 @@
 	 * Doing it this way makes the syscall restartable in case of EINTR
 	 */
 	rc = brightness_set(level);
+	if (!rc && ibm_backlight_device)
+		backlight_force_update(ibm_backlight_device,
+					BACKLIGHT_UPDATE_SYSFS);
 	return (rc == -EINTR)? -ERESTARTSYS : rc;
 }
 
@@ -6338,99 +6366,654 @@
  * Volume subdriver
  */
 
-static int volume_offset = 0x30;
+/*
+ * IBM ThinkPads have a simple volume controller with MUTE gating.
+ * Very early Lenovo ThinkPads follow the IBM ThinkPad spec.
+ *
+ * Since the *61 series (and probably also the later *60 series), Lenovo
+ * ThinkPads only implement the MUTE gate.
+ *
+ * EC register 0x30
+ *   Bit 6: MUTE (1 mutes sound)
+ *   Bit 3-0: Volume
+ *   Other bits should be zero as far as we know.
+ *
+ * This is also stored in CMOS NVRAM, byte 0x60, bit 6 (MUTE), and
+ * bits 3-0 (volume).  Other bits in NVRAM may have other functions,
+ * such as bit 7 which is used to detect repeated presses of MUTE,
+ * and we leave them unchanged.
+ */
 
-static int volume_read(char *p)
+#define TPACPI_ALSA_DRVNAME  "ThinkPad EC"
+#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
+#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
+
+static int alsa_index = SNDRV_DEFAULT_IDX1;
+static char *alsa_id = "ThinkPadEC";
+static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
+
+struct tpacpi_alsa_data {
+	struct snd_card *card;
+	struct snd_ctl_elem_id *ctl_mute_id;
+	struct snd_ctl_elem_id *ctl_vol_id;
+};
+
+static struct snd_card *alsa_card;
+
+enum {
+	TP_EC_AUDIO = 0x30,
+
+	/* TP_EC_AUDIO bits */
+	TP_EC_AUDIO_MUTESW = 6,
+
+	/* TP_EC_AUDIO bitmasks */
+	TP_EC_AUDIO_LVL_MSK = 0x0F,
+	TP_EC_AUDIO_MUTESW_MSK = (1 << TP_EC_AUDIO_MUTESW),
+
+	/* Maximum volume */
+	TP_EC_VOLUME_MAX = 14,
+};
+
+enum tpacpi_volume_access_mode {
+	TPACPI_VOL_MODE_AUTO = 0,	/* Not implemented yet */
+	TPACPI_VOL_MODE_EC,		/* Pure EC control */
+	TPACPI_VOL_MODE_UCMS_STEP,	/* UCMS step-based control: N/A */
+	TPACPI_VOL_MODE_ECNVRAM,	/* EC control w/ NVRAM store */
+	TPACPI_VOL_MODE_MAX
+};
+
+enum tpacpi_volume_capabilities {
+	TPACPI_VOL_CAP_AUTO = 0,	/* Use white/blacklist */
+	TPACPI_VOL_CAP_VOLMUTE,		/* Output vol and mute */
+	TPACPI_VOL_CAP_MUTEONLY,	/* Output mute only */
+	TPACPI_VOL_CAP_MAX
+};
+
+static enum tpacpi_volume_access_mode volume_mode =
+	TPACPI_VOL_MODE_MAX;
+
+static enum tpacpi_volume_capabilities volume_capabilities;
+static int volume_control_allowed;
+
+/*
+ * Used to syncronize writers to TP_EC_AUDIO and
+ * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write
+ */
+static struct mutex volume_mutex;
+
+static void tpacpi_volume_checkpoint_nvram(void)
 {
-	int len = 0;
-	u8 level;
+	u8 lec = 0;
+	u8 b_nvram;
+	u8 ec_mask;
 
-	if (!acpi_ec_read(volume_offset, &level)) {
-		len += sprintf(p + len, "level:\t\tunreadable\n");
+	if (volume_mode != TPACPI_VOL_MODE_ECNVRAM)
+		return;
+	if (!volume_control_allowed)
+		return;
+
+	vdbg_printk(TPACPI_DBG_MIXER,
+		"trying to checkpoint mixer state to NVRAM...\n");
+
+	if (tp_features.mixer_no_level_control)
+		ec_mask = TP_EC_AUDIO_MUTESW_MSK;
+	else
+		ec_mask = TP_EC_AUDIO_MUTESW_MSK | TP_EC_AUDIO_LVL_MSK;
+
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return;
+
+	if (unlikely(!acpi_ec_read(TP_EC_AUDIO, &lec)))
+		goto unlock;
+	lec &= ec_mask;
+	b_nvram = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
+
+	if (lec != (b_nvram & ec_mask)) {
+		/* NVRAM needs update */
+		b_nvram &= ~ec_mask;
+		b_nvram |= lec;
+		nvram_write_byte(b_nvram, TP_NVRAM_ADDR_MIXER);
+		dbg_printk(TPACPI_DBG_MIXER,
+			   "updated NVRAM mixer status to 0x%02x (0x%02x)\n",
+			   (unsigned int) lec, (unsigned int) b_nvram);
 	} else {
-		len += sprintf(p + len, "level:\t\t%d\n", level & 0xf);
-		len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6));
-		len += sprintf(p + len, "commands:\tup, down, mute\n");
-		len += sprintf(p + len, "commands:\tlevel <level>"
-			       " (<level> is 0-15)\n");
+		vdbg_printk(TPACPI_DBG_MIXER,
+			   "NVRAM mixer status already is 0x%02x (0x%02x)\n",
+			   (unsigned int) lec, (unsigned int) b_nvram);
 	}
 
-	return len;
+unlock:
+	mutex_unlock(&volume_mutex);
 }
 
-static int volume_write(char *buf)
+static int volume_get_status_ec(u8 *status)
 {
-	int cmos_cmd, inc, i;
-	u8 level, mute;
-	int new_level, new_mute;
-	char *cmd;
+	u8 s;
 
-	while ((cmd = next_cmd(&buf))) {
-		if (!acpi_ec_read(volume_offset, &level))
-			return -EIO;
-		new_mute = mute = level & 0x40;
-		new_level = level = level & 0xf;
+	if (!acpi_ec_read(TP_EC_AUDIO, &s))
+		return -EIO;
 
-		if (strlencmp(cmd, "up") == 0) {
-			if (mute)
-				new_mute = 0;
-			else
-				new_level = level == 15 ? 15 : level + 1;
-		} else if (strlencmp(cmd, "down") == 0) {
-			if (mute)
-				new_mute = 0;
-			else
-				new_level = level == 0 ? 0 : level - 1;
-		} else if (sscanf(cmd, "level %d", &new_level) == 1 &&
-			   new_level >= 0 && new_level <= 15) {
-			/* new_level set */
-		} else if (strlencmp(cmd, "mute") == 0) {
-			new_mute = 0x40;
-		} else
-			return -EINVAL;
+	*status = s;
 
-		if (new_level != level) {
-			/* mute doesn't change */
+	dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s);
 
-			cmos_cmd = (new_level > level) ?
-					TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN;
-			inc = new_level > level ? 1 : -1;
+	return 0;
+}
 
-			if (mute && (issue_thinkpad_cmos_command(cmos_cmd) ||
-				     !acpi_ec_write(volume_offset, level)))
-				return -EIO;
+static int volume_get_status(u8 *status)
+{
+	return volume_get_status_ec(status);
+}
 
-			for (i = level; i != new_level; i += inc)
-				if (issue_thinkpad_cmos_command(cmos_cmd) ||
-				    !acpi_ec_write(volume_offset, i + inc))
-					return -EIO;
+static int volume_set_status_ec(const u8 status)
+{
+	if (!acpi_ec_write(TP_EC_AUDIO, status))
+		return -EIO;
 
-			if (mute &&
-			    (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) ||
-			     !acpi_ec_write(volume_offset, new_level + mute))) {
-				return -EIO;
-			}
+	dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
+
+	return 0;
+}
+
+static int volume_set_status(const u8 status)
+{
+	return volume_set_status_ec(status);
+}
+
+static int volume_set_mute_ec(const bool mute)
+{
+	int rc;
+	u8 s, n;
+
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return -EINTR;
+
+	rc = volume_get_status_ec(&s);
+	if (rc)
+		goto unlock;
+
+	n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
+		     s & ~TP_EC_AUDIO_MUTESW_MSK;
+
+	if (n != s)
+		rc = volume_set_status_ec(n);
+
+unlock:
+	mutex_unlock(&volume_mutex);
+	return rc;
+}
+
+static int volume_set_mute(const bool mute)
+{
+	dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
+		   (mute) ? "" : "un");
+	return volume_set_mute_ec(mute);
+}
+
+static int volume_set_volume_ec(const u8 vol)
+{
+	int rc;
+	u8 s, n;
+
+	if (vol > TP_EC_VOLUME_MAX)
+		return -EINVAL;
+
+	if (mutex_lock_killable(&volume_mutex) < 0)
+		return -EINTR;
+
+	rc = volume_get_status_ec(&s);
+	if (rc)
+		goto unlock;
+
+	n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
+
+	if (n != s)
+		rc = volume_set_status_ec(n);
+
+unlock:
+	mutex_unlock(&volume_mutex);
+	return rc;
+}
+
+static int volume_set_volume(const u8 vol)
+{
+	dbg_printk(TPACPI_DBG_MIXER,
+		   "trying to set volume level to %hu\n", vol);
+	return volume_set_volume_ec(vol);
+}
+
+static void volume_alsa_notify_change(void)
+{
+	struct tpacpi_alsa_data *d;
+
+	if (alsa_card && alsa_card->private_data) {
+		d = alsa_card->private_data;
+		if (d->ctl_mute_id)
+			snd_ctl_notify(alsa_card,
+					SNDRV_CTL_EVENT_MASK_VALUE,
+					d->ctl_mute_id);
+		if (d->ctl_vol_id)
+			snd_ctl_notify(alsa_card,
+					SNDRV_CTL_EVENT_MASK_VALUE,
+					d->ctl_vol_id);
+	}
+}
+
+static int volume_alsa_vol_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = TP_EC_VOLUME_MAX;
+	return 0;
+}
+
+static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 s;
+	int rc;
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	ucontrol->value.integer.value[0] = s & TP_EC_AUDIO_LVL_MSK;
+	return 0;
+}
+
+static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	return volume_set_volume(ucontrol->value.integer.value[0]);
+}
+
+#define volume_alsa_mute_info snd_ctl_boolean_mono_info
+
+static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	u8 s;
+	int rc;
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	ucontrol->value.integer.value[0] =
+				(s & TP_EC_AUDIO_MUTESW_MSK) ? 0 : 1;
+	return 0;
+}
+
+static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	return volume_set_mute(!ucontrol->value.integer.value[0]);
+}
+
+static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Console Playback Volume",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.info = volume_alsa_vol_info,
+	.get = volume_alsa_vol_get,
+};
+
+static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Console Playback Switch",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.info = volume_alsa_mute_info,
+	.get = volume_alsa_mute_get,
+};
+
+static void volume_suspend(pm_message_t state)
+{
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static void volume_resume(void)
+{
+	volume_alsa_notify_change();
+}
+
+static void volume_shutdown(void)
+{
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static void volume_exit(void)
+{
+	if (alsa_card) {
+		snd_card_free(alsa_card);
+		alsa_card = NULL;
+	}
+
+	tpacpi_volume_checkpoint_nvram();
+}
+
+static int __init volume_create_alsa_mixer(void)
+{
+	struct snd_card *card;
+	struct tpacpi_alsa_data *data;
+	struct snd_kcontrol *ctl_vol;
+	struct snd_kcontrol *ctl_mute;
+	int rc;
+
+	rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
+			    sizeof(struct tpacpi_alsa_data), &card);
+	if (rc < 0)
+		return rc;
+	if (!card)
+		return -ENOMEM;
+
+	BUG_ON(!card->private_data);
+	data = card->private_data;
+	data->card = card;
+
+	strlcpy(card->driver, TPACPI_ALSA_DRVNAME,
+		sizeof(card->driver));
+	strlcpy(card->shortname, TPACPI_ALSA_SHRTNAME,
+		sizeof(card->shortname));
+	snprintf(card->mixername, sizeof(card->mixername), "ThinkPad EC %s",
+		 (thinkpad_id.ec_version_str) ?
+			thinkpad_id.ec_version_str : "(unknown)");
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s at EC reg 0x%02x, fw %s", card->shortname, TP_EC_AUDIO,
+		 (thinkpad_id.ec_version_str) ?
+			thinkpad_id.ec_version_str : "unknown");
+
+	if (volume_control_allowed) {
+		volume_alsa_control_vol.put = volume_alsa_vol_put;
+		volume_alsa_control_vol.access =
+				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+
+		volume_alsa_control_mute.put = volume_alsa_mute_put;
+		volume_alsa_control_mute.access =
+				SNDRV_CTL_ELEM_ACCESS_READWRITE;
+	}
+
+	if (!tp_features.mixer_no_level_control) {
+		ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
+		rc = snd_ctl_add(card, ctl_vol);
+		if (rc < 0) {
+			printk(TPACPI_ERR
+				"Failed to create ALSA volume control\n");
+			goto err_out;
 		}
+		data->ctl_vol_id = &ctl_vol->id;
+	}
 
-		if (new_mute != mute) {
-			/* level doesn't change */
+	ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
+	rc = snd_ctl_add(card, ctl_mute);
+	if (rc < 0) {
+		printk(TPACPI_ERR "Failed to create ALSA mute control\n");
+		goto err_out;
+	}
+	data->ctl_mute_id = &ctl_mute->id;
 
-			cmos_cmd = (new_mute) ?
-				   TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP;
+	snd_card_set_dev(card, &tpacpi_pdev->dev);
+	rc = snd_card_register(card);
 
-			if (issue_thinkpad_cmos_command(cmos_cmd) ||
-			    !acpi_ec_write(volume_offset, level + new_mute))
-				return -EIO;
+err_out:
+	if (rc < 0) {
+		snd_card_free(card);
+		card = NULL;
+	}
+
+	alsa_card = card;
+	return rc;
+}
+
+#define TPACPI_VOL_Q_MUTEONLY	0x0001	/* Mute-only control available */
+#define TPACPI_VOL_Q_LEVEL	0x0002  /* Volume control available */
+
+static const struct tpacpi_quirk volume_quirk_table[] __initconst = {
+	/* Whitelist volume level on all IBM by default */
+	{ .vendor = PCI_VENDOR_ID_IBM,
+	  .bios   = TPACPI_MATCH_ANY,
+	  .ec     = TPACPI_MATCH_ANY,
+	  .quirks = TPACPI_VOL_Q_LEVEL },
+
+	/* Lenovo models with volume control (needs confirmation) */
+	TPACPI_QEC_LNV('7', 'C', TPACPI_VOL_Q_LEVEL), /* R60/i */
+	TPACPI_QEC_LNV('7', 'E', TPACPI_VOL_Q_LEVEL), /* R60e/i */
+	TPACPI_QEC_LNV('7', '9', TPACPI_VOL_Q_LEVEL), /* T60/p */
+	TPACPI_QEC_LNV('7', 'B', TPACPI_VOL_Q_LEVEL), /* X60/s */
+	TPACPI_QEC_LNV('7', 'J', TPACPI_VOL_Q_LEVEL), /* X60t */
+	TPACPI_QEC_LNV('7', '7', TPACPI_VOL_Q_LEVEL), /* Z60 */
+	TPACPI_QEC_LNV('7', 'F', TPACPI_VOL_Q_LEVEL), /* Z61 */
+
+	/* Whitelist mute-only on all Lenovo by default */
+	{ .vendor = PCI_VENDOR_ID_LENOVO,
+	  .bios   = TPACPI_MATCH_ANY,
+	  .ec	  = TPACPI_MATCH_ANY,
+	  .quirks = TPACPI_VOL_Q_MUTEONLY }
+};
+
+static int __init volume_init(struct ibm_init_struct *iibm)
+{
+	unsigned long quirks;
+	int rc;
+
+	vdbg_printk(TPACPI_DBG_INIT, "initializing volume subdriver\n");
+
+	mutex_init(&volume_mutex);
+
+	/*
+	 * Check for module parameter bogosity, note that we
+	 * init volume_mode to TPACPI_VOL_MODE_MAX in order to be
+	 * able to detect "unspecified"
+	 */
+	if (volume_mode > TPACPI_VOL_MODE_MAX)
+		return -EINVAL;
+
+	if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
+		printk(TPACPI_ERR
+			"UCMS step volume mode not implemented, "
+			"please contact %s\n", TPACPI_MAIL);
+		return 1;
+	}
+
+	if (volume_capabilities >= TPACPI_VOL_CAP_MAX)
+		return -EINVAL;
+
+	/*
+	 * The ALSA mixer is our primary interface.
+	 * When disabled, don't install the subdriver at all
+	 */
+	if (!alsa_enable) {
+		vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+			    "ALSA mixer disabled by parameter, "
+			    "not loading volume subdriver...\n");
+		return 1;
+	}
+
+	quirks = tpacpi_check_quirks(volume_quirk_table,
+				     ARRAY_SIZE(volume_quirk_table));
+
+	switch (volume_capabilities) {
+	case TPACPI_VOL_CAP_AUTO:
+		if (quirks & TPACPI_VOL_Q_MUTEONLY)
+			tp_features.mixer_no_level_control = 1;
+		else if (quirks & TPACPI_VOL_Q_LEVEL)
+			tp_features.mixer_no_level_control = 0;
+		else
+			return 1; /* no mixer */
+		break;
+	case TPACPI_VOL_CAP_VOLMUTE:
+		tp_features.mixer_no_level_control = 0;
+		break;
+	case TPACPI_VOL_CAP_MUTEONLY:
+		tp_features.mixer_no_level_control = 1;
+		break;
+	default:
+		return 1;
+	}
+
+	if (volume_capabilities != TPACPI_VOL_CAP_AUTO)
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"using user-supplied volume_capabilities=%d\n",
+				volume_capabilities);
+
+	if (volume_mode == TPACPI_VOL_MODE_AUTO ||
+	    volume_mode == TPACPI_VOL_MODE_MAX) {
+		volume_mode = TPACPI_VOL_MODE_ECNVRAM;
+
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"driver auto-selected volume_mode=%d\n",
+				volume_mode);
+	} else {
+		dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+				"using user-supplied volume_mode=%d\n",
+				volume_mode);
+	}
+
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+			"mute is supported, volume control is %s\n",
+			str_supported(!tp_features.mixer_no_level_control));
+
+	rc = volume_create_alsa_mixer();
+	if (rc) {
+		printk(TPACPI_ERR
+			"Could not create the ALSA mixer interface\n");
+		return rc;
+	}
+
+	printk(TPACPI_INFO
+		"Console audio control enabled, mode: %s\n",
+		(volume_control_allowed) ?
+			"override (read/write)" :
+			"monitor (read only)");
+
+	vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
+		"registering volume hotkeys as change notification\n");
+	tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
+			| TP_ACPI_HKEY_VOLUP_MASK
+			| TP_ACPI_HKEY_VOLDWN_MASK
+			| TP_ACPI_HKEY_MUTE_MASK);
+
+	return 0;
+}
+
+static int volume_read(struct seq_file *m)
+{
+	u8 status;
+
+	if (volume_get_status(&status) < 0) {
+		seq_printf(m, "level:\t\tunreadable\n");
+	} else {
+		if (tp_features.mixer_no_level_control)
+			seq_printf(m, "level:\t\tunsupported\n");
+		else
+			seq_printf(m, "level:\t\t%d\n",
+					status & TP_EC_AUDIO_LVL_MSK);
+
+		seq_printf(m, "mute:\t\t%s\n",
+				onoff(status, TP_EC_AUDIO_MUTESW));
+
+		if (volume_control_allowed) {
+			seq_printf(m, "commands:\tunmute, mute\n");
+			if (!tp_features.mixer_no_level_control) {
+				seq_printf(m,
+					       "commands:\tup, down\n");
+				seq_printf(m,
+					       "commands:\tlevel <level>"
+					       " (<level> is 0-%d)\n",
+					       TP_EC_VOLUME_MAX);
+			}
 		}
 	}
 
 	return 0;
 }
 
+static int volume_write(char *buf)
+{
+	u8 s;
+	u8 new_level, new_mute;
+	int l;
+	char *cmd;
+	int rc;
+
+	/*
+	 * We do allow volume control at driver startup, so that the
+	 * user can set initial state through the volume=... parameter hack.
+	 */
+	if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
+		if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
+			tp_warned.volume_ctrl_forbidden = 1;
+			printk(TPACPI_NOTICE
+				"Console audio control in monitor mode, "
+				"changes are not allowed.\n");
+			printk(TPACPI_NOTICE
+				"Use the volume_control=1 module parameter "
+				"to enable volume control\n");
+		}
+		return -EPERM;
+	}
+
+	rc = volume_get_status(&s);
+	if (rc < 0)
+		return rc;
+
+	new_level = s & TP_EC_AUDIO_LVL_MSK;
+	new_mute  = s & TP_EC_AUDIO_MUTESW_MSK;
+
+	while ((cmd = next_cmd(&buf))) {
+		if (!tp_features.mixer_no_level_control) {
+			if (strlencmp(cmd, "up") == 0) {
+				if (new_mute)
+					new_mute = 0;
+				else if (new_level < TP_EC_VOLUME_MAX)
+					new_level++;
+				continue;
+			} else if (strlencmp(cmd, "down") == 0) {
+				if (new_mute)
+					new_mute = 0;
+				else if (new_level > 0)
+					new_level--;
+				continue;
+			} else if (sscanf(cmd, "level %u", &l) == 1 &&
+				   l >= 0 && l <= TP_EC_VOLUME_MAX) {
+					new_level = l;
+				continue;
+			}
+		}
+		if (strlencmp(cmd, "mute") == 0)
+			new_mute = TP_EC_AUDIO_MUTESW_MSK;
+		else if (strlencmp(cmd, "unmute") == 0)
+			new_mute = 0;
+		else
+			return -EINVAL;
+	}
+
+	if (tp_features.mixer_no_level_control) {
+		tpacpi_disclose_usertask("procfs volume", "%smute\n",
+					new_mute ? "" : "un");
+		rc = volume_set_mute(!!new_mute);
+	} else {
+		tpacpi_disclose_usertask("procfs volume",
+					"%smute and set level to %d\n",
+					new_mute ? "" : "un", new_level);
+		rc = volume_set_status(new_mute | new_level);
+	}
+	volume_alsa_notify_change();
+
+	return (rc == -EINTR) ? -ERESTARTSYS : rc;
+}
+
 static struct ibm_struct volume_driver_data = {
 	.name = "volume",
 	.read = volume_read,
 	.write = volume_write,
+	.exit = volume_exit,
+	.suspend = volume_suspend,
+	.resume = volume_resume,
+	.shutdown = volume_shutdown,
 };
 
 /*************************************************************************
@@ -7507,9 +8090,8 @@
 	}
 }
 
-static int fan_read(char *p)
+static int fan_read(struct seq_file *m)
 {
-	int len = 0;
 	int rc;
 	u8 status;
 	unsigned int speed = 0;
@@ -7521,7 +8103,7 @@
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "status:\t\t%s\n"
+		seq_printf(m, "status:\t\t%s\n"
 			       "level:\t\t%d\n",
 			       (status != 0) ? "enabled" : "disabled", status);
 		break;
@@ -7532,54 +8114,54 @@
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "status:\t\t%s\n",
+		seq_printf(m, "status:\t\t%s\n",
 			       (status != 0) ? "enabled" : "disabled");
 
 		rc = fan_get_speed(&speed);
 		if (rc < 0)
 			return rc;
 
-		len += sprintf(p + len, "speed:\t\t%d\n", speed);
+		seq_printf(m, "speed:\t\t%d\n", speed);
 
 		if (status & TP_EC_FAN_FULLSPEED)
 			/* Disengaged mode takes precedence */
-			len += sprintf(p + len, "level:\t\tdisengaged\n");
+			seq_printf(m, "level:\t\tdisengaged\n");
 		else if (status & TP_EC_FAN_AUTO)
-			len += sprintf(p + len, "level:\t\tauto\n");
+			seq_printf(m, "level:\t\tauto\n");
 		else
-			len += sprintf(p + len, "level:\t\t%d\n", status);
+			seq_printf(m, "level:\t\t%d\n", status);
 		break;
 
 	case TPACPI_FAN_NONE:
 	default:
-		len += sprintf(p + len, "status:\t\tnot supported\n");
+		seq_printf(m, "status:\t\tnot supported\n");
 	}
 
 	if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
-		len += sprintf(p + len, "commands:\tlevel <level>");
+		seq_printf(m, "commands:\tlevel <level>");
 
 		switch (fan_control_access_mode) {
 		case TPACPI_FAN_WR_ACPI_SFAN:
-			len += sprintf(p + len, " (<level> is 0-7)\n");
+			seq_printf(m, " (<level> is 0-7)\n");
 			break;
 
 		default:
-			len += sprintf(p + len, " (<level> is 0-7, "
+			seq_printf(m, " (<level> is 0-7, "
 				       "auto, disengaged, full-speed)\n");
 			break;
 		}
 	}
 
 	if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
-		len += sprintf(p + len, "commands:\tenable, disable\n"
+		seq_printf(m, "commands:\tenable, disable\n"
 			       "commands:\twatchdog <timeout> (<timeout> "
 			       "is 0 (off), 1-120 (seconds))\n");
 
 	if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
-		len += sprintf(p + len, "commands:\tspeed <speed>"
+		seq_printf(m, "commands:\tspeed <speed>"
 			       " (<speed> is 0-65535)\n");
 
-	return len;
+	return 0;
 }
 
 static int fan_write_cmd_level(const char *cmd, int *rc)
@@ -7721,10 +8303,23 @@
  */
 static void tpacpi_driver_event(const unsigned int hkey_event)
 {
+	if (ibm_backlight_device) {
+		switch (hkey_event) {
+		case TP_HKEY_EV_BRGHT_UP:
+		case TP_HKEY_EV_BRGHT_DOWN:
+			tpacpi_brightness_notify_change();
+		}
+	}
+	if (alsa_card) {
+		switch (hkey_event) {
+		case TP_HKEY_EV_VOL_UP:
+		case TP_HKEY_EV_VOL_DOWN:
+		case TP_HKEY_EV_VOL_MUTE:
+			volume_alsa_notify_change();
+		}
+	}
 }
 
-
-
 static void hotkey_driver_event(const unsigned int scancode)
 {
 	tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
@@ -7853,19 +8448,19 @@
 		"%s installed\n", ibm->name);
 
 	if (ibm->read) {
-		entry = create_proc_entry(ibm->name,
-					  S_IFREG | S_IRUGO | S_IWUSR,
-					  proc_dir);
+		mode_t mode;
+
+		mode = S_IRUGO;
+		if (ibm->write)
+			mode |= S_IWUSR;
+		entry = proc_create_data(ibm->name, mode, proc_dir,
+					 &dispatch_proc_fops, ibm);
 		if (!entry) {
 			printk(TPACPI_ERR "unable to create proc entry %s\n",
 			       ibm->name);
 			ret = -ENODEV;
 			goto err_out;
 		}
-		entry->data = ibm;
-		entry->read_proc = &dispatch_procfs_read;
-		if (ibm->write)
-			entry->write_proc = &dispatch_procfs_write;
 		ibm->flags.proc_created = 1;
 	}
 
@@ -8077,6 +8672,7 @@
 		.data = &brightness_driver_data,
 	},
 	{
+		.init = volume_init,
 		.data = &volume_driver_data,
 	},
 	{
@@ -8112,36 +8708,59 @@
 	return -EINVAL;
 }
 
-module_param(experimental, int, 0);
+module_param(experimental, int, 0444);
 MODULE_PARM_DESC(experimental,
 		 "Enables experimental features when non-zero");
 
 module_param_named(debug, dbg_level, uint, 0);
 MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
 
-module_param(force_load, bool, 0);
+module_param(force_load, bool, 0444);
 MODULE_PARM_DESC(force_load,
 		 "Attempts to load the driver even on a "
 		 "mis-identified ThinkPad when true");
 
-module_param_named(fan_control, fan_control_allowed, bool, 0);
+module_param_named(fan_control, fan_control_allowed, bool, 0444);
 MODULE_PARM_DESC(fan_control,
 		 "Enables setting fan parameters features when true");
 
-module_param_named(brightness_mode, brightness_mode, uint, 0);
+module_param_named(brightness_mode, brightness_mode, uint, 0444);
 MODULE_PARM_DESC(brightness_mode,
 		 "Selects brightness control strategy: "
 		 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
 
-module_param(brightness_enable, uint, 0);
+module_param(brightness_enable, uint, 0444);
 MODULE_PARM_DESC(brightness_enable,
 		 "Enables backlight control when 1, disables when 0");
 
-module_param(hotkey_report_mode, uint, 0);
+module_param(hotkey_report_mode, uint, 0444);
 MODULE_PARM_DESC(hotkey_report_mode,
 		 "used for backwards compatibility with userspace, "
 		 "see documentation");
 
+module_param_named(volume_mode, volume_mode, uint, 0444);
+MODULE_PARM_DESC(volume_mode,
+		 "Selects volume control strategy: "
+		 "0=auto, 1=EC, 2=N/A, 3=EC+NVRAM");
+
+module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
+MODULE_PARM_DESC(volume_capabilities,
+		 "Selects the mixer capabilites: "
+		 "0=auto, 1=volume and mute, 2=mute only");
+
+module_param_named(volume_control, volume_control_allowed, bool, 0444);
+MODULE_PARM_DESC(volume_control,
+		 "Enables software override for the console audio "
+		 "control when true");
+
+/* ALSA module API parameters */
+module_param_named(index, alsa_index, int, 0444);
+MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
+module_param_named(id, alsa_id, charp, 0444);
+MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
+module_param_named(enable, alsa_enable, bool, 0444);
+MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
+
 #define TPACPI_PARAM(feature) \
 	module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
 	MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
@@ -8160,25 +8779,25 @@
 TPACPI_PARAM(fan);
 
 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
-module_param(dbg_wlswemul, uint, 0);
+module_param(dbg_wlswemul, uint, 0444);
 MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
 module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
 MODULE_PARM_DESC(wlsw_state,
 		 "Initial state of the emulated WLSW switch");
 
-module_param(dbg_bluetoothemul, uint, 0);
+module_param(dbg_bluetoothemul, uint, 0444);
 MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
 module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
 MODULE_PARM_DESC(bluetooth_state,
 		 "Initial state of the emulated bluetooth switch");
 
-module_param(dbg_wwanemul, uint, 0);
+module_param(dbg_wwanemul, uint, 0444);
 MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
 module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
 MODULE_PARM_DESC(wwan_state,
 		 "Initial state of the emulated WWAN switch");
 
-module_param(dbg_uwbemul, uint, 0);
+module_param(dbg_uwbemul, uint, 0444);
 MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
 module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
 MODULE_PARM_DESC(uwb_state,
@@ -8371,6 +8990,7 @@
 						PCI_VENDOR_ID_IBM;
 		tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
 		tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
+		tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
 	}
 	for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
 		ret = ibm_init(&ibms_init[i]);
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c
new file mode 100644
index 0000000..a350418
--- /dev/null
+++ b/drivers/platform/x86/toshiba_bluetooth.c
@@ -0,0 +1,144 @@
+/*
+ * Toshiba Bluetooth Enable Driver
+ *
+ * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
+ *
+ * Thanks to Matthew Garrett for background info on ACPI innards which
+ * normal people aren't meant to understand :-)
+ *
+ * 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.
+ *
+ * Note the Toshiba Bluetooth RFKill switch seems to be a strange
+ * fish. It only provides a BT event when the switch is flipped to
+ * the 'on' position. When flipping it to 'off', the USB device is
+ * simply pulled away underneath us, without any BT event being
+ * delivered.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
+MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
+MODULE_LICENSE("GPL");
+
+
+static int toshiba_bt_rfkill_add(struct acpi_device *device);
+static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
+static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
+static int toshiba_bt_resume(struct acpi_device *device);
+
+static const struct acpi_device_id bt_device_ids[] = {
+	{ "TOS6205", 0},
+	{ "", 0},
+};
+MODULE_DEVICE_TABLE(acpi, bt_device_ids);
+
+static struct acpi_driver toshiba_bt_rfkill_driver = {
+	.name =		"Toshiba BT",
+	.class =	"Toshiba",
+	.ids =		bt_device_ids,
+	.ops =		{
+				.add =		toshiba_bt_rfkill_add,
+				.remove =	toshiba_bt_rfkill_remove,
+				.notify =	toshiba_bt_rfkill_notify,
+				.resume =	toshiba_bt_resume,
+			},
+	.owner = 	THIS_MODULE,
+};
+
+
+static int toshiba_bluetooth_enable(acpi_handle handle)
+{
+	acpi_status res1, res2;
+	acpi_integer result;
+
+	/*
+	 * Query ACPI to verify RFKill switch is set to 'on'.
+	 * If not, we return silently, no need to report it as
+	 * an error.
+	 */
+	res1 = acpi_evaluate_integer(handle, "BTST", NULL, &result);
+	if (ACPI_FAILURE(res1))
+		return res1;
+	if (!(result & 0x01))
+		return 0;
+
+	printk(KERN_INFO "toshiba_bluetooth: Re-enabling Toshiba Bluetooth\n");
+	res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
+	res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
+	if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2))
+		return 0;
+
+	printk(KERN_WARNING "toshiba_bluetooth: Failed to re-enable "
+	       "Toshiba Bluetooth\n");
+
+	return -ENODEV;
+}
+
+static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
+{
+	toshiba_bluetooth_enable(device->handle);
+}
+
+static int toshiba_bt_resume(struct acpi_device *device)
+{
+	return toshiba_bluetooth_enable(device->handle);
+}
+
+static int toshiba_bt_rfkill_add(struct acpi_device *device)
+{
+	acpi_status status;
+	acpi_integer bt_present;
+	int result = -ENODEV;
+
+	/*
+	 * Some Toshiba laptops may have a fake TOS6205 device in
+	 * their ACPI BIOS, so query the _STA method to see if there
+	 * is really anything there, before trying to enable it.
+	 */
+	status = acpi_evaluate_integer(device->handle, "_STA", NULL,
+				       &bt_present);
+
+	if (!ACPI_FAILURE(status) && bt_present) {
+		printk(KERN_INFO "Detected Toshiba ACPI Bluetooth device - "
+		      "installing RFKill handler\n");
+		result = toshiba_bluetooth_enable(device->handle);
+	}
+
+	return result;
+}
+
+static int __init toshiba_bt_rfkill_init(void)
+{
+	int result;
+
+	result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver);
+	if (result < 0) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				  "Error registering driver\n"));
+		return result;
+	}
+
+	return 0;
+}
+
+static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
+{
+	/* clean up */
+	return 0;
+}
+
+static void __exit toshiba_bt_rfkill_exit(void)
+{
+	acpi_bus_unregister_driver(&toshiba_bt_rfkill_driver);
+}
+
+module_init(toshiba_bt_rfkill_init);
+module_exit(toshiba_bt_rfkill_exit);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 177f8d7..e425a86 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -30,6 +30,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/device.h>
 #include <linux/list.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
@@ -65,6 +66,7 @@
 	acpi_handle handle;
 	wmi_notify_handler handler;
 	void *handler_data;
+	struct device *dev;
 };
 
 static struct wmi_block wmi_blocks;
@@ -195,6 +197,34 @@
 	return true;
 }
 
+/*
+ * Convert a raw GUID to the ACII string representation
+ */
+static int wmi_gtoa(const char *in, char *out)
+{
+	int i;
+
+	for (i = 3; i >= 0; i--)
+		out += sprintf(out, "%02X", in[i] & 0xFF);
+
+	out += sprintf(out, "-");
+	out += sprintf(out, "%02X", in[5] & 0xFF);
+	out += sprintf(out, "%02X", in[4] & 0xFF);
+	out += sprintf(out, "-");
+	out += sprintf(out, "%02X", in[7] & 0xFF);
+	out += sprintf(out, "%02X", in[6] & 0xFF);
+	out += sprintf(out, "-");
+	out += sprintf(out, "%02X", in[8] & 0xFF);
+	out += sprintf(out, "%02X", in[9] & 0xFF);
+	out += sprintf(out, "-");
+
+	for (i = 10; i <= 15; i++)
+		out += sprintf(out, "%02X", in[i] & 0xFF);
+
+	out = '\0';
+	return 0;
+}
+
 static bool find_guid(const char *guid_string, struct wmi_block **out)
 {
 	char tmp[16], guid_input[16];
@@ -555,6 +585,138 @@
 EXPORT_SYMBOL_GPL(wmi_has_guid);
 
 /*
+ * sysfs interface
+ */
+static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	char guid_string[37];
+	struct wmi_block *wblock;
+
+	wblock = dev_get_drvdata(dev);
+	if (!wblock)
+		return -ENOMEM;
+
+	wmi_gtoa(wblock->gblock.guid, guid_string);
+
+	return sprintf(buf, "wmi:%s\n", guid_string);
+}
+static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+
+static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	char guid_string[37];
+
+	struct wmi_block *wblock;
+
+	if (add_uevent_var(env, "MODALIAS="))
+		return -ENOMEM;
+
+	wblock = dev_get_drvdata(dev);
+	if (!wblock)
+		return -ENOMEM;
+
+	wmi_gtoa(wblock->gblock.guid, guid_string);
+
+	strcpy(&env->buf[env->buflen - 1], "wmi:");
+	memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
+	env->buflen += 40;
+
+	return 0;
+}
+
+static void wmi_dev_free(struct device *dev)
+{
+	kfree(dev);
+}
+
+static struct class wmi_class = {
+	.name = "wmi",
+	.dev_release = wmi_dev_free,
+	.dev_uevent = wmi_dev_uevent,
+};
+
+static int wmi_create_devs(void)
+{
+	int result;
+	char guid_string[37];
+	struct guid_block *gblock;
+	struct wmi_block *wblock;
+	struct list_head *p;
+	struct device *guid_dev;
+
+	/* Create devices for all the GUIDs */
+	list_for_each(p, &wmi_blocks.list) {
+		wblock = list_entry(p, struct wmi_block, list);
+
+		guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+		if (!guid_dev)
+			return -ENOMEM;
+
+		wblock->dev = guid_dev;
+
+		guid_dev->class = &wmi_class;
+		dev_set_drvdata(guid_dev, wblock);
+
+		gblock = &wblock->gblock;
+
+		wmi_gtoa(gblock->guid, guid_string);
+		dev_set_name(guid_dev, guid_string);
+
+		result = device_register(guid_dev);
+		if (result)
+			return result;
+
+		result = device_create_file(guid_dev, &dev_attr_modalias);
+		if (result)
+			return result;
+	}
+
+	return 0;
+}
+
+static void wmi_remove_devs(void)
+{
+	struct guid_block *gblock;
+	struct wmi_block *wblock;
+	struct list_head *p;
+	struct device *guid_dev;
+
+	/* Delete devices for all the GUIDs */
+	list_for_each(p, &wmi_blocks.list) {
+		wblock = list_entry(p, struct wmi_block, list);
+
+		guid_dev = wblock->dev;
+		gblock = &wblock->gblock;
+
+		device_remove_file(guid_dev, &dev_attr_modalias);
+
+		device_unregister(guid_dev);
+	}
+}
+
+static void wmi_class_exit(void)
+{
+	wmi_remove_devs();
+	class_unregister(&wmi_class);
+}
+
+static int wmi_class_init(void)
+{
+	int ret;
+
+	ret = class_register(&wmi_class);
+	if (ret)
+		return ret;
+
+	ret = wmi_create_devs();
+	if (ret)
+		wmi_class_exit();
+
+	return ret;
+}
+
+/*
  * Parse the _WDG method for the GUID data blocks
  */
 static __init acpi_status parse_wdg(acpi_handle handle)
@@ -709,10 +871,17 @@
 
 	if (result < 0) {
 		printk(KERN_INFO PREFIX "Error loading mapper\n");
-	} else {
-		printk(KERN_INFO PREFIX "Mapper loaded\n");
+		return -ENODEV;
 	}
 
+	result = wmi_class_init();
+	if (result) {
+		acpi_bus_unregister_driver(&acpi_wmi_driver);
+		return result;
+	}
+
+	printk(KERN_INFO PREFIX "Mapper loaded\n");
+
 	return result;
 }
 
@@ -721,6 +890,8 @@
 	struct list_head *p, *tmp;
 	struct wmi_block *wblock;
 
+	wmi_class_exit();
+
 	acpi_bus_unregister_driver(&acpi_wmi_driver);
 
 	list_for_each_safe(p, tmp, &wmi_blocks.list) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 83b8b5a..5314bf6 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -80,7 +80,8 @@
 
 static int pnpacpi_set_resources(struct pnp_dev *dev)
 {
-	acpi_handle handle = dev->data;
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	struct acpi_buffer buffer;
 	int ret;
 
@@ -103,7 +104,8 @@
 
 static int pnpacpi_disable_resources(struct pnp_dev *dev)
 {
-	acpi_handle handle = dev->data;
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	int ret;
 
 	dev_dbg(&dev->dev, "disable resources\n");
@@ -121,6 +123,8 @@
 #ifdef CONFIG_ACPI_SLEEP
 static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
 {
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	int power_state;
 
 	power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
@@ -128,16 +132,19 @@
 		power_state = (state.event == PM_EVENT_ON) ?
 				ACPI_STATE_D0 : ACPI_STATE_D3;
 
-	return acpi_bus_set_power((acpi_handle) dev->data, power_state);
+	return acpi_bus_set_power(handle, power_state);
 }
 
 static int pnpacpi_resume(struct pnp_dev *dev)
 {
-	return acpi_bus_set_power((acpi_handle) dev->data, ACPI_STATE_D0);
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
+
+	return acpi_bus_set_power(handle, ACPI_STATE_D0);
 }
 #endif
 
-static struct pnp_protocol pnpacpi_protocol = {
+struct pnp_protocol pnpacpi_protocol = {
 	.name	 = "Plug and Play ACPI",
 	.get	 = pnpacpi_get_resources,
 	.set	 = pnpacpi_set_resources,
@@ -147,6 +154,7 @@
 	.resume = pnpacpi_resume,
 #endif
 };
+EXPORT_SYMBOL(pnpacpi_protocol);
 
 static int __init pnpacpi_add_device(struct acpi_device *device)
 {
@@ -168,7 +176,7 @@
 	if (!dev)
 		return -ENOMEM;
 
-	dev->data = device->handle;
+	dev->data = device;
 	/* .enabled means the device can decode the resources */
 	dev->active = device->status.enabled;
 	status = acpi_get_handle(device->handle, "_SRS", &temp);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index ef3a2cd3a..5702b2c 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -465,7 +465,8 @@
 
 int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
 {
-	acpi_handle handle = dev->data;
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	acpi_status status;
 
 	pnp_dbg(&dev->dev, "parse allocated resources\n");
@@ -773,7 +774,8 @@
 
 int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
 {
-	acpi_handle handle = dev->data;
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	acpi_status status;
 	struct acpipnp_parse_option_s parse_data;
 
@@ -845,7 +847,8 @@
 int pnpacpi_build_resource_template(struct pnp_dev *dev,
 				    struct acpi_buffer *buffer)
 {
-	acpi_handle handle = dev->data;
+	struct acpi_device *acpi_dev = dev->data;
+	acpi_handle handle = acpi_dev->handle;
 	struct acpi_resource *resource;
 	int res_cnt = 0;
 	acpi_status status;
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index b35d921..2d8ac43 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -24,6 +24,7 @@
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/pnp.h>
+#include <linux/seq_file.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
@@ -33,42 +34,65 @@
 static struct proc_dir_entry *proc_pnp = NULL;
 static struct proc_dir_entry *proc_pnp_boot = NULL;
 
-static int proc_read_pnpconfig(char *buf, char **start, off_t pos,
-			       int count, int *eof, void *data)
+static int pnpconfig_proc_show(struct seq_file *m, void *v)
 {
 	struct pnp_isa_config_struc pnps;
 
 	if (pnp_bios_isapnp_config(&pnps))
 		return -EIO;
-	return snprintf(buf, count,
-			"structure_revision %d\n"
-			"number_of_CSNs %d\n"
-			"ISA_read_data_port 0x%x\n",
-			pnps.revision, pnps.no_csns, pnps.isa_rd_data_port);
+	seq_printf(m, "structure_revision %d\n"
+		      "number_of_CSNs %d\n"
+		      "ISA_read_data_port 0x%x\n",
+		   pnps.revision, pnps.no_csns, pnps.isa_rd_data_port);
+	return 0;
 }
 
-static int proc_read_escdinfo(char *buf, char **start, off_t pos,
-			      int count, int *eof, void *data)
+static int pnpconfig_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pnpconfig_proc_show, NULL);
+}
+
+static const struct file_operations pnpconfig_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pnpconfig_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int escd_info_proc_show(struct seq_file *m, void *v)
 {
 	struct escd_info_struc escd;
 
 	if (pnp_bios_escd_info(&escd))
 		return -EIO;
-	return snprintf(buf, count,
-			"min_ESCD_write_size %d\n"
+	seq_printf(m, "min_ESCD_write_size %d\n"
 			"ESCD_size %d\n"
 			"NVRAM_base 0x%x\n",
 			escd.min_escd_write_size,
 			escd.escd_size, escd.nv_storage_base);
+	return 0;
 }
 
+static int escd_info_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, escd_info_proc_show, NULL);
+}
+
+static const struct file_operations escd_info_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= escd_info_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 #define MAX_SANE_ESCD_SIZE (32*1024)
-static int proc_read_escd(char *buf, char **start, off_t pos,
-			  int count, int *eof, void *data)
+static int escd_proc_show(struct seq_file *m, void *v)
 {
 	struct escd_info_struc escd;
 	char *tmpbuf;
-	int escd_size, escd_left_to_read, n;
+	int escd_size;
 
 	if (pnp_bios_escd_info(&escd))
 		return -EIO;
@@ -76,7 +100,7 @@
 	/* sanity check */
 	if (escd.escd_size > MAX_SANE_ESCD_SIZE) {
 		printk(KERN_ERR
-		       "PnPBIOS: proc_read_escd: ESCD size reported by BIOS escd_info call is too great\n");
+		       "PnPBIOS: %s: ESCD size reported by BIOS escd_info call is too great\n", __func__);
 		return -EFBIG;
 	}
 
@@ -94,56 +118,75 @@
 
 	/* sanity check */
 	if (escd_size > MAX_SANE_ESCD_SIZE) {
-		printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size reported by"
-				" BIOS read_escd call is too great\n");
+		printk(KERN_ERR "PnPBIOS: %s: ESCD size reported by"
+				" BIOS read_escd call is too great\n", __func__);
 		kfree(tmpbuf);
 		return -EFBIG;
 	}
 
-	escd_left_to_read = escd_size - pos;
-	if (escd_left_to_read < 0)
-		escd_left_to_read = 0;
-	if (escd_left_to_read == 0)
-		*eof = 1;
-	n = min(count, escd_left_to_read);
-	memcpy(buf, tmpbuf + pos, n);
+	seq_write(m, tmpbuf, escd_size);
 	kfree(tmpbuf);
-	*start = buf;
-	return n;
+	return 0;
 }
 
-static int proc_read_legacyres(char *buf, char **start, off_t pos,
-			       int count, int *eof, void *data)
+static int escd_proc_open(struct inode *inode, struct file *file)
 {
-	/* Assume that the following won't overflow the buffer */
-	if (pnp_bios_get_stat_res(buf))
-		return -EIO;
-
-	return count;		// FIXME: Return actual length
+	return single_open(file, escd_proc_show, NULL);
 }
 
-static int proc_read_devices(char *buf, char **start, off_t pos,
-			     int count, int *eof, void *data)
+static const struct file_operations escd_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= escd_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int pnp_legacyres_proc_show(struct seq_file *m, void *v)
+{
+	void *buf;
+
+	buf = kmalloc(65536, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	if (pnp_bios_get_stat_res(buf)) {
+		kfree(buf);
+		return -EIO;
+	}
+
+	seq_write(m, buf, 65536);
+	kfree(buf);
+	return 0;
+}
+
+static int pnp_legacyres_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pnp_legacyres_proc_show, NULL);
+}
+
+static const struct file_operations pnp_legacyres_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pnp_legacyres_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int pnp_devices_proc_show(struct seq_file *m, void *v)
 {
 	struct pnp_bios_node *node;
 	u8 nodenum;
-	char *p = buf;
-
-	if (pos >= 0xff)
-		return 0;
 
 	node = kzalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -ENOMEM;
 
-	for (nodenum = pos; nodenum < 0xff;) {
+	for (nodenum = 0; nodenum < 0xff;) {
 		u8 thisnodenum = nodenum;
-		/* 26 = the number of characters per line sprintf'ed */
-		if ((p - buf + 26) > count)
-			break;
+
 		if (pnp_bios_get_dev_node(&nodenum, PNPMODE_DYNAMIC, node))
 			break;
-		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
+		seq_printf(m, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
 			     node->handle, node->eisa_id,
 			     node->type_code[0], node->type_code[1],
 			     node->type_code[2], node->flags);
@@ -153,20 +196,29 @@
 			       "PnPBIOS: proc_read_devices:",
 			       (unsigned int)nodenum,
 			       (unsigned int)thisnodenum);
-			*eof = 1;
 			break;
 		}
 	}
 	kfree(node);
-	if (nodenum == 0xff)
-		*eof = 1;
-	*start = (char *)((off_t) nodenum - pos);
-	return p - buf;
+	return 0;
 }
 
-static int proc_read_node(char *buf, char **start, off_t pos,
-			  int count, int *eof, void *data)
+static int pnp_devices_proc_open(struct inode *inode, struct file *file)
 {
+	return single_open(file, pnp_devices_proc_show, NULL);
+}
+
+static const struct file_operations pnp_devices_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pnp_devices_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int pnpbios_proc_show(struct seq_file *m, void *v)
+{
+	void *data = m->private;
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
 	u8 nodenum = (long)data;
@@ -180,14 +232,20 @@
 		return -EIO;
 	}
 	len = node->size - sizeof(struct pnp_bios_node);
-	memcpy(buf, node->data, len);
+	seq_write(m, node->data, len);
 	kfree(node);
-	return len;
+	return 0;
 }
 
-static int proc_write_node(struct file *file, const char __user * buf,
-			   unsigned long count, void *data)
+static int pnpbios_proc_open(struct inode *inode, struct file *file)
 {
+	return single_open(file, pnpbios_proc_show, PDE(inode)->data);
+}
+
+static ssize_t pnpbios_proc_write(struct file *file, const char __user *buf,
+				  size_t count, loff_t *pos)
+{
+	void *data = PDE(file->f_path.dentry->d_inode)->data;
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
 	u8 nodenum = (long)data;
@@ -218,34 +276,33 @@
 	return ret;
 }
 
+static const struct file_operations pnpbios_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= pnpbios_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= pnpbios_proc_write,
+};
+
 int pnpbios_interface_attach_device(struct pnp_bios_node *node)
 {
 	char name[3];
-	struct proc_dir_entry *ent;
 
 	sprintf(name, "%02x", node->handle);
 
 	if (!proc_pnp)
 		return -EIO;
 	if (!pnpbios_dont_use_current_config) {
-		ent = create_proc_entry(name, 0, proc_pnp);
-		if (ent) {
-			ent->read_proc = proc_read_node;
-			ent->write_proc = proc_write_node;
-			ent->data = (void *)(long)(node->handle);
-		}
+		proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_fops,
+				 (void *)(long)(node->handle));
 	}
 
 	if (!proc_pnp_boot)
 		return -EIO;
-	ent = create_proc_entry(name, 0, proc_pnp_boot);
-	if (ent) {
-		ent->read_proc = proc_read_node;
-		ent->write_proc = proc_write_node;
-		ent->data = (void *)(long)(node->handle + 0x100);
+	if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_fops,
+			     (void *)(long)(node->handle + 0x100)))
 		return 0;
-	}
-
 	return -EIO;
 }
 
@@ -262,14 +319,11 @@
 	proc_pnp_boot = proc_mkdir("boot", proc_pnp);
 	if (!proc_pnp_boot)
 		return -EIO;
-	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
-	create_proc_read_entry("configuration_info", 0, proc_pnp,
-			       proc_read_pnpconfig, NULL);
-	create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo,
-			       NULL);
-	create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL);
-	create_proc_read_entry("legacy_device_resources", 0, proc_pnp,
-			       proc_read_legacyres, NULL);
+	proc_create("devices", 0, proc_pnp, &pnp_devices_proc_fops);
+	proc_create("configuration_info", 0, proc_pnp, &pnpconfig_proc_fops);
+	proc_create("escd_info", 0, proc_pnp, &escd_info_proc_fops);
+	proc_create("escd", S_IRUSR, proc_pnp, &escd_proc_fops);
+	proc_create("legacy_device_resources", 0, proc_pnp, &pnp_legacyres_proc_fops);
 
 	return 0;
 }
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
new file mode 100644
index 0000000..0471955
--- /dev/null
+++ b/drivers/regulator/88pm8607.c
@@ -0,0 +1,685 @@
+/*
+ * Regulators driver for Marvell 88PM8607
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * 	Haojian Zhuang <haojian.zhuang@marvell.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/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/88pm8607.h>
+
+struct pm8607_regulator_info {
+	struct regulator_desc	desc;
+	struct pm8607_chip	*chip;
+	struct regulator_dev	*regulator;
+
+	int	min_uV;
+	int	max_uV;
+	int	step_uV;
+	int	vol_reg;
+	int	vol_shift;
+	int	vol_nbits;
+	int	update_reg;
+	int	update_bit;
+	int	enable_reg;
+	int	enable_bit;
+	int	slope_double;
+};
+
+static inline int check_range(struct pm8607_regulator_info *info,
+				int min_uV, int max_uV)
+{
+	if (max_uV < info->min_uV || min_uV > info->max_uV || min_uV > max_uV)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	uint8_t chip_id = info->chip->chip_id;
+	int ret = -EINVAL;
+
+	switch (info->desc.id) {
+	case PM8607_ID_BUCK1:
+		ret = (index < 0x1d) ? (index * 25000 + 800000) :
+			((index < 0x20) ? 1500000 :
+			((index < 0x40) ? ((index - 0x20) * 25000) :
+			-EINVAL));
+		break;
+	case PM8607_ID_BUCK3:
+		ret = (index < 0x3d) ? (index * 25000) :
+			((index < 0x40) ? 1500000 : -EINVAL);
+		if (ret < 0)
+			break;
+		if (info->slope_double)
+			ret <<= 1;
+		break;
+	case PM8607_ID_LDO1:
+		ret = (index == 0) ? 1800000 :
+			((index == 1) ? 1200000 :
+			((index == 2) ? 2800000 : -EINVAL));
+		break;
+	case PM8607_ID_LDO5:
+		ret = (index == 0) ? 2900000 :
+			((index == 1) ? 3000000 :
+			((index == 2) ? 3100000 : 3300000));
+		break;
+	case PM8607_ID_LDO7:
+	case PM8607_ID_LDO8:
+		ret = (index < 3) ? (index * 50000 + 1800000) :
+			((index < 8) ? (index * 50000 + 2550000) :
+			 -EINVAL);
+		break;
+	case PM8607_ID_LDO12:
+		ret = (index < 2) ? (index * 100000 + 1800000) :
+			((index < 7) ? (index * 100000 + 2500000) :
+			((index == 7) ? 3300000 : 1200000));
+		break;
+	case PM8607_ID_LDO2:
+	case PM8607_ID_LDO3:
+	case PM8607_ID_LDO9:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 8) ? (index * 50000 + 2550000) :
+				 -EINVAL);
+			break;
+		case PM8607_CHIP_B0:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 7) ? (index * 50000 + 2550000) :
+				3300000);
+			break;
+		}
+		break;
+	case PM8607_ID_LDO4:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 8) ? (index * 50000 + 2550000) :
+				 -EINVAL);
+			break;
+		case PM8607_CHIP_B0:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 6) ? (index * 50000 + 2550000) :
+				((index == 6) ? 2900000 : 3300000));
+			break;
+		}
+		break;
+	case PM8607_ID_LDO6:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 8) ? (index * 50000 + 2450000) :
+				-EINVAL);
+			break;
+		case PM8607_CHIP_B0:
+			ret = (index < 2) ? (index * 50000 + 1800000) :
+				((index < 7) ? (index * 50000 + 2500000) :
+				3300000);
+			break;
+		}
+		break;
+	case PM8607_ID_LDO10:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 8) ? (index * 50000 + 2550000) :
+				1200000);
+			break;
+		case PM8607_CHIP_B0:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 7) ? (index * 50000 + 2550000) :
+				((index == 7) ? 3300000 : 1200000));
+			break;
+		}
+		break;
+	case PM8607_ID_LDO14:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			ret = (index < 3) ? (index * 50000 + 1800000) :
+				((index < 8) ? (index * 50000 + 2550000) :
+				 -EINVAL);
+			break;
+		case PM8607_CHIP_B0:
+			ret = (index < 2) ? (index * 50000 + 1800000) :
+				((index < 7) ? (index * 50000 + 2600000) :
+				3300000);
+			break;
+		}
+		break;
+	}
+	return ret;
+}
+
+static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	uint8_t chip_id = info->chip->chip_id;
+	int val = -ENOENT;
+	int ret;
+
+	switch (info->desc.id) {
+	case PM8607_ID_BUCK1:
+		if (min_uV >= 800000) 		/* 800mV ~ 1500mV / 25mV */
+			val = (min_uV - 775001) / 25000;
+		else {				/* 25mV ~ 775mV / 25mV */
+			val = (min_uV + 249999) / 25000;
+			val += 32;
+		}
+		break;
+	case PM8607_ID_BUCK3:
+		if (info->slope_double)
+			min_uV = min_uV >> 1;
+		val = (min_uV + 249999) / 25000; /* 0mV ~ 1500mV / 25mV */
+
+		break;
+	case PM8607_ID_LDO1:
+		if (min_uV > 1800000)
+			val = 2;
+		else if (min_uV > 1200000)
+			val = 0;
+		else
+			val = 1;
+		break;
+	case PM8607_ID_LDO5:
+		if (min_uV > 3100000)
+			val = 3;
+		else				/* 2900mV ~ 3100mV / 100mV */
+			val = (min_uV - 2800001) / 100000;
+		break;
+	case PM8607_ID_LDO7:
+	case PM8607_ID_LDO8:
+		if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+			if (min_uV <= 1800000)
+				val = 0;	/* 1800mv */
+			else if (min_uV <= 1900000)
+				val = (min_uV - 1750001) / 50000;
+			else
+				val = 3;	/* 2700mV */
+		} else {		 /* 2700mV ~ 2900mV / 50mV */
+			if (min_uV <= 2900000) {
+				val = (min_uV - 2650001) / 50000;
+				val += 3;
+			} else
+				val = -EINVAL;
+		}
+		break;
+	case PM8607_ID_LDO10:
+		if (min_uV > 2850000)
+			val = 7;
+		else if (min_uV <= 1200000)
+			val = 8;
+		else if (min_uV < 2700000)	/* 1800mV ~ 1900mV / 50mV */
+			val = (min_uV - 1750001) / 50000;
+		else {				/* 2700mV ~ 2850mV / 50mV */
+			val = (min_uV - 2650001) / 50000;
+			val += 3;
+		}
+		break;
+	case PM8607_ID_LDO12:
+		if (min_uV < 2700000) {		/* 1800mV ~ 1900mV / 100mV */
+			if (min_uV <= 1200000)
+				val = 8;	/* 1200mV */
+			else if (min_uV <= 1800000)
+				val = 0;	/* 1800mV */
+			else if (min_uV <= 1900000)
+				val = (min_uV - 1700001) / 100000;
+			else
+				val = 2;	/* 2700mV */
+		} else {			/* 2700mV ~ 3100mV / 100mV */
+			if (min_uV <= 3100000) {
+				val = (min_uV - 2600001) / 100000;
+				val += 2;
+			} else if (min_uV <= 3300000)
+				val = 7;
+			else
+				val = -EINVAL;
+		}
+		break;
+	case PM8607_ID_LDO2:
+	case PM8607_ID_LDO3:
+	case PM8607_ID_LDO9:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			if (min_uV < 2700000)	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2700mV */
+			else {			/* 2700mV ~ 2900mV / 50mV */
+				if (min_uV <= 2900000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 3;
+				} else
+					val = -EINVAL;
+			}
+			break;
+		case PM8607_CHIP_B0:
+			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2700mV */
+			} else {		 /* 2700mV ~ 2850mV / 50mV */
+				if (min_uV <= 2850000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 3;
+				} else if (min_uV <= 3300000)
+					val = 7;
+				else
+					val = -EINVAL;
+			}
+			break;
+		}
+		break;
+	case PM8607_ID_LDO4:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			if (min_uV < 2700000)	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2700mV */
+			else {			/* 2700mV ~ 2900mV / 50mV */
+				if (min_uV <= 2900000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 3;
+				} else
+					val = -EINVAL;
+			}
+			break;
+		case PM8607_CHIP_B0:
+			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2700mV */
+			} else {		 /* 2700mV ~ 2800mV / 50mV */
+				if (min_uV <= 2850000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 3;
+				} else if (min_uV <= 2900000)
+					val = 6;
+				else if (min_uV <= 3300000)
+					val = 7;
+				else
+					val = -EINVAL;
+			}
+			break;
+		}
+		break;
+	case PM8607_ID_LDO6:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			if (min_uV < 2600000) {	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2600mV */
+			} else {		/* 2600mV ~ 2800mV / 50mV */
+				if (min_uV <= 2800000) {
+					val = (min_uV - 2550001) / 50000;
+					val += 3;
+				} else
+					val = -EINVAL;
+			}
+			break;
+		case PM8607_CHIP_B0:
+			if (min_uV < 2600000) {	/* 1800mV ~ 1850mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1850000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 2;	/* 2600mV */
+			} else {		/* 2600mV ~ 2800mV / 50mV */
+				if (min_uV <= 2800000) {
+					val = (min_uV - 2550001) / 50000;
+					val += 2;
+				} else if (min_uV <= 3300000)
+					val = 7;
+				else
+					val = -EINVAL;
+			}
+			break;
+		}
+		break;
+	case PM8607_ID_LDO14:
+		switch (chip_id) {
+		case PM8607_CHIP_A0:
+		case PM8607_CHIP_A1:
+			if (min_uV < 2700000) {	/* 1800mV ~ 1900mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1900000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 3;	/* 2700mV */
+			} else {		 /* 2700mV ~ 2900mV / 50mV */
+				if (min_uV <= 2900000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 3;
+				} else
+					val = -EINVAL;
+			}
+			break;
+		case PM8607_CHIP_B0:
+			if (min_uV < 2700000) {	/* 1800mV ~ 1850mV / 50mV */
+				if (min_uV <= 1800000)
+					val = 0;
+				else if (min_uV <= 1850000)
+					val = (min_uV - 1750001) / 50000;
+				else
+					val = 2;	/* 2700mV */
+			} else {		 /* 2700mV ~ 2900mV / 50mV */
+				if (min_uV <= 2900000) {
+					val = (min_uV - 2650001) / 50000;
+					val += 2;
+				} else if (min_uV <= 3300000)
+					val = 7;
+				else
+					val = -EINVAL;
+			}
+			break;
+		}
+		break;
+	}
+	if (val >= 0) {
+		ret = pm8607_list_voltage(rdev, val);
+		if (ret > max_uV) {
+			pr_err("exceed voltage range (%d %d) uV",
+				min_uV, max_uV);
+			return -EINVAL;
+		}
+	} else
+		pr_err("invalid voltage range (%d %d) uV", min_uV, max_uV);
+	return val;
+}
+
+static int pm8607_set_voltage(struct regulator_dev *rdev,
+			      int min_uV, int max_uV)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	struct pm8607_chip *chip = info->chip;
+	uint8_t val, mask;
+	int ret;
+
+	if (check_range(info, min_uV, max_uV)) {
+		pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	ret = choose_voltage(rdev, min_uV, max_uV);
+	if (ret < 0)
+		return -EINVAL;
+	val = (uint8_t)(ret << info->vol_shift);
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+
+	ret = pm8607_set_bits(chip, info->vol_reg, mask, val);
+	if (ret)
+		return ret;
+	switch (info->desc.id) {
+	case PM8607_ID_BUCK1:
+	case PM8607_ID_BUCK3:
+		ret = pm8607_set_bits(chip, info->update_reg,
+				      1 << info->update_bit,
+				      1 << info->update_bit);
+		break;
+	}
+	return ret;
+}
+
+static int pm8607_get_voltage(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	struct pm8607_chip *chip = info->chip;
+	uint8_t val, mask;
+	int ret;
+
+	ret = pm8607_reg_read(chip, info->vol_reg);
+	if (ret < 0)
+		return ret;
+
+	mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
+	val = ((unsigned char)ret & mask) >> info->vol_shift;
+
+	return pm8607_list_voltage(rdev, val);
+}
+
+static int pm8607_enable(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	struct pm8607_chip *chip = info->chip;
+
+	return pm8607_set_bits(chip, info->enable_reg,
+			       1 << info->enable_bit,
+			       1 << info->enable_bit);
+}
+
+static int pm8607_disable(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	struct pm8607_chip *chip = info->chip;
+
+	return pm8607_set_bits(chip, info->enable_reg,
+			       1 << info->enable_bit, 0);
+}
+
+static int pm8607_is_enabled(struct regulator_dev *rdev)
+{
+	struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
+	struct pm8607_chip *chip = info->chip;
+	int ret;
+
+	ret = pm8607_reg_read(chip, info->enable_reg);
+	if (ret < 0)
+		return ret;
+
+	return !!((unsigned char)ret & (1 << info->enable_bit));
+}
+
+static struct regulator_ops pm8607_regulator_ops = {
+	.set_voltage	= pm8607_set_voltage,
+	.get_voltage	= pm8607_get_voltage,
+	.enable		= pm8607_enable,
+	.disable	= pm8607_disable,
+	.is_enabled	= pm8607_is_enabled,
+};
+
+#define PM8607_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \
+{									\
+	.desc	= {							\
+		.name	= "BUCK" #_id,					\
+		.ops	= &pm8607_regulator_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= PM8607_ID_BUCK##_id,				\
+		.owner	= THIS_MODULE,					\
+	},								\
+	.min_uV		= (min) * 1000,					\
+	.max_uV		= (max) * 1000,					\
+	.step_uV	= (step) * 1000,				\
+	.vol_reg	= PM8607_##vreg,				\
+	.vol_shift	= (0),						\
+	.vol_nbits	= (nbits),					\
+	.update_reg	= PM8607_##ureg,				\
+	.update_bit	= (ubit),					\
+	.enable_reg	= PM8607_##ereg,				\
+	.enable_bit	= (ebit),					\
+	.slope_double	= (0),						\
+}
+
+#define PM8607_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit)	\
+{									\
+	.desc	= {							\
+		.name	= "LDO" #_id,					\
+		.ops	= &pm8607_regulator_ops,			\
+		.type	= REGULATOR_VOLTAGE,				\
+		.id	= PM8607_ID_LDO##_id,				\
+		.owner	= THIS_MODULE,					\
+	},								\
+	.min_uV		= (min) * 1000,					\
+	.max_uV		= (max) * 1000,					\
+	.step_uV	= (step) * 1000,				\
+	.vol_reg	= PM8607_##vreg,				\
+	.vol_shift	= (shift),					\
+	.vol_nbits	= (nbits),					\
+	.enable_reg	= PM8607_##ereg,				\
+	.enable_bit	= (ebit),					\
+	.slope_double	= (0),						\
+}
+
+static struct pm8607_regulator_info pm8607_regulator_info[] = {
+	PM8607_DVC(1, 0, 1500, 25, BUCK1, 6, GO, 0, SUPPLIES_EN11, 0),
+	PM8607_DVC(3, 0, 1500, 25, BUCK3, 6, GO, 2, SUPPLIES_EN11, 2),
+
+	PM8607_LDO(1 , 1200, 2800, 0, LDO1 , 0, 2, SUPPLIES_EN11, 3),
+	PM8607_LDO(2 , 1800, 3300, 0, LDO2 , 0, 3, SUPPLIES_EN11, 4),
+	PM8607_LDO(3 , 1800, 3300, 0, LDO3 , 0, 3, SUPPLIES_EN11, 5),
+	PM8607_LDO(4 , 1800, 3300, 0, LDO4 , 0, 3, SUPPLIES_EN11, 6),
+	PM8607_LDO(5 , 2900, 3300, 0, LDO5 , 0, 2, SUPPLIES_EN11, 7),
+	PM8607_LDO(6 , 1800, 3300, 0, LDO6 , 0, 3, SUPPLIES_EN12, 0),
+	PM8607_LDO(7 , 1800, 2900, 0, LDO7 , 0, 3, SUPPLIES_EN12, 1),
+	PM8607_LDO(8 , 1800, 2900, 0, LDO8 , 0, 3, SUPPLIES_EN12, 2),
+	PM8607_LDO(9 , 1800, 3300, 0, LDO9 , 0, 3, SUPPLIES_EN12, 3),
+	PM8607_LDO(10, 1200, 3300, 0, LDO10, 0, 4, SUPPLIES_EN11, 4),
+	PM8607_LDO(12, 1200, 3300, 0, LDO12, 0, 4, SUPPLIES_EN11, 5),
+	PM8607_LDO(14, 1800, 3300, 0, LDO14, 0, 3, SUPPLIES_EN11, 6),
+};
+
+static inline struct pm8607_regulator_info *find_regulator_info(int id)
+{
+	struct pm8607_regulator_info *info;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
+		info = &pm8607_regulator_info[i];
+		if (info->desc.id == id)
+			return info;
+	}
+	return NULL;
+}
+
+static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+{
+	struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm8607_platform_data *pdata = chip->dev->platform_data;
+	struct pm8607_regulator_info *info = NULL;
+
+	info = find_regulator_info(pdev->id);
+	if (info == NULL) {
+		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+		return -EINVAL;
+	}
+
+	info->chip = chip;
+
+	info->regulator = regulator_register(&info->desc, &pdev->dev,
+					     pdata->regulator[pdev->id], info);
+	if (IS_ERR(info->regulator)) {
+		dev_err(&pdev->dev, "failed to register regulator %s\n",
+			info->desc.name);
+		return PTR_ERR(info->regulator);
+	}
+
+	/* check DVC ramp slope double */
+	if (info->desc.id == PM8607_ID_BUCK3)
+		if (info->chip->buck3_double)
+			info->slope_double = 1;
+
+	platform_set_drvdata(pdev, info);
+	return 0;
+}
+
+static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+{
+	struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
+
+	regulator_unregister(info->regulator);
+	return 0;
+}
+
+#define PM8607_REGULATOR_DRIVER(_name)				\
+{								\
+	.driver		= {					\
+		.name	= "88pm8607-" #_name,			\
+		.owner	= THIS_MODULE,				\
+	},							\
+	.probe		= pm8607_regulator_probe,		\
+	.remove		= __devexit_p(pm8607_regulator_remove),	\
+}
+
+static struct platform_driver pm8607_regulator_driver[] = {
+	PM8607_REGULATOR_DRIVER(buck1),
+	PM8607_REGULATOR_DRIVER(buck2),
+	PM8607_REGULATOR_DRIVER(buck3),
+	PM8607_REGULATOR_DRIVER(ldo1),
+	PM8607_REGULATOR_DRIVER(ldo2),
+	PM8607_REGULATOR_DRIVER(ldo3),
+	PM8607_REGULATOR_DRIVER(ldo4),
+	PM8607_REGULATOR_DRIVER(ldo5),
+	PM8607_REGULATOR_DRIVER(ldo6),
+	PM8607_REGULATOR_DRIVER(ldo7),
+	PM8607_REGULATOR_DRIVER(ldo8),
+	PM8607_REGULATOR_DRIVER(ldo9),
+	PM8607_REGULATOR_DRIVER(ldo10),
+	PM8607_REGULATOR_DRIVER(ldo12),
+	PM8607_REGULATOR_DRIVER(ldo14),
+};
+
+static int __init pm8607_regulator_init(void)
+{
+	int i, count, ret;
+
+	count = ARRAY_SIZE(pm8607_regulator_driver);
+	for (i = 0; i < count; i++) {
+		ret = platform_driver_register(&pm8607_regulator_driver[i]);
+		if (ret != 0)
+			pr_err("Failed to register regulator driver: %d\n",
+				ret);
+	}
+	return 0;
+}
+subsys_initcall(pm8607_regulator_init);
+
+static void __exit pm8607_regulator_exit(void)
+{
+	int i, count;
+
+	count = ARRAY_SIZE(pm8607_regulator_driver);
+	for (i = 0; i < count; i++)
+		platform_driver_unregister(&pm8607_regulator_driver[i]);
+}
+module_exit(pm8607_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
+MODULE_ALIAS("platform:88pm8607-regulator");
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 7cfdd65..262f62e 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -69,6 +69,13 @@
 	  regulator via I2C bus. The provided regulator is suitable
 	  for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX8660
+	tristate "Maxim 8660/8661 voltage regulator"
+	depends on I2C
+	help
+	  This driver controls a Maxim 8660/8661 voltage output
+	  regulator via I2C bus.
+
 config REGULATOR_TWL4030
 	bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
 	depends on TWL4030_CORE
@@ -157,5 +164,11 @@
 	  three step-down converters and two general-purpose LDO voltage regulators.
 	  It supports TI's software based Class-2 SmartReflex implementation.
 
+config REGULATOR_88PM8607
+	bool "Marvell 88PM8607 Power regulators"
+	depends on MFD_88PM8607=y
+	help
+	  This driver supports 88PM8607 voltage regulator chips.
+
 endif
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 9ae3cc4..b3c806c 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
@@ -20,10 +21,11 @@
 obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
-obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o
+obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
+obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c
index 49aeee8..b349db4 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -81,7 +81,7 @@
 #define LDO_C_VOLTAGE 2650000
 #define LDO_D_VOLTAGE 2650000
 
-static const int const ldo_e_buck_typ_voltages[] = {
+static const int ldo_e_buck_typ_voltages[] = {
 	1800000,
 	1400000,
 	1300000,
@@ -91,7 +91,7 @@
 	900000,
 };
 
-static const int const ldo_f_typ_voltages[] = {
+static const int ldo_f_typ_voltages[] = {
 	1800000,
 	1400000,
 	1300000,
@@ -102,21 +102,21 @@
 	2650000,
 };
 
-static const int const ldo_g_typ_voltages[] = {
+static const int ldo_g_typ_voltages[] = {
 	2850000,
 	2750000,
 	1800000,
 	1500000,
 };
 
-static const int const ldo_h_typ_voltages[] = {
+static const int ldo_h_typ_voltages[] = {
 	2750000,
 	1800000,
 	1500000,
 	1200000,
 };
 
-static const int const ldo_k_typ_voltages[] = {
+static const int ldo_k_typ_voltages[] = {
 	2750000,
 	1800000,
 };
@@ -241,24 +241,12 @@
 	 * LDO D is a special regulator. When it is disabled, the entire
 	 * system is shut down. So this is handled specially.
 	 */
+	pr_info("Called ab3100_disable_regulator\n");
 	if (abreg->regreg == AB3100_LDO_D) {
-		int i;
-
 		dev_info(&reg->dev, "disabling LDO D - shut down system\n");
-		/*
-		 * Set regulators to default values, ignore any errors,
-		 * we're going DOWN
-		 */
-		for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
-			(void) ab3100_set_register_interruptible(abreg->ab3100,
-					ab3100_reg_init_order[i],
-					abreg->plfdata->reg_initvals[i]);
-		}
-
 		/* Setting LDO D to 0x00 cuts the power to the SoC */
 		return ab3100_set_register_interruptible(abreg->ab3100,
 							 AB3100_LDO_D, 0x00U);
-
 	}
 
 	/*
@@ -607,13 +595,6 @@
 		}
 	}
 
-	if (err) {
-		dev_err(&pdev->dev,
-			"LDO D regulator initialization failed with error %d\n",
-			err);
-		return err;
-	}
-
 	/* Register the regulators */
 	for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
 		struct ab3100_regulator *reg = &ab3100_regulators[i];
@@ -688,7 +669,7 @@
 
 static __exit void ab3100_regulators_exit(void)
 {
-	platform_driver_register(&ab3100_regulators_driver);
+	platform_driver_unregister(&ab3100_regulators_driver);
 }
 
 subsys_initcall(ab3100_regulators_init);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index efe568d..686ef27 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -66,6 +66,16 @@
 static void _notifier_call_chain(struct regulator_dev *rdev,
 				  unsigned long event, void *data);
 
+static const char *rdev_get_name(struct regulator_dev *rdev)
+{
+	if (rdev->constraints && rdev->constraints->name)
+		return rdev->constraints->name;
+	else if (rdev->desc->name)
+		return rdev->desc->name;
+	else
+		return "";
+}
+
 /* gets the regulator for a given consumer device */
 static struct regulator *get_device_regulator(struct device *dev)
 {
@@ -96,12 +106,12 @@
 
 	if (!rdev->constraints) {
 		printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-		       rdev->desc->name);
+		       rdev_get_name(rdev));
 		return -ENODEV;
 	}
 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
 		printk(KERN_ERR "%s: operation not allowed for %s\n",
-		       __func__, rdev->desc->name);
+		       __func__, rdev_get_name(rdev));
 		return -EPERM;
 	}
 
@@ -124,12 +134,12 @@
 
 	if (!rdev->constraints) {
 		printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-		       rdev->desc->name);
+		       rdev_get_name(rdev));
 		return -ENODEV;
 	}
 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) {
 		printk(KERN_ERR "%s: operation not allowed for %s\n",
-		       __func__, rdev->desc->name);
+		       __func__, rdev_get_name(rdev));
 		return -EPERM;
 	}
 
@@ -159,17 +169,17 @@
 
 	if (!rdev->constraints) {
 		printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-		       rdev->desc->name);
+		       rdev_get_name(rdev));
 		return -ENODEV;
 	}
 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) {
 		printk(KERN_ERR "%s: operation not allowed for %s\n",
-		       __func__, rdev->desc->name);
+		       __func__, rdev_get_name(rdev));
 		return -EPERM;
 	}
 	if (!(rdev->constraints->valid_modes_mask & mode)) {
 		printk(KERN_ERR "%s: invalid mode %x for %s\n",
-		       __func__, mode, rdev->desc->name);
+		       __func__, mode, rdev_get_name(rdev));
 		return -EINVAL;
 	}
 	return 0;
@@ -180,12 +190,12 @@
 {
 	if (!rdev->constraints) {
 		printk(KERN_ERR "%s: no constraints for %s\n", __func__,
-		       rdev->desc->name);
+		       rdev_get_name(rdev));
 		return -ENODEV;
 	}
 	if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) {
 		printk(KERN_ERR "%s: operation not allowed for %s\n",
-		       __func__, rdev->desc->name);
+		       __func__, rdev_get_name(rdev));
 		return -EPERM;
 	}
 	return 0;
@@ -230,16 +240,8 @@
 			     struct device_attribute *attr, char *buf)
 {
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
-	const char *name;
 
-	if (rdev->constraints && rdev->constraints->name)
-		name = rdev->constraints->name;
-	else if (rdev->desc->name)
-		name = rdev->desc->name;
-	else
-		name = "";
-
-	return sprintf(buf, "%s\n", name);
+	return sprintf(buf, "%s\n", rdev_get_name(rdev));
 }
 
 static ssize_t regulator_print_opmode(char *buf, int mode)
@@ -388,7 +390,7 @@
 
 	mutex_lock(&rdev->mutex);
 	list_for_each_entry(regulator, &rdev->consumer_list, list)
-	    uA += regulator->uA_load;
+		uA += regulator->uA_load;
 	mutex_unlock(&rdev->mutex);
 	return sprintf(buf, "%d\n", uA);
 }
@@ -563,7 +565,7 @@
 
 	/* calc total requested load */
 	list_for_each_entry(sibling, &rdev->consumer_list, list)
-	    current_uA += sibling->uA_load;
+		current_uA += sibling->uA_load;
 
 	/* now get the optimum mode for our new total regulator load */
 	mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV,
@@ -579,10 +581,29 @@
 	struct regulator_state *rstate)
 {
 	int ret = 0;
+	bool can_set_state;
 
-	/* enable & disable are mandatory for suspend control */
-	if (!rdev->desc->ops->set_suspend_enable ||
-		!rdev->desc->ops->set_suspend_disable) {
+	can_set_state = rdev->desc->ops->set_suspend_enable &&
+		rdev->desc->ops->set_suspend_disable;
+
+	/* If we have no suspend mode configration don't set anything;
+	 * only warn if the driver actually makes the suspend mode
+	 * configurable.
+	 */
+	if (!rstate->enabled && !rstate->disabled) {
+		if (can_set_state)
+			printk(KERN_WARNING "%s: No configuration for %s\n",
+			       __func__, rdev_get_name(rdev));
+		return 0;
+	}
+
+	if (rstate->enabled && rstate->disabled) {
+		printk(KERN_ERR "%s: invalid configuration for %s\n",
+		       __func__, rdev_get_name(rdev));
+		return -EINVAL;
+	}
+
+	if (!can_set_state) {
 		printk(KERN_ERR "%s: no way to set suspend state\n",
 			__func__);
 		return -EINVAL;
@@ -641,25 +662,43 @@
 {
 	struct regulation_constraints *constraints = rdev->constraints;
 	char buf[80];
-	int count;
+	int count = 0;
+	int ret;
 
-	if (rdev->desc->type == REGULATOR_VOLTAGE) {
+	if (constraints->min_uV && constraints->max_uV) {
 		if (constraints->min_uV == constraints->max_uV)
-			count = sprintf(buf, "%d mV ",
-					constraints->min_uV / 1000);
+			count += sprintf(buf + count, "%d mV ",
+					 constraints->min_uV / 1000);
 		else
-			count = sprintf(buf, "%d <--> %d mV ",
-					constraints->min_uV / 1000,
-					constraints->max_uV / 1000);
-	} else {
-		if (constraints->min_uA == constraints->max_uA)
-			count = sprintf(buf, "%d mA ",
-					constraints->min_uA / 1000);
-		else
-			count = sprintf(buf, "%d <--> %d mA ",
-					constraints->min_uA / 1000,
-					constraints->max_uA / 1000);
+			count += sprintf(buf + count, "%d <--> %d mV ",
+					 constraints->min_uV / 1000,
+					 constraints->max_uV / 1000);
 	}
+
+	if (!constraints->min_uV ||
+	    constraints->min_uV != constraints->max_uV) {
+		ret = _regulator_get_voltage(rdev);
+		if (ret > 0)
+			count += sprintf(buf + count, "at %d mV ", ret / 1000);
+	}
+
+	if (constraints->min_uA && constraints->max_uA) {
+		if (constraints->min_uA == constraints->max_uA)
+			count += sprintf(buf + count, "%d mA ",
+					 constraints->min_uA / 1000);
+		else
+			count += sprintf(buf + count, "%d <--> %d mA ",
+					 constraints->min_uA / 1000,
+					 constraints->max_uA / 1000);
+	}
+
+	if (!constraints->min_uA ||
+	    constraints->min_uA != constraints->max_uA) {
+		ret = _regulator_get_current_limit(rdev);
+		if (ret > 0)
+			count += sprintf(buf + count, "at %d uA ", ret / 1000);
+	}
+
 	if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
 		count += sprintf(buf + count, "fast ");
 	if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
@@ -669,33 +708,30 @@
 	if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
 		count += sprintf(buf + count, "standby");
 
-	printk(KERN_INFO "regulator: %s: %s\n", rdev->desc->name, buf);
+	printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf);
 }
 
-/**
- * set_machine_constraints - sets regulator constraints
- * @rdev: regulator source
- * @constraints: constraints to apply
- *
- * Allows platform initialisation code to define and constrain
- * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
- * Constraints *must* be set by platform code in order for some
- * regulator operations to proceed i.e. set_voltage, set_current_limit,
- * set_mode.
- */
-static int set_machine_constraints(struct regulator_dev *rdev,
+static int machine_constraints_voltage(struct regulator_dev *rdev,
 	struct regulation_constraints *constraints)
 {
-	int ret = 0;
-	const char *name;
 	struct regulator_ops *ops = rdev->desc->ops;
+	const char *name = rdev_get_name(rdev);
+	int ret;
 
-	if (constraints->name)
-		name = constraints->name;
-	else if (rdev->desc->name)
-		name = rdev->desc->name;
-	else
-		name = "regulator";
+	/* do we need to apply the constraint voltage */
+	if (rdev->constraints->apply_uV &&
+		rdev->constraints->min_uV == rdev->constraints->max_uV &&
+		ops->set_voltage) {
+		ret = ops->set_voltage(rdev,
+			rdev->constraints->min_uV, rdev->constraints->max_uV);
+			if (ret < 0) {
+				printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
+				       __func__,
+				       rdev->constraints->min_uV, name);
+				rdev->constraints = NULL;
+				return ret;
+			}
+	}
 
 	/* constrain machine-level voltage specs to fit
 	 * the actual range supported by this regulator.
@@ -719,14 +755,13 @@
 
 		/* voltage constraints are optional */
 		if ((cmin == 0) && (cmax == 0))
-			goto out;
+			return 0;
 
 		/* else require explicit machine-level constraints */
 		if (cmin <= 0 || cmax <= 0 || cmax < cmin) {
 			pr_err("%s: %s '%s' voltage constraints\n",
 				       __func__, "invalid", name);
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 
 		/* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
@@ -748,8 +783,7 @@
 		if (max_uV < min_uV) {
 			pr_err("%s: %s '%s' voltage constraints\n",
 				       __func__, "unsupportable", name);
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 
 		/* use regulator's subset of machine constraints */
@@ -767,22 +801,34 @@
 		}
 	}
 
+	return 0;
+}
+
+/**
+ * set_machine_constraints - sets regulator constraints
+ * @rdev: regulator source
+ * @constraints: constraints to apply
+ *
+ * Allows platform initialisation code to define and constrain
+ * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
+ * Constraints *must* be set by platform code in order for some
+ * regulator operations to proceed i.e. set_voltage, set_current_limit,
+ * set_mode.
+ */
+static int set_machine_constraints(struct regulator_dev *rdev,
+	struct regulation_constraints *constraints)
+{
+	int ret = 0;
+	const char *name;
+	struct regulator_ops *ops = rdev->desc->ops;
+
 	rdev->constraints = constraints;
 
-	/* do we need to apply the constraint voltage */
-	if (rdev->constraints->apply_uV &&
-		rdev->constraints->min_uV == rdev->constraints->max_uV &&
-		ops->set_voltage) {
-		ret = ops->set_voltage(rdev,
-			rdev->constraints->min_uV, rdev->constraints->max_uV);
-			if (ret < 0) {
-				printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n",
-				       __func__,
-				       rdev->constraints->min_uV, name);
-				rdev->constraints = NULL;
-				goto out;
-			}
-	}
+	name = rdev_get_name(rdev);
+
+	ret = machine_constraints_voltage(rdev, constraints);
+	if (ret != 0)
+		goto out;
 
 	/* do we need to setup our suspend state */
 	if (constraints->initial_state) {
@@ -903,7 +949,7 @@
 				dev_name(&node->regulator->dev),
 				node->regulator->desc->name,
 				supply,
-				dev_name(&rdev->dev), rdev->desc->name);
+				dev_name(&rdev->dev), rdev_get_name(rdev));
 		return -EBUSY;
 	}
 
@@ -1212,7 +1258,7 @@
 		ret = _regulator_enable(rdev->supply);
 		if (ret < 0) {
 			printk(KERN_ERR "%s: failed to enable %s: %d\n",
-			       __func__, rdev->desc->name, ret);
+			       __func__, rdev_get_name(rdev), ret);
 			return ret;
 		}
 	}
@@ -1238,7 +1284,7 @@
 			}
 		} else if (ret < 0) {
 			printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n",
-			       __func__, rdev->desc->name, ret);
+			       __func__, rdev_get_name(rdev), ret);
 			return ret;
 		}
 		/* Fallthrough on positive return values - already enabled */
@@ -1279,7 +1325,7 @@
 
 	if (WARN(rdev->use_count <= 0,
 			"unbalanced disables for %s\n",
-			rdev->desc->name))
+			rdev_get_name(rdev)))
 		return -EIO;
 
 	/* are we the last user and permitted to disable ? */
@@ -1292,7 +1338,7 @@
 			ret = rdev->desc->ops->disable(rdev);
 			if (ret < 0) {
 				printk(KERN_ERR "%s: failed to disable %s\n",
-				       __func__, rdev->desc->name);
+				       __func__, rdev_get_name(rdev));
 				return ret;
 			}
 		}
@@ -1349,7 +1395,7 @@
 		ret = rdev->desc->ops->disable(rdev);
 		if (ret < 0) {
 			printk(KERN_ERR "%s: failed to force disable %s\n",
-			       __func__, rdev->desc->name);
+			       __func__, rdev_get_name(rdev));
 			return ret;
 		}
 		/* notify other consumers that power has been forced off */
@@ -1766,7 +1812,7 @@
 	output_uV = rdev->desc->ops->get_voltage(rdev);
 	if (output_uV <= 0) {
 		printk(KERN_ERR "%s: invalid output voltage found for %s\n",
-			__func__, rdev->desc->name);
+			__func__, rdev_get_name(rdev));
 		goto out;
 	}
 
@@ -1777,13 +1823,13 @@
 		input_uV = rdev->constraints->input_uV;
 	if (input_uV <= 0) {
 		printk(KERN_ERR "%s: invalid input voltage found for %s\n",
-			__func__, rdev->desc->name);
+			__func__, rdev_get_name(rdev));
 		goto out;
 	}
 
 	/* calc total requested load for this regulator */
 	list_for_each_entry(consumer, &rdev->consumer_list, list)
-	    total_uA_load += consumer->uA_load;
+		total_uA_load += consumer->uA_load;
 
 	mode = rdev->desc->ops->get_optimum_mode(rdev,
 						 input_uV, output_uV,
@@ -1791,7 +1837,7 @@
 	ret = regulator_check_mode(rdev, mode);
 	if (ret < 0) {
 		printk(KERN_ERR "%s: failed to get optimum mode for %s @"
-			" %d uA %d -> %d uV\n", __func__, rdev->desc->name,
+			" %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev),
 			total_uA_load, input_uV, output_uV);
 		goto out;
 	}
@@ -1799,7 +1845,7 @@
 	ret = rdev->desc->ops->set_mode(rdev, mode);
 	if (ret < 0) {
 		printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n",
-			__func__, mode, rdev->desc->name);
+			__func__, mode, rdev_get_name(rdev));
 		goto out;
 	}
 	ret = mode;
@@ -1852,9 +1898,9 @@
 
 	/* now notify regulator we supply */
 	list_for_each_entry(_rdev, &rdev->supply_list, slist) {
-	  mutex_lock(&_rdev->mutex);
-	  _notifier_call_chain(_rdev, event, data);
-	  mutex_unlock(&_rdev->mutex);
+		mutex_lock(&_rdev->mutex);
+		_notifier_call_chain(_rdev, event, data);
+		mutex_unlock(&_rdev->mutex);
 	}
 }
 
@@ -1885,9 +1931,9 @@
 		consumers[i].consumer = regulator_get(dev,
 						      consumers[i].supply);
 		if (IS_ERR(consumers[i].consumer)) {
-			dev_err(dev, "Failed to get supply '%s'\n",
-				consumers[i].supply);
 			ret = PTR_ERR(consumers[i].consumer);
+			dev_err(dev, "Failed to get supply '%s': %d\n",
+				consumers[i].supply, ret);
 			consumers[i].consumer = NULL;
 			goto err;
 		}
@@ -1930,8 +1976,8 @@
 	return 0;
 
 err:
-	printk(KERN_ERR "Failed to enable %s\n", consumers[i].supply);
-	for (i = 0; i < num_consumers; i++)
+	printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret);
+	for (--i; i >= 0; --i)
 		regulator_disable(consumers[i].consumer);
 
 	return ret;
@@ -1965,8 +2011,9 @@
 	return 0;
 
 err:
-	printk(KERN_ERR "Failed to disable %s\n", consumers[i].supply);
-	for (i = 0; i < num_consumers; i++)
+	printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply,
+	       ret);
+	for (--i; i >= 0; --i)
 		regulator_enable(consumers[i].consumer);
 
 	return ret;
@@ -2316,7 +2363,7 @@
 
 		if (ret < 0) {
 			printk(KERN_ERR "%s: failed to prepare %s\n",
-				__func__, rdev->desc->name);
+				__func__, rdev_get_name(rdev));
 			goto out;
 		}
 	}
@@ -2429,12 +2476,7 @@
 		ops = rdev->desc->ops;
 		c = rdev->constraints;
 
-		if (c && c->name)
-			name = c->name;
-		else if (rdev->desc->name)
-			name = rdev->desc->name;
-		else
-			name = "regulator";
+		name = rdev_get_name(rdev);
 
 		if (!ops->disable || (c && c->always_on))
 			continue;
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index aa224d9..f8c4661 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -331,7 +331,7 @@
 static int da9034_list_ldo12_voltage(struct regulator_dev *rdev,
 				     unsigned selector)
 {
-	if (selector > ARRAY_SIZE(da9034_ldo12_data))
+	if (selector >= ARRAY_SIZE(da9034_ldo12_data))
 		return -EINVAL;
 	return da9034_ldo12_data[selector] * 1000;
 }
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 7803a32..76d08c2 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -446,8 +446,8 @@
 		lp3971->rdev[i] = regulator_register(&regulators[id],
 			lp3971->dev, pdata->regulators[i].initdata, lp3971);
 
-		err = IS_ERR(lp3971->rdev[i]);
-		if (err) {
+		if (IS_ERR(lp3971->rdev[i])) {
+			err = PTR_ERR(lp3971->rdev[i]);
 			dev_err(lp3971->dev, "regulator init failed: %d\n",
 				err);
 			goto error;
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
new file mode 100644
index 0000000..acc2fb7
--- /dev/null
+++ b/drivers/regulator/max8660.c
@@ -0,0 +1,510 @@
+/*
+ * max8660.c  --  Voltage regulation for the Maxim 8660/8661
+ *
+ * based on max1586.c and wm8400-regulator.c
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; 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
+ *
+ * Some info:
+ *
+ * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8660-MAX8661.pdf
+ *
+ * This chip is a bit nasty because it is a write-only device. Thus, the driver
+ * uses shadow registers to keep track of its values. The main problem appears
+ * to be the initialization: When Linux boots up, we cannot know if the chip is
+ * in the default state or not, so we would have to pass such information in
+ * platform_data. As this adds a bit of complexity to the driver, this is left
+ * out for now until it is really needed.
+ *
+ * [A|S|M]DTV1 registers are currently not used, but [A|S|M]DTV2.
+ *
+ * If the driver is feature complete, it might be worth to check if one set of
+ * functions for V3-V7 is sufficient. For maximum flexibility during
+ * development, they are separated for now.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/max8660.h>
+
+#define MAX8660_DCDC_MIN_UV	 725000
+#define MAX8660_DCDC_MAX_UV	1800000
+#define MAX8660_DCDC_STEP	  25000
+#define MAX8660_DCDC_MAX_SEL	0x2b
+
+#define MAX8660_LDO5_MIN_UV	1700000
+#define MAX8660_LDO5_MAX_UV	2000000
+#define MAX8660_LDO5_STEP	  25000
+#define MAX8660_LDO5_MAX_SEL	0x0c
+
+#define MAX8660_LDO67_MIN_UV	1800000
+#define MAX8660_LDO67_MAX_UV	3300000
+#define MAX8660_LDO67_STEP	 100000
+#define MAX8660_LDO67_MAX_SEL	0x0f
+
+enum {
+	MAX8660_OVER1,
+	MAX8660_OVER2,
+	MAX8660_VCC1,
+	MAX8660_ADTV1,
+	MAX8660_ADTV2,
+	MAX8660_SDTV1,
+	MAX8660_SDTV2,
+	MAX8660_MDTV1,
+	MAX8660_MDTV2,
+	MAX8660_L12VCR,
+	MAX8660_FPWM,
+	MAX8660_N_REGS,	/* not a real register */
+};
+
+struct max8660 {
+	struct i2c_client *client;
+	u8 shadow_regs[MAX8660_N_REGS];		/* as chip is write only */
+	struct regulator_dev *rdev[];
+};
+
+static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val)
+{
+	static const u8 max8660_addresses[MAX8660_N_REGS] =
+	  { 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80 };
+
+	int ret;
+	u8 reg_val = (max8660->shadow_regs[reg] & mask) | val;
+	dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n",
+			max8660_addresses[reg], reg_val);
+
+	ret = i2c_smbus_write_byte_data(max8660->client,
+			max8660_addresses[reg], reg_val);
+	if (ret == 0)
+		max8660->shadow_regs[reg] = reg_val;
+
+	return ret;
+}
+
+
+/*
+ * DCDC functions
+ */
+
+static int max8660_dcdc_is_enabled(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 val = max8660->shadow_regs[MAX8660_OVER1];
+	u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
+	return !!(val & mask);
+}
+
+static int max8660_dcdc_enable(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
+	return max8660_write(max8660, MAX8660_OVER1, 0xff, bit);
+}
+
+static int max8660_dcdc_disable(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4;
+	return max8660_write(max8660, MAX8660_OVER1, mask, 0);
+}
+
+static int max8660_dcdc_list(struct regulator_dev *rdev, unsigned selector)
+{
+	if (selector > MAX8660_DCDC_MAX_SEL)
+		return -EINVAL;
+	return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
+}
+
+static int max8660_dcdc_get(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
+	u8 selector = max8660->shadow_regs[reg];
+	return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP;
+}
+
+static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 reg, selector, bits;
+	int ret;
+
+	if (min_uV < MAX8660_DCDC_MIN_UV || min_uV > MAX8660_DCDC_MAX_UV)
+		return -EINVAL;
+	if (max_uV < MAX8660_DCDC_MIN_UV || max_uV > MAX8660_DCDC_MAX_UV)
+		return -EINVAL;
+
+	selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1))
+			/ MAX8660_DCDC_STEP;
+
+	ret = max8660_dcdc_list(rdev, selector);
+	if (ret < 0 || ret > max_uV)
+		return -EINVAL;
+
+	reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
+	ret = max8660_write(max8660, reg, 0, selector);
+	if (ret)
+		return ret;
+
+	/* Select target voltage register and activate regulation */
+	bits = (rdev_get_id(rdev) == MAX8660_V3) ? 0x03 : 0x30;
+	return max8660_write(max8660, MAX8660_VCC1, 0xff, bits);
+}
+
+static struct regulator_ops max8660_dcdc_ops = {
+	.is_enabled = max8660_dcdc_is_enabled,
+	.list_voltage = max8660_dcdc_list,
+	.set_voltage = max8660_dcdc_set,
+	.get_voltage = max8660_dcdc_get,
+};
+
+
+/*
+ * LDO5 functions
+ */
+
+static int max8660_ldo5_list(struct regulator_dev *rdev, unsigned selector)
+{
+	if (selector > MAX8660_LDO5_MAX_SEL)
+		return -EINVAL;
+	return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
+}
+
+static int max8660_ldo5_get(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 selector = max8660->shadow_regs[MAX8660_MDTV2];
+
+	return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP;
+}
+
+static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 selector;
+	int ret;
+
+	if (min_uV < MAX8660_LDO5_MIN_UV || min_uV > MAX8660_LDO5_MAX_UV)
+		return -EINVAL;
+	if (max_uV < MAX8660_LDO5_MIN_UV || max_uV > MAX8660_LDO5_MAX_UV)
+		return -EINVAL;
+
+	selector = (min_uV - (MAX8660_LDO5_MIN_UV - MAX8660_LDO5_STEP + 1))
+			/ MAX8660_LDO5_STEP;
+	ret = max8660_ldo5_list(rdev, selector);
+	if (ret < 0 || ret > max_uV)
+		return -EINVAL;
+
+	ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector);
+	if (ret)
+		return ret;
+
+	/* Select target voltage register and activate regulation */
+	return max8660_write(max8660, MAX8660_VCC1, 0xff, 0xc0);
+}
+
+static struct regulator_ops max8660_ldo5_ops = {
+	.list_voltage = max8660_ldo5_list,
+	.set_voltage = max8660_ldo5_set,
+	.get_voltage = max8660_ldo5_get,
+};
+
+
+/*
+ * LDO67 functions
+ */
+
+static int max8660_ldo67_is_enabled(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 val = max8660->shadow_regs[MAX8660_OVER2];
+	u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
+	return !!(val & mask);
+}
+
+static int max8660_ldo67_enable(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
+	return max8660_write(max8660, MAX8660_OVER2, 0xff, bit);
+}
+
+static int max8660_ldo67_disable(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4;
+	return max8660_write(max8660, MAX8660_OVER2, mask, 0);
+}
+
+static int max8660_ldo67_list(struct regulator_dev *rdev, unsigned selector)
+{
+	if (selector > MAX8660_LDO67_MAX_SEL)
+		return -EINVAL;
+	return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
+}
+
+static int max8660_ldo67_get(struct regulator_dev *rdev)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;
+	u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;
+
+	return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP;
+}
+
+static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV)
+{
+	struct max8660 *max8660 = rdev_get_drvdata(rdev);
+	u8 selector;
+	int ret;
+
+	if (min_uV < MAX8660_LDO67_MIN_UV || min_uV > MAX8660_LDO67_MAX_UV)
+		return -EINVAL;
+	if (max_uV < MAX8660_LDO67_MIN_UV || max_uV > MAX8660_LDO67_MAX_UV)
+		return -EINVAL;
+
+	selector = (min_uV - (MAX8660_LDO67_MIN_UV - MAX8660_LDO67_STEP + 1))
+			/ MAX8660_LDO67_STEP;
+
+	ret = max8660_ldo67_list(rdev, selector);
+	if (ret < 0 || ret > max_uV)
+		return -EINVAL;
+
+	if (rdev_get_id(rdev) == MAX8660_V6)
+		return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector);
+	else
+		return max8660_write(max8660, MAX8660_L12VCR, 0x0f, selector << 4);
+}
+
+static struct regulator_ops max8660_ldo67_ops = {
+	.is_enabled = max8660_ldo67_is_enabled,
+	.enable = max8660_ldo67_enable,
+	.disable = max8660_ldo67_disable,
+	.list_voltage = max8660_ldo67_list,
+	.get_voltage = max8660_ldo67_get,
+	.set_voltage = max8660_ldo67_set,
+};
+
+static struct regulator_desc max8660_reg[] = {
+	{
+		.name = "V3(DCDC)",
+		.id = MAX8660_V3,
+		.ops = &max8660_dcdc_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = MAX8660_DCDC_MAX_SEL + 1,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "V4(DCDC)",
+		.id = MAX8660_V4,
+		.ops = &max8660_dcdc_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = MAX8660_DCDC_MAX_SEL + 1,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "V5(LDO)",
+		.id = MAX8660_V5,
+		.ops = &max8660_ldo5_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = MAX8660_LDO5_MAX_SEL + 1,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "V6(LDO)",
+		.id = MAX8660_V6,
+		.ops = &max8660_ldo67_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = MAX8660_LDO67_MAX_SEL + 1,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "V7(LDO)",
+		.id = MAX8660_V7,
+		.ops = &max8660_ldo67_ops,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = MAX8660_LDO67_MAX_SEL + 1,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int max8660_probe(struct i2c_client *client,
+			      const struct i2c_device_id *i2c_id)
+{
+	struct regulator_dev **rdev;
+	struct max8660_platform_data *pdata = client->dev.platform_data;
+	struct max8660 *max8660;
+	int boot_on, i, id, ret = -EINVAL;
+
+	if (pdata->num_subdevs > MAX8660_V_END) {
+		dev_err(&client->dev, "Too much regulators found!\n");
+		goto out;
+	}
+
+	max8660 = kzalloc(sizeof(struct max8660) +
+			sizeof(struct regulator_dev *) * MAX8660_V_END,
+			GFP_KERNEL);
+	if (!max8660) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	max8660->client = client;
+	rdev = max8660->rdev;
+
+	if (pdata->en34_is_high) {
+		/* Simulate always on */
+		max8660->shadow_regs[MAX8660_OVER1] = 5;
+	} else {
+		/* Otherwise devices can be toggled via software */
+		max8660_dcdc_ops.enable = max8660_dcdc_enable;
+		max8660_dcdc_ops.disable = max8660_dcdc_disable;
+	}
+
+	/*
+	 * First, set up shadow registers to prevent glitches. As some
+	 * registers are shared between regulators, everything must be properly
+	 * set up for all regulators in advance.
+	 */
+	max8660->shadow_regs[MAX8660_ADTV1] =
+		max8660->shadow_regs[MAX8660_ADTV2] =
+		max8660->shadow_regs[MAX8660_SDTV1] =
+		max8660->shadow_regs[MAX8660_SDTV2] = 0x1b;
+	max8660->shadow_regs[MAX8660_MDTV1] =
+		max8660->shadow_regs[MAX8660_MDTV2] = 0x04;
+
+	for (i = 0; i < pdata->num_subdevs; i++) {
+
+		if (!pdata->subdevs[i].platform_data)
+			goto err_free;
+
+		boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
+
+		switch (pdata->subdevs[i].id) {
+		case MAX8660_V3:
+			if (boot_on)
+				max8660->shadow_regs[MAX8660_OVER1] |= 1;
+			break;
+
+		case MAX8660_V4:
+			if (boot_on)
+				max8660->shadow_regs[MAX8660_OVER1] |= 4;
+			break;
+
+		case MAX8660_V5:
+			break;
+
+		case MAX8660_V6:
+			if (boot_on)
+				max8660->shadow_regs[MAX8660_OVER2] |= 2;
+			break;
+
+		case MAX8660_V7:
+			if (!strcmp(i2c_id->name, "max8661")) {
+				dev_err(&client->dev, "Regulator not on this chip!\n");
+				goto err_free;
+			}
+
+			if (boot_on)
+				max8660->shadow_regs[MAX8660_OVER2] |= 4;
+			break;
+
+		default:
+			dev_err(&client->dev, "invalid regulator %s\n",
+				 pdata->subdevs[i].name);
+			goto err_free;
+		}
+	}
+
+	/* Finally register devices */
+	for (i = 0; i < pdata->num_subdevs; i++) {
+
+		id = pdata->subdevs[i].id;
+
+		rdev[i] = regulator_register(&max8660_reg[id], &client->dev,
+					     pdata->subdevs[i].platform_data,
+					     max8660);
+		if (IS_ERR(rdev[i])) {
+			ret = PTR_ERR(rdev[i]);
+			dev_err(&client->dev, "failed to register %s\n",
+				max8660_reg[id].name);
+			goto err_unregister;
+		}
+	}
+
+	i2c_set_clientdata(client, rdev);
+	dev_info(&client->dev, "Maxim 8660/8661 regulator driver loaded\n");
+	return 0;
+
+err_unregister:
+	while (--i >= 0)
+		regulator_unregister(rdev[i]);
+err_free:
+	kfree(max8660);
+out:
+	return ret;
+}
+
+static int max8660_remove(struct i2c_client *client)
+{
+	struct regulator_dev **rdev = i2c_get_clientdata(client);
+	int i;
+
+	for (i = 0; i < MAX8660_V_END; i++)
+		if (rdev[i])
+			regulator_unregister(rdev[i]);
+	kfree(rdev);
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static const struct i2c_device_id max8660_id[] = {
+	{ "max8660", 0 },
+	{ "max8661", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max8660_id);
+
+static struct i2c_driver max8660_driver = {
+	.probe = max8660_probe,
+	.remove = max8660_remove,
+	.driver		= {
+		.name	= "max8660",
+	},
+	.id_table	= max8660_id,
+};
+
+static int __init max8660_init(void)
+{
+	return i2c_add_driver(&max8660_driver);
+}
+subsys_initcall(max8660_init);
+
+static void __exit max8660_exit(void)
+{
+	i2c_del_driver(&max8660_driver);
+}
+module_exit(max8660_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MAXIM 8660/8661 voltage regulator driver");
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
new file mode 100644
index 0000000..39c4953
--- /dev/null
+++ b/drivers/regulator/mc13783-regulator.c
@@ -0,0 +1,245 @@
+/*
+ * Regulator Driver for Freescale MC13783 PMIC
+ *
+ * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/mfd/mc13783.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#define MC13783_REG_SWITCHERS4			28
+#define MC13783_REG_SWITCHERS4_PLLEN			(1 << 18)
+
+#define MC13783_REG_SWITCHERS5			29
+#define MC13783_REG_SWITCHERS5_SW3EN			(1 << 20)
+
+#define MC13783_REG_REGULATORMODE0		32
+#define MC13783_REG_REGULATORMODE0_VAUDIOEN		(1 << 0)
+#define MC13783_REG_REGULATORMODE0_VIOHIEN		(1 << 3)
+#define MC13783_REG_REGULATORMODE0_VIOLOEN		(1 << 6)
+#define MC13783_REG_REGULATORMODE0_VDIGEN		(1 << 9)
+#define MC13783_REG_REGULATORMODE0_VGENEN		(1 << 12)
+#define MC13783_REG_REGULATORMODE0_VRFDIGEN		(1 << 15)
+#define MC13783_REG_REGULATORMODE0_VRFREFEN		(1 << 18)
+#define MC13783_REG_REGULATORMODE0_VRFCPEN		(1 << 21)
+
+#define MC13783_REG_REGULATORMODE1		33
+#define MC13783_REG_REGULATORMODE1_VSIMEN		(1 << 0)
+#define MC13783_REG_REGULATORMODE1_VESIMEN		(1 << 3)
+#define MC13783_REG_REGULATORMODE1_VCAMEN		(1 << 6)
+#define MC13783_REG_REGULATORMODE1_VRFBGEN		(1 << 9)
+#define MC13783_REG_REGULATORMODE1_VVIBEN		(1 << 11)
+#define MC13783_REG_REGULATORMODE1_VRF1EN		(1 << 12)
+#define MC13783_REG_REGULATORMODE1_VRF2EN		(1 << 15)
+#define MC13783_REG_REGULATORMODE1_VMMC1EN		(1 << 18)
+#define MC13783_REG_REGULATORMODE1_VMMC2EN		(1 << 21)
+
+#define MC13783_REG_POWERMISC			34
+#define MC13783_REG_POWERMISC_GPO1EN			(1 << 6)
+#define MC13783_REG_POWERMISC_GPO2EN			(1 << 8)
+#define MC13783_REG_POWERMISC_GPO3EN			(1 << 10)
+#define MC13783_REG_POWERMISC_GPO4EN			(1 << 12)
+
+struct mc13783_regulator {
+	struct regulator_desc desc;
+	int reg;
+	int enable_bit;
+};
+
+static struct regulator_ops mc13783_regulator_ops;
+
+#define MC13783_DEFINE(prefix, _name, _reg)				\
+	[MC13783_ ## prefix ## _ ## _name] = {				\
+		.desc = {						\
+			.name = #prefix "_" #_name,			\
+			.ops = &mc13783_regulator_ops,			\
+			.type = REGULATOR_VOLTAGE,			\
+			.id = MC13783_ ## prefix ## _ ## _name,		\
+			.owner = THIS_MODULE,				\
+		},							\
+		.reg = MC13783_REG_ ## _reg,				\
+		.enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN,	\
+	}
+
+#define MC13783_DEFINE_SW(_name, _reg) MC13783_DEFINE(SW, _name, _reg)
+#define MC13783_DEFINE_REGU(_name, _reg) MC13783_DEFINE(REGU, _name, _reg)
+
+static struct mc13783_regulator mc13783_regulators[] = {
+	MC13783_DEFINE_SW(SW3, SWITCHERS5),
+	MC13783_DEFINE_SW(PLL, SWITCHERS4),
+
+	MC13783_DEFINE_REGU(VAUDIO, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VIOHI, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VDIG, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VGEN, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0),
+	MC13783_DEFINE_REGU(VSIM, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VESIM, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VCAM, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VRFBG, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VVIB, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VRF1, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VRF2, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1),
+	MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1),
+	MC13783_DEFINE_REGU(GPO1, POWERMISC),
+	MC13783_DEFINE_REGU(GPO2, POWERMISC),
+	MC13783_DEFINE_REGU(GPO3, POWERMISC),
+	MC13783_DEFINE_REGU(GPO4, POWERMISC),
+};
+
+struct mc13783_regulator_priv {
+	struct mc13783 *mc13783;
+	struct regulator_dev *regulators[];
+};
+
+static int mc13783_regulator_enable(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+	int ret;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
+			mc13783_regulators[id].enable_bit,
+			mc13783_regulators[id].enable_bit);
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static int mc13783_regulator_disable(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+	int ret;
+
+	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg,
+			mc13783_regulators[id].enable_bit, 0);
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static int mc13783_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev);
+	int ret, id = rdev_get_id(rdev);
+	unsigned int val;
+
+	mc13783_lock(priv->mc13783);
+	ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
+	mc13783_unlock(priv->mc13783);
+
+	if (ret)
+		return ret;
+
+	return (val & mc13783_regulators[id].enable_bit) != 0;
+}
+
+static struct regulator_ops mc13783_regulator_ops = {
+	.enable = mc13783_regulator_enable,
+	.disable = mc13783_regulator_disable,
+	.is_enabled = mc13783_regulator_is_enabled,
+};
+
+static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+{
+	struct mc13783_regulator_priv *priv;
+	struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
+	struct mc13783_regulator_platform_data *pdata =
+		dev_get_platdata(&pdev->dev);
+	struct mc13783_regulator_init_data *init_data;
+	int i, ret;
+
+	dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);
+
+	priv = kzalloc(sizeof(*priv) +
+			pdata->num_regulators * sizeof(priv->regulators[0]),
+			GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->mc13783 = mc13783;
+
+	for (i = 0; i < pdata->num_regulators; i++) {
+		init_data = &pdata->regulators[i];
+		priv->regulators[i] = regulator_register(
+				&mc13783_regulators[init_data->id].desc,
+				&pdev->dev, init_data->init_data, priv);
+
+		if (IS_ERR(priv->regulators[i])) {
+			dev_err(&pdev->dev, "failed to register regulator %s\n",
+				mc13783_regulators[i].desc.name);
+			ret = PTR_ERR(priv->regulators[i]);
+			goto err;
+		}
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
+err:
+	while (--i >= 0)
+		regulator_unregister(priv->regulators[i]);
+
+	kfree(priv);
+
+	return ret;
+}
+
+static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+{
+	struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev);
+	struct mc13783_regulator_platform_data *pdata =
+		dev_get_platdata(&pdev->dev);
+	int i;
+
+	for (i = 0; i < pdata->num_regulators; i++)
+		regulator_unregister(priv->regulators[i]);
+
+	return 0;
+}
+
+static struct platform_driver mc13783_regulator_driver = {
+	.driver	= {
+		.name	= "mc13783-regulator",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __devexit_p(mc13783_regulator_remove),
+	.probe		= mc13783_regulator_probe,
+};
+
+static int __init mc13783_regulator_init(void)
+{
+	return platform_driver_register(&mc13783_regulator_driver);
+}
+subsys_initcall(mc13783_regulator_init);
+
+static void __exit mc13783_regulator_exit(void)
+{
+	platform_driver_unregister(&mc13783_regulator_driver);
+}
+module_exit(mc13783_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
+MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC");
+MODULE_ALIAS("platform:mc13783-regulator");
diff --git a/drivers/regulator/mc13783.c b/drivers/regulator/mc13783.c
deleted file mode 100644
index 710211f..0000000
--- a/drivers/regulator/mc13783.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Regulator Driver for Freescale MC13783 PMIC
- *
- * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/mfd/mc13783-private.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/driver.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/mc13783.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-
-struct mc13783_regulator {
-	struct regulator_desc desc;
-	int reg;
-	int enable_bit;
-};
-
-static struct regulator_ops mc13783_regulator_ops;
-
-static struct mc13783_regulator mc13783_regulators[] = {
-	[MC13783_SW_SW3] = {
-		.desc = {
-			.name	= "SW_SW3",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_SW_SW3,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_SWITCHERS_5,
-		.enable_bit = MC13783_SWCTRL_SW3_EN,
-	},
-	[MC13783_SW_PLL] = {
-		.desc = {
-			.name	= "SW_PLL",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_SW_PLL,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_SWITCHERS_4,
-		.enable_bit = MC13783_SWCTRL_PLL_EN,
-	},
-	[MC13783_REGU_VAUDIO] = {
-		.desc = {
-			.name	= "REGU_VAUDIO",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VAUDIO,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VAUDIO_EN,
-	},
-	[MC13783_REGU_VIOHI] = {
-		.desc = {
-			.name	= "REGU_VIOHI",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VIOHI,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VIOHI_EN,
-	},
-	[MC13783_REGU_VIOLO] = {
-		.desc = {
-			.name	= "REGU_VIOLO",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VIOLO,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VIOLO_EN,
-	},
-	[MC13783_REGU_VDIG] = {
-		.desc = {
-			.name	= "REGU_VDIG",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VDIG,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VDIG_EN,
-	},
-	[MC13783_REGU_VGEN] = {
-		.desc = {
-			.name	= "REGU_VGEN",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VGEN,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VGEN_EN,
-	},
-	[MC13783_REGU_VRFDIG] = {
-		.desc = {
-			.name	= "REGU_VRFDIG",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRFDIG,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VRFDIG_EN,
-	},
-	[MC13783_REGU_VRFREF] = {
-		.desc = {
-			.name	= "REGU_VRFREF",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRFREF,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VRFREF_EN,
-	},
-	[MC13783_REGU_VRFCP] = {
-		.desc = {
-			.name	= "REGU_VRFCP",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRFCP,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_0,
-		.enable_bit = MC13783_REGCTRL_VRFCP_EN,
-	},
-	[MC13783_REGU_VSIM] = {
-		.desc = {
-			.name	= "REGU_VSIM",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VSIM,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VSIM_EN,
-	},
-	[MC13783_REGU_VESIM] = {
-		.desc = {
-			.name	= "REGU_VESIM",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VESIM,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VESIM_EN,
-	},
-	[MC13783_REGU_VCAM] = {
-		.desc = {
-			.name	= "REGU_VCAM",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VCAM,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VCAM_EN,
-	},
-	[MC13783_REGU_VRFBG] = {
-		.desc = {
-			.name	= "REGU_VRFBG",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRFBG,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VRFBG_EN,
-	},
-	[MC13783_REGU_VVIB] = {
-		.desc = {
-			.name	= "REGU_VVIB",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VVIB,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VVIB_EN,
-	},
-	[MC13783_REGU_VRF1] = {
-		.desc = {
-			.name	= "REGU_VRF1",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRF1,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VRF1_EN,
-	},
-	[MC13783_REGU_VRF2] = {
-		.desc = {
-			.name	= "REGU_VRF2",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VRF2,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VRF2_EN,
-	},
-	[MC13783_REGU_VMMC1] = {
-		.desc = {
-			.name	= "REGU_VMMC1",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VMMC1,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VMMC1_EN,
-	},
-	[MC13783_REGU_VMMC2] = {
-		.desc = {
-			.name	= "REGU_VMMC2",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_VMMC2,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_REGULATOR_MODE_1,
-		.enable_bit = MC13783_REGCTRL_VMMC2_EN,
-	},
-	[MC13783_REGU_GPO1] = {
-		.desc = {
-			.name	= "REGU_GPO1",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_GPO1,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_POWER_MISCELLANEOUS,
-		.enable_bit = MC13783_REGCTRL_GPO1_EN,
-	},
-	[MC13783_REGU_GPO2] = {
-		.desc = {
-			.name	= "REGU_GPO2",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_GPO2,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_POWER_MISCELLANEOUS,
-		.enable_bit = MC13783_REGCTRL_GPO2_EN,
-	},
-	[MC13783_REGU_GPO3] = {
-		.desc = {
-			.name	= "REGU_GPO3",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_GPO3,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_POWER_MISCELLANEOUS,
-		.enable_bit = MC13783_REGCTRL_GPO3_EN,
-	},
-	[MC13783_REGU_GPO4] = {
-		.desc = {
-			.name	= "REGU_GPO4",
-			.ops	= &mc13783_regulator_ops,
-			.type	= REGULATOR_VOLTAGE,
-			.id	= MC13783_REGU_GPO4,
-			.owner	= THIS_MODULE,
-		},
-		.reg = MC13783_REG_POWER_MISCELLANEOUS,
-		.enable_bit = MC13783_REGCTRL_GPO4_EN,
-	},
-};
-
-struct mc13783_priv {
-	struct regulator_desc desc[ARRAY_SIZE(mc13783_regulators)];
-	struct mc13783 *mc13783;
-	struct regulator_dev *regulators[0];
-};
-
-static int mc13783_enable(struct regulator_dev *rdev)
-{
-	struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
-
-	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
-
-	return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
-			mc13783_regulators[id].enable_bit,
-			mc13783_regulators[id].enable_bit);
-}
-
-static int mc13783_disable(struct regulator_dev *rdev)
-{
-	struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
-
-	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
-
-	return mc13783_set_bits(priv->mc13783, mc13783_regulators[id].reg,
-			mc13783_regulators[id].enable_bit, 0);
-}
-
-static int mc13783_is_enabled(struct regulator_dev *rdev)
-{
-	struct mc13783_priv *priv = rdev_get_drvdata(rdev);
-	int ret, id = rdev_get_id(rdev);
-	unsigned int val;
-
-	ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val);
-	if (ret)
-		return ret;
-
-	return (val & mc13783_regulators[id].enable_bit) != 0;
-}
-
-static struct regulator_ops mc13783_regulator_ops = {
-	.enable		= mc13783_enable,
-	.disable	= mc13783_disable,
-	.is_enabled	= mc13783_is_enabled,
-};
-
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
-{
-	struct mc13783_priv *priv;
-	struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent);
-	struct mc13783_regulator_init_data *init_data;
-	int i, ret;
-
-	dev_dbg(&pdev->dev, "mc13783_regulator_probe id %d\n", pdev->id);
-
-	priv = kzalloc(sizeof(*priv) + mc13783->num_regulators * sizeof(void *),
-			GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->mc13783 = mc13783;
-
-	for (i = 0; i < mc13783->num_regulators; i++) {
-		init_data = &mc13783->regulators[i];
-		priv->regulators[i] = regulator_register(
-				&mc13783_regulators[init_data->id].desc,
-				&pdev->dev, init_data->init_data, priv);
-
-		if (IS_ERR(priv->regulators[i])) {
-			dev_err(&pdev->dev, "failed to register regulator %s\n",
-				mc13783_regulators[i].desc.name);
-			ret = PTR_ERR(priv->regulators[i]);
-			goto err;
-		}
-	}
-
-	platform_set_drvdata(pdev, priv);
-
-	return 0;
-err:
-	while (--i >= 0)
-		regulator_unregister(priv->regulators[i]);
-
-	kfree(priv);
-
-	return ret;
-}
-
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
-{
-	struct mc13783_priv *priv = platform_get_drvdata(pdev);
-	struct mc13783 *mc13783 = priv->mc13783;
-	int i;
-
-	for (i = 0; i < mc13783->num_regulators; i++)
-		regulator_unregister(priv->regulators[i]);
-
-	return 0;
-}
-
-static struct platform_driver mc13783_regulator_driver = {
-	.driver	= {
-		.name	= "mc13783-regulator",
-		.owner	= THIS_MODULE,
-	},
-	.remove		= __devexit_p(mc13783_regulator_remove),
-};
-
-static int __init mc13783_regulator_init(void)
-{
-	return platform_driver_probe(&mc13783_regulator_driver,
-			mc13783_regulator_probe);
-}
-subsys_initcall(mc13783_regulator_init);
-
-static void __exit mc13783_regulator_exit(void)
-{
-	platform_driver_unregister(&mc13783_regulator_driver);
-}
-module_exit(mc13783_regulator_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de");
-MODULE_DESCRIPTION("Regulator Driver for Freescale MC13783 PMIC");
-MODULE_ALIAS("platform:mc13783-regulator");
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 7ea1c3a..7e67485 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
@@ -40,6 +41,12 @@
 	u8			table_len;
 	const u16		*table;
 
+	/* regulator specific turn-on delay */
+	u16			delay;
+
+	/* State REMAP default configuration */
+	u8			remap;
+
 	/* chip constraints on regulator behavior */
 	u16			min_mV;
 
@@ -128,6 +135,7 @@
 {
 	struct twlreg_info	*info = rdev_get_drvdata(rdev);
 	int			grp;
+	int			ret;
 
 	grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
 	if (grp < 0)
@@ -138,7 +146,11 @@
 	else
 		grp |= P1_GRP_6030;
 
-	return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+	ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
+
+	udelay(info->delay);
+
+	return ret;
 }
 
 static int twlreg_disable(struct regulator_dev *rdev)
@@ -151,9 +163,9 @@
 		return grp;
 
 	if (twl_class_is_4030())
-		grp &= ~P1_GRP_4030;
+		grp &= ~(P1_GRP_4030 | P2_GRP_4030 | P3_GRP_4030);
 	else
-		grp &= ~P1_GRP_6030;
+		grp &= ~(P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030);
 
 	return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
 }
@@ -294,6 +306,18 @@
 static const u16 VDAC_VSEL_table[] = {
 	1200, 1300, 1800, 1800,
 };
+static const u16 VDD1_VSEL_table[] = {
+	800, 1450,
+};
+static const u16 VDD2_VSEL_table[] = {
+	800, 1450, 1500,
+};
+static const u16 VIO_VSEL_table[] = {
+	1800, 1850,
+};
+static const u16 VINTANA2_VSEL_table[] = {
+	2500, 2750,
+};
 static const u16 VAUX1_6030_VSEL_table[] = {
 	1000, 1300, 1800, 2500,
 	2800, 2900, 3000, 3000,
@@ -414,20 +438,30 @@
 
 /*----------------------------------------------------------------------*/
 
-#define TWL4030_ADJUSTABLE_LDO(label, offset, num) \
-		TWL_ADJUSTABLE_LDO(label, offset, num, TWL4030)
-#define TWL4030_FIXED_LDO(label, offset, mVolts, num) \
-		TWL_FIXED_LDO(label, offset, mVolts, num, TWL4030)
-#define TWL6030_ADJUSTABLE_LDO(label, offset, num) \
-		TWL_ADJUSTABLE_LDO(label, offset, num, TWL6030)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, num) \
-		TWL_FIXED_LDO(label, offset, mVolts, num, TWL6030)
+#define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
+		TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+			remap_conf, TWL4030)
+#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+			remap_conf) \
+		TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+			remap_conf, TWL4030)
+#define TWL6030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+			remap_conf) \
+		TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, \
+			remap_conf, TWL6030)
+#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+			remap_conf) \
+		TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+			remap_conf, TWL6030)
 
-#define TWL_ADJUSTABLE_LDO(label, offset, num, family) { \
+#define TWL_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf, \
+		family) { \
 	.base = offset, \
 	.id = num, \
 	.table_len = ARRAY_SIZE(label##_VSEL_table), \
 	.table = label##_VSEL_table, \
+	.delay = turnon_delay, \
+	.remap = remap_conf, \
 	.desc = { \
 		.name = #label, \
 		.id = family##_REG_##label, \
@@ -438,10 +472,13 @@
 		}, \
 	}
 
-#define TWL_FIXED_LDO(label, offset, mVolts, num, family) { \
+#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
+		family) { \
 	.base = offset, \
 	.id = num, \
 	.min_mV = mVolts, \
+	.delay = turnon_delay, \
+	.remap = remap_conf, \
 	.desc = { \
 		.name = #label, \
 		.id = family##_REG_##label, \
@@ -457,43 +494,41 @@
  * software control over them after boot.
  */
 static struct twlreg_info twl_regs[] = {
-	TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1),
-	TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2),
-	TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2),
-	TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3),
-	TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4),
-	TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5),
-	TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6),
-	/*
-	TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7),
-	*/
-	TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8),
-	TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9),
-	TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10),
-	/*
-	TWL4030_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11),
-	TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12),
-	TWL4030_ADJUSTABLE_LDO(VINTDIG, 0x47, 13),
-	TWL4030_SMPS(VIO, 0x4b, 14),
-	TWL4030_SMPS(VDD1, 0x55, 15),
-	TWL4030_SMPS(VDD2, 0x63, 16),
-	 */
-	TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17),
-	TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18),
-	TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19),
+	TWL4030_ADJUSTABLE_LDO(VAUX1, 0x17, 1, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VAUX2, 0x1b, 2, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VAUX3, 0x1f, 3, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VAUX4, 0x23, 4, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VMMC1, 0x27, 5, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VMMC2, 0x2b, 6, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VPLL1, 0x2f, 7, 100, 0x00),
+	TWL4030_ADJUSTABLE_LDO(VPLL2, 0x33, 8, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VSIM, 0x37, 9, 100, 0x00),
+	TWL4030_ADJUSTABLE_LDO(VDAC, 0x3b, 10, 100, 0x08),
+	TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08),
+	TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08),
+	TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08),
+	TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08),
+	TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08),
+	TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08),
 	/* VUSBCP is managed *only* by the USB subchip */
 
 	/* 6030 REG with base as PMC Slave Misc : 0x0030 */
-	TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1),
-	TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2),
-	TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3),
-	TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4),
-	TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5),
-	TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7),
-	TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15),
-	TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16),
-	TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17),
-	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18)
+	/* Turnon-delay and remap configuration values for 6030 are not
+	   verified since the specification is not public */
+	TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1, 0, 0x08),
+	TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 2, 0, 0x08),
+	TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 3, 0, 0x08),
+	TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 4, 0, 0x08),
+	TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 5, 0, 0x08),
+	TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 7, 0, 0x08),
+	TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x08),
+	TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x08),
+	TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x08),
+	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x08)
 };
 
 static int twlreg_probe(struct platform_device *pdev)
@@ -525,6 +560,19 @@
 	c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
 				| REGULATOR_CHANGE_MODE
 				| REGULATOR_CHANGE_STATUS;
+	switch (pdev->id) {
+	case TWL4030_REG_VIO:
+	case TWL4030_REG_VDD1:
+	case TWL4030_REG_VDD2:
+	case TWL4030_REG_VPLL1:
+	case TWL4030_REG_VINTANA1:
+	case TWL4030_REG_VINTANA2:
+	case TWL4030_REG_VINTDIG:
+		c->always_on = true;
+		break;
+	default:
+		break;
+	}
 
 	rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
 	if (IS_ERR(rdev)) {
@@ -534,6 +582,9 @@
 	}
 	platform_set_drvdata(pdev, rdev);
 
+	twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
+						info->remap);
+
 	/* NOTE:  many regulators support short-circuit IRQs (presentable
 	 * as REGULATOR_OVER_CURRENT notifications?) configured via:
 	 *  - SC_CONFIG
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 2eefc1a..0a65775 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -19,6 +19,8 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/regulator.h>
@@ -39,6 +41,7 @@
 #define WM831X_DCDC_CONTROL_2     1
 #define WM831X_DCDC_ON_CONFIG     2
 #define WM831X_DCDC_SLEEP_CONTROL 3
+#define WM831X_DCDC_DVS_CONTROL   4
 
 /*
  * Shared
@@ -50,6 +53,10 @@
 	int base;
 	struct wm831x *wm831x;
 	struct regulator_dev *regulator;
+	int dvs_gpio;
+	int dvs_gpio_state;
+	int on_vsel;
+	int dvs_vsel;
 };
 
 static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev)
@@ -240,11 +247,9 @@
 	return -EINVAL;
 }
 
-static int wm831x_buckv_set_voltage_int(struct regulator_dev *rdev, int reg,
-					 int min_uV, int max_uV)
+static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
+					   int min_uV, int max_uV)
 {
-	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-	struct wm831x *wm831x = dcdc->wm831x;
 	u16 vsel;
 
 	if (min_uV < 600000)
@@ -257,39 +262,126 @@
 	if (wm831x_buckv_list_voltage(rdev, vsel) > max_uV)
 		return -EINVAL;
 
-	return wm831x_set_bits(wm831x, reg, WM831X_DC1_ON_VSEL_MASK, vsel);
+	return vsel;
+}
+
+static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev,
+					   int min_uV, int max_uV)
+{
+	u16 vsel;
+
+	if (max_uV < 600000 || max_uV > 1800000)
+		return -EINVAL;
+
+	vsel = ((max_uV - 600000) / 12500) + 8;
+
+	if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV ||
+	    wm831x_buckv_list_voltage(rdev, vsel) < max_uV)
+		return -EINVAL;
+
+	return vsel;
+}
+
+static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
+{
+	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+
+	if (state == dcdc->dvs_gpio_state)
+		return 0;
+
+	dcdc->dvs_gpio_state = state;
+	gpio_set_value(dcdc->dvs_gpio, state);
+
+	/* Should wait for DVS state change to be asserted if we have
+	 * a GPIO for it, for now assume the device is configured
+	 * for the fastest possible transition.
+	 */
+
+	return 0;
 }
 
 static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
-				     int min_uV, int max_uV)
+				    int min_uV, int max_uV)
 {
 	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-	u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+	struct wm831x *wm831x = dcdc->wm831x;
+	int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+	int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
+	int vsel, ret;
 
-	return wm831x_buckv_set_voltage_int(rdev, reg, min_uV, max_uV);
+	vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV);
+	if (vsel < 0)
+		return vsel;
+
+	/* If this value is already set then do a GPIO update if we can */
+	if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
+		return wm831x_buckv_set_dvs(rdev, 0);
+
+	if (dcdc->dvs_gpio && dcdc->dvs_vsel == vsel)
+		return wm831x_buckv_set_dvs(rdev, 1);
+
+	/* Always set the ON status to the minimum voltage */
+	ret = wm831x_set_bits(wm831x, on_reg, WM831X_DC1_ON_VSEL_MASK, vsel);
+	if (ret < 0)
+		return ret;
+	dcdc->on_vsel = vsel;
+
+	if (!dcdc->dvs_gpio)
+		return ret;
+
+	/* Kick the voltage transition now */
+	ret = wm831x_buckv_set_dvs(rdev, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Set the high voltage as the DVS voltage.  This is optimised
+	 * for CPUfreq usage, most processors will keep the maximum
+	 * voltage constant and lower the minimum with the frequency. */
+	vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV);
+	if (vsel < 0) {
+		/* This should never happen - at worst the same vsel
+		 * should be chosen */
+		WARN_ON(vsel < 0);
+		return 0;
+	}
+
+	/* Don't bother if it's the same VSEL we're already using */
+	if (vsel == dcdc->on_vsel)
+		return 0;
+
+	ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel);
+	if (ret == 0)
+		dcdc->dvs_vsel = vsel;
+	else
+		dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n",
+			 ret);
+
+	return 0;
 }
 
 static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
-					     int uV)
+					    int uV)
 {
 	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+	struct wm831x *wm831x = dcdc->wm831x;
 	u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
+	int vsel;
 
-	return wm831x_buckv_set_voltage_int(rdev, reg, uV, uV);
+	vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV);
+	if (vsel < 0)
+		return vsel;
+
+	return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel);
 }
 
 static int wm831x_buckv_get_voltage(struct regulator_dev *rdev)
 {
 	struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-	struct wm831x *wm831x = dcdc->wm831x;
-	u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
-	int val;
 
-	val = wm831x_reg_read(wm831x, reg);
-	if (val < 0)
-		return val;
-
-	return wm831x_buckv_list_voltage(rdev, val & WM831X_DC1_ON_VSEL_MASK);
+	if (dcdc->dvs_gpio && dcdc->dvs_gpio_state)
+		return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel);
+	else
+		return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel);
 }
 
 /* Current limit options */
@@ -346,6 +438,64 @@
 	.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
+/*
+ * Set up DVS control.  We just log errors since we can still run
+ * (with reduced performance) if we fail.
+ */
+static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+					    struct wm831x_buckv_pdata *pdata)
+{
+	struct wm831x *wm831x = dcdc->wm831x;
+	int ret;
+	u16 ctrl;
+
+	if (!pdata || !pdata->dvs_gpio)
+		return;
+
+	switch (pdata->dvs_control_src) {
+	case 1:
+		ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
+		break;
+	case 2:
+		ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
+		break;
+	default:
+		dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
+			pdata->dvs_control_src, dcdc->name);
+		return;
+	}
+
+	ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
+			      WM831X_DC1_DVS_SRC_MASK, ctrl);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
+			dcdc->name, ret);
+		return;
+	}
+
+	ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
+			dcdc->name, ret);
+		return;
+	}
+
+	/* gpiolib won't let us read the GPIO status so pick the higher
+	 * of the two existing voltages so we take it as platform data.
+	 */
+	dcdc->dvs_gpio_state = pdata->dvs_init_state;
+
+	ret = gpio_direction_output(pdata->dvs_gpio, dcdc->dvs_gpio_state);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Failed to enable %s DVS GPIO: %d\n",
+			dcdc->name, ret);
+		gpio_free(pdata->dvs_gpio);
+		return;
+	}
+
+	dcdc->dvs_gpio = pdata->dvs_gpio;
+}
+
 static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 {
 	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -384,6 +534,23 @@
 	dcdc->desc.ops = &wm831x_buckv_ops;
 	dcdc->desc.owner = THIS_MODULE;
 
+	ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Failed to read ON VSEL: %d\n", ret);
+		goto err;
+	}
+	dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
+
+	ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
+		goto err;
+	}
+	dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
+
+	if (pdata->dcdc[id])
+		wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+
 	dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev,
 					     pdata->dcdc[id], dcdc);
 	if (IS_ERR(dcdc->regulator)) {
@@ -422,6 +589,8 @@
 err_regulator:
 	regulator_unregister(dcdc->regulator);
 err:
+	if (dcdc->dvs_gpio)
+		gpio_free(dcdc->dvs_gpio);
 	kfree(dcdc);
 	return ret;
 }
@@ -434,6 +603,8 @@
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
 	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
+	if (dcdc->dvs_gpio)
+		gpio_free(dcdc->dvs_gpio);
 	kfree(dcdc);
 
 	return 0;
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 902db56..61e02ac 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -470,7 +470,7 @@
 	struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
 	struct wm831x *wm831x = ldo->wm831x;
 	int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
-	unsigned int ret;
+	int ret;
 
 	ret = wm831x_reg_read(wm831x, on_reg);
 	if (ret < 0)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 71fbd6e..8167e9e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -242,6 +242,15 @@
 	  If you say Y here you will get support for the
 	  watchdog timer in the ST M41T60 and M41T80 RTC chips series.
 
+config RTC_DRV_BQ32K
+	tristate "TI BQ32000"
+	help
+	  If you say Y here you will get support for the TI
+	  BQ32000 I2C RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-bq32k.
+
 config RTC_DRV_DM355EVM
 	tristate "TI DaVinci DM355 EVM RTC"
 	depends on MFD_DM355EVM_MSP
@@ -592,15 +601,22 @@
 	  Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC
 	  support. This chip contains a battery- and capacitor-backed RTC.
 
+config RTC_DRV_NUC900
+	tristate "NUC910/NUC920 RTC driver"
+	depends on RTC_CLASS && ARCH_W90X900
+	help
+	  If you say yes here you get support for the RTC subsystem of the
+	  NUC910/NUC920 used in embedded systems.
 
 comment "on-CPU RTC drivers"
 
 config RTC_DRV_OMAP
 	tristate "TI OMAP1"
-	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730
+	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
 	help
-	  Say "yes" here to support the real time clock on TI OMAP1 chips.
-	  This driver can also be built as a module called rtc-omap.
+	  Say "yes" here to support the real time clock on TI OMAP1 and
+	  DA8xx/OMAP-L13x chips.  This driver can also be built as a
+	  module called rtc-omap.
 
 config RTC_DRV_S3C
 	tristate "Samsung S3C series SoC RTC"
@@ -846,4 +862,10 @@
 	  If you say Y here you will get support for the RTC found on
 	  the PCAP2 ASIC used on some Motorola phones.
 
+config RTC_DRV_MC13783
+	depends on MFD_MC13783
+	tristate "Freescale MC13783 RTC"
+	help
+	  This enables support for the Freescale MC13783 PMIC RTC
+
 endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 7da6efb..e5160fd 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_RTC_DRV_AT91SAM9)	+= rtc-at91sam9.o
 obj-$(CONFIG_RTC_DRV_AU1XXX)	+= rtc-au1xxx.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
+obj-$(CONFIG_RTC_DRV_BQ32K)	+= rtc-bq32k.o
 obj-$(CONFIG_RTC_DRV_BQ4802)	+= rtc-bq4802.o
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_COH901331)	+= rtc-coh901331.o
@@ -52,8 +53,10 @@
 obj-$(CONFIG_RTC_MXC)		+= rtc-mxc.o
 obj-$(CONFIG_RTC_DRV_MAX6900)	+= rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MC13783)	+= rtc-mc13783.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
+obj-$(CONFIG_RTC_DRV_NUC900)	+= rtc-nuc900.o
 obj-$(CONFIG_RTC_DRV_OMAP)	+= rtc-omap.o
 obj-$(CONFIG_RTC_DRV_PCAP)	+= rtc-pcap.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index e1ec33e..8825695 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -256,6 +256,8 @@
 		goto out_iounmap;
 	}
 
+	platform_set_drvdata(pdev, rtc);
+
 	rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				&at32_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc->rtc)) {
@@ -264,7 +266,6 @@
 		goto out_free_irq;
 	}
 
-	platform_set_drvdata(pdev, rtc);
 	device_init_wakeup(&pdev->dev, 1);
 
 	dev_info(&pdev->dev, "Atmel RTC for AT32AP700x at %08lx irq %ld\n",
@@ -273,6 +274,7 @@
 	return 0;
 
 out_free_irq:
+	platform_set_drvdata(pdev, NULL);
 	free_irq(irq, rtc);
 out_iounmap:
 	iounmap(rtc->regs);
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
new file mode 100644
index 0000000..408cc8f
--- /dev/null
+++ b/drivers/rtc/rtc-bq32k.c
@@ -0,0 +1,204 @@
+/*
+ * Driver for TI BQ32000 RTC.
+ *
+ * Copyright (C) 2009 Semihalf.
+ *
+ * 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/i2c.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/bcd.h>
+
+#define BQ32K_SECONDS		0x00	/* Seconds register address */
+#define BQ32K_SECONDS_MASK	0x7F	/* Mask over seconds value */
+#define BQ32K_STOP		0x80	/* Oscillator Stop flat */
+
+#define BQ32K_MINUTES		0x01	/* Minutes register address */
+#define BQ32K_MINUTES_MASK	0x7F	/* Mask over minutes value */
+#define BQ32K_OF		0x80	/* Oscillator Failure flag */
+
+#define BQ32K_HOURS_MASK	0x3F	/* Mask over hours value */
+#define BQ32K_CENT		0x40	/* Century flag */
+#define BQ32K_CENT_EN		0x80	/* Century flag enable bit */
+
+struct bq32k_regs {
+	uint8_t		seconds;
+	uint8_t		minutes;
+	uint8_t		cent_hours;
+	uint8_t		day;
+	uint8_t		date;
+	uint8_t		month;
+	uint8_t		years;
+};
+
+static struct i2c_driver bq32k_driver;
+
+static int bq32k_read(struct device *dev, void *data, uint8_t off, uint8_t len)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_msg msgs[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &off,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = data,
+		}
+	};
+
+	if (i2c_transfer(client->adapter, msgs, 2) == 2)
+		return 0;
+
+	return -EIO;
+}
+
+static int bq32k_write(struct device *dev, void *data, uint8_t off, uint8_t len)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	uint8_t buffer[len + 1];
+
+	buffer[0] = off;
+	memcpy(&buffer[1], data, len);
+
+	if (i2c_master_send(client, buffer, len + 1) == len + 1)
+		return 0;
+
+	return -EIO;
+}
+
+static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct bq32k_regs regs;
+	int error;
+
+	error = bq32k_read(dev, &regs, 0, sizeof(regs));
+	if (error)
+		return error;
+
+	tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
+	tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK);
+	tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
+	tm->tm_mday = bcd2bin(regs.date);
+	tm->tm_wday = bcd2bin(regs.day) - 1;
+	tm->tm_mon = bcd2bin(regs.month) - 1;
+	tm->tm_year = bcd2bin(regs.years) +
+				((regs.cent_hours & BQ32K_CENT) ? 100 : 0);
+
+	return rtc_valid_tm(tm);
+}
+
+static int bq32k_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct bq32k_regs regs;
+
+	regs.seconds = bin2bcd(tm->tm_sec);
+	regs.minutes = bin2bcd(tm->tm_min);
+	regs.cent_hours = bin2bcd(tm->tm_hour) | BQ32K_CENT_EN;
+	regs.day = bin2bcd(tm->tm_wday + 1);
+	regs.date = bin2bcd(tm->tm_mday);
+	regs.month = bin2bcd(tm->tm_mon + 1);
+
+	if (tm->tm_year >= 100) {
+		regs.cent_hours |= BQ32K_CENT;
+		regs.years = bin2bcd(tm->tm_year - 100);
+	} else
+		regs.years = bin2bcd(tm->tm_year);
+
+	return bq32k_write(dev, &regs, 0, sizeof(regs));
+}
+
+static const struct rtc_class_ops bq32k_rtc_ops = {
+	.read_time	= bq32k_rtc_read_time,
+	.set_time	= bq32k_rtc_set_time,
+};
+
+static int bq32k_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct rtc_device *rtc;
+	uint8_t reg;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -ENODEV;
+
+	/* Check Oscillator Stop flag */
+	error = bq32k_read(dev, &reg, BQ32K_SECONDS, 1);
+	if (!error && (reg & BQ32K_STOP)) {
+		dev_warn(dev, "Oscillator was halted. Restarting...\n");
+		reg &= ~BQ32K_STOP;
+		error = bq32k_write(dev, &reg, BQ32K_SECONDS, 1);
+	}
+	if (error)
+		return error;
+
+	/* Check Oscillator Failure flag */
+	error = bq32k_read(dev, &reg, BQ32K_MINUTES, 1);
+	if (!error && (reg & BQ32K_OF)) {
+		dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
+		reg &= ~BQ32K_OF;
+		error = bq32k_write(dev, &reg, BQ32K_MINUTES, 1);
+	}
+	if (error)
+		return error;
+
+	rtc = rtc_device_register(bq32k_driver.driver.name, &client->dev,
+						&bq32k_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	i2c_set_clientdata(client, rtc);
+
+	return 0;
+}
+
+static int __devexit bq32k_remove(struct i2c_client *client)
+{
+	struct rtc_device *rtc = i2c_get_clientdata(client);
+
+	rtc_device_unregister(rtc);
+	return 0;
+}
+
+static const struct i2c_device_id bq32k_id[] = {
+	{ "bq32000", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bq32k_id);
+
+static struct i2c_driver bq32k_driver = {
+	.driver = {
+		.name	= "bq32k",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= bq32k_probe,
+	.remove		= __devexit_p(bq32k_remove),
+	.id_table	= bq32k_id,
+};
+
+static __init int bq32k_init(void)
+{
+	return i2c_add_driver(&bq32k_driver);
+}
+module_init(bq32k_init);
+
+static __exit void bq32k_exit(void)
+{
+	i2c_del_driver(&bq32k_driver);
+}
+module_exit(bq32k_exit);
+
+MODULE_AUTHOR("Semihalf, Piotr Ziecik <kosmo@semihalf.com>");
+MODULE_DESCRIPTION("TI BQ32000 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index d00a274..280fe48 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -169,6 +169,8 @@
 		goto out_free;
 	}
 
+	platform_set_drvdata(pdev, p);
+
 	p->rtc = rtc_device_register("bq4802", &pdev->dev,
 				     &bq4802_ops, THIS_MODULE);
 	if (IS_ERR(p->rtc)) {
@@ -176,7 +178,6 @@
 		goto out_iounmap;
 	}
 
-	platform_set_drvdata(pdev, p);
 	err = 0;
 out:
 	return err;
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index f7a4701..c8c1232 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -420,49 +420,43 @@
 	return 0;
 }
 
-#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
-
-static int
-cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
 	unsigned long	flags;
 
-	switch (cmd) {
-	case RTC_AIE_OFF:
-	case RTC_AIE_ON:
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		if (!is_valid_irq(cmos->irq))
-			return -EINVAL;
-		break;
-	/* PIE ON/OFF is handled by cmos_irq_set_state() */
-	default:
-		return -ENOIOCTLCMD;
-	}
+	if (!is_valid_irq(cmos->irq))
+		return -EINVAL;
 
 	spin_lock_irqsave(&rtc_lock, flags);
-	switch (cmd) {
-	case RTC_AIE_OFF:	/* alarm off */
-		cmos_irq_disable(cmos, RTC_AIE);
-		break;
-	case RTC_AIE_ON:	/* alarm on */
+
+	if (enabled)
 		cmos_irq_enable(cmos, RTC_AIE);
-		break;
-	case RTC_UIE_OFF:	/* update off */
-		cmos_irq_disable(cmos, RTC_UIE);
-		break;
-	case RTC_UIE_ON:	/* update on */
-		cmos_irq_enable(cmos, RTC_UIE);
-		break;
-	}
+	else
+		cmos_irq_disable(cmos, RTC_AIE);
+
 	spin_unlock_irqrestore(&rtc_lock, flags);
 	return 0;
 }
 
-#else
-#define	cmos_rtc_ioctl	NULL
-#endif
+static int cmos_update_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	if (!is_valid_irq(cmos->irq))
+		return -EINVAL;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+
+	if (enabled)
+		cmos_irq_enable(cmos, RTC_UIE);
+	else
+		cmos_irq_disable(cmos, RTC_UIE);
+
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return 0;
+}
 
 #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
 
@@ -503,14 +497,15 @@
 #endif
 
 static const struct rtc_class_ops cmos_rtc_ops = {
-	.ioctl		= cmos_rtc_ioctl,
-	.read_time	= cmos_read_time,
-	.set_time	= cmos_set_time,
-	.read_alarm	= cmos_read_alarm,
-	.set_alarm	= cmos_set_alarm,
-	.proc		= cmos_procfs,
-	.irq_set_freq	= cmos_irq_set_freq,
-	.irq_set_state	= cmos_irq_set_state,
+	.read_time		= cmos_read_time,
+	.set_time		= cmos_set_time,
+	.read_alarm		= cmos_read_alarm,
+	.set_alarm		= cmos_set_alarm,
+	.proc			= cmos_procfs,
+	.irq_set_freq		= cmos_irq_set_freq,
+	.irq_set_state		= cmos_irq_set_state,
+	.alarm_irq_enable	= cmos_alarm_irq_enable,
+	.update_irq_enable	= cmos_update_irq_enable,
 };
 
 /*----------------------------------------------------------------*/
@@ -691,7 +686,8 @@
 	 */
 #if	defined(CONFIG_ATARI)
 	address_space = 64;
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__)
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \
+			|| defined(__sparc__) || defined(__mips__)
 	address_space = 128;
 #else
 #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@@ -871,8 +867,9 @@
 			mask = RTC_IRQMASK;
 		tmp &= ~mask;
 		CMOS_WRITE(tmp, RTC_CONTROL);
-		hpet_mask_rtc_irq_bit(mask);
 
+		/* shut down hpet emulation - we don't need it for alarm */
+		hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
 		cmos_checkintr(cmos, tmp);
 	}
 	spin_unlock_irq(&rtc_lock);
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
index 1e73c8f..532acf9 100644
--- a/drivers/rtc/rtc-ds1302.c
+++ b/drivers/rtc/rtc-ds1302.c
@@ -143,7 +143,6 @@
 #ifdef RTC_SET_CHARGE
 	case RTC_SET_CHARGE:
 	{
-		struct ds1302_rtc *rtc = dev_get_drvdata(dev);
 		int tcs_val;
 
 		if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int)))
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 2736b11..9630e7d 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -617,7 +617,6 @@
 static int __devinit ds1305_probe(struct spi_device *spi)
 {
 	struct ds1305			*ds1305;
-	struct rtc_device		*rtc;
 	int				status;
 	u8				addr, value;
 	struct ds1305_platform_data	*pdata = spi->dev.platform_data;
@@ -756,14 +755,13 @@
 		dev_dbg(&spi->dev, "AM/PM\n");
 
 	/* register RTC ... from here on, ds1305->ctrl needs locking */
-	rtc = rtc_device_register("ds1305", &spi->dev,
+	ds1305->rtc = rtc_device_register("ds1305", &spi->dev,
 			&ds1305_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		status = PTR_ERR(rtc);
+	if (IS_ERR(ds1305->rtc)) {
+		status = PTR_ERR(ds1305->rtc);
 		dev_dbg(&spi->dev, "register rtc --> %d\n", status);
 		goto fail0;
 	}
-	ds1305->rtc = rtc;
 
 	/* Maybe set up alarm IRQ; be ready to handle it triggering right
 	 * away.  NOTE that we don't share this.  The signal is active low,
@@ -774,12 +772,14 @@
 	if (spi->irq) {
 		INIT_WORK(&ds1305->work, ds1305_work);
 		status = request_irq(spi->irq, ds1305_irq,
-				0, dev_name(&rtc->dev), ds1305);
+				0, dev_name(&ds1305->rtc->dev), ds1305);
 		if (status < 0) {
 			dev_dbg(&spi->dev, "request_irq %d --> %d\n",
 					spi->irq, status);
 			goto fail1;
 		}
+
+		device_set_wakeup_capable(&spi->dev, 1);
 	}
 
 	/* export NVRAM */
@@ -794,7 +794,7 @@
 fail2:
 	free_irq(spi->irq, ds1305);
 fail1:
-	rtc_device_unregister(rtc);
+	rtc_device_unregister(ds1305->rtc);
 fail0:
 	kfree(ds1305);
 	return status;
@@ -802,7 +802,7 @@
 
 static int __devexit ds1305_remove(struct spi_device *spi)
 {
-	struct ds1305	*ds1305 = spi_get_drvdata(spi);
+	struct ds1305 *ds1305 = spi_get_drvdata(spi);
 
 	sysfs_remove_bin_file(&spi->dev.kobj, &nvram);
 
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index eb99ee4..c4ec5c1 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -874,13 +874,15 @@
 	}
 
 	if (want_irq) {
-		err = request_irq(client->irq, ds1307_irq, 0,
+		err = request_irq(client->irq, ds1307_irq, IRQF_SHARED,
 			  ds1307->rtc->name, client);
 		if (err) {
 			dev_err(&client->dev,
 				"unable to request IRQ!\n");
 			goto exit_irq;
 		}
+
+		device_set_wakeup_capable(&client->dev, 1);
 		set_bit(HAS_ALARM, &ds1307->flags);
 		dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
 	}
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 713f7bf..5317bbc 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -383,6 +383,8 @@
 			dev_err(&client->dev, "unable to request IRQ\n");
 			goto out_free;
 		}
+
+		device_set_wakeup_capable(&client->dev, 1);
 	}
 
 	ds1374->rtc = rtc_device_register(client->name, &client->dev,
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 539676e..4166b84 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -87,7 +87,6 @@
 struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;		/* virtual base address */
-	unsigned long baseaddr;		/* physical base address */
 	int size;				/* amount of memory mapped */
 	int irq;
 	unsigned int irqen;
@@ -95,6 +94,7 @@
 	int alrm_min;
 	int alrm_hour;
 	int alrm_mday;
+	spinlock_t lock;
 };
 
 static DEFINE_SPINLOCK(ds1511_lock);
@@ -302,7 +302,7 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+	spin_lock_irqsave(&pdata->lock, flags);
 	rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
 	       0x80 : bin2bcd(pdata->alrm_mday) & 0x3f,
 	       RTC_ALARM_DATE);
@@ -317,7 +317,7 @@
 	       RTC_ALARM_SEC);
 	rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD);
 	rtc_read(RTC_CMD1);	/* clear interrupts */
-	spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+	spin_unlock_irqrestore(&pdata->lock, flags);
 }
 
  static int
@@ -362,61 +362,63 @@
 {
 	struct platform_device *pdev = dev_id;
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-	unsigned long events = RTC_IRQF;
+	unsigned long events = 0;
 
+	spin_lock(&pdata->lock);
 	/*
 	 * read and clear interrupt
 	 */
-	if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) {
-		return IRQ_NONE;
+	if (rtc_read(RTC_CMD1) & DS1511_IRQF) {
+		events = RTC_IRQF;
+		if (rtc_read(RTC_ALARM_SEC) & 0x80)
+			events |= RTC_UF;
+		else
+			events |= RTC_AF;
+		if (likely(pdata->rtc))
+			rtc_update_irq(pdata->rtc, 1, events);
 	}
-	if (rtc_read(RTC_ALARM_SEC) & 0x80) {
-		events |= RTC_UF;
-	} else {
-		events |= RTC_AF;
-	}
-	rtc_update_irq(pdata->rtc, 1, events);
-	return IRQ_HANDLED;
+	spin_unlock(&pdata->lock);
+	return events ? IRQ_HANDLED : IRQ_NONE;
 }
 
- static int
-ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
-	if (pdata->irq <= 0) {
-		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
-	}
-	switch (cmd) {
-	case RTC_AIE_OFF:
-		pdata->irqen &= ~RTC_AF;
-		ds1511_rtc_update_alarm(pdata);
-		break;
-	case RTC_AIE_ON:
+	if (pdata->irq <= 0)
+		return -EINVAL;
+	if (enabled)
 		pdata->irqen |= RTC_AF;
-		ds1511_rtc_update_alarm(pdata);
-		break;
-	case RTC_UIE_OFF:
-		pdata->irqen &= ~RTC_UF;
-		ds1511_rtc_update_alarm(pdata);
-		break;
-	case RTC_UIE_ON:
+	else
+		pdata->irqen &= ~RTC_AF;
+	ds1511_rtc_update_alarm(pdata);
+	return 0;
+}
+
+static int ds1511_rtc_update_irq_enable(struct device *dev,
+	unsigned int enabled)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq <= 0)
+		return -EINVAL;
+	if (enabled)
 		pdata->irqen |= RTC_UF;
-		ds1511_rtc_update_alarm(pdata);
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
+	else
+		pdata->irqen &= ~RTC_UF;
+	ds1511_rtc_update_alarm(pdata);
 	return 0;
 }
 
 static const struct rtc_class_ops ds1511_rtc_ops = {
-	.read_time	= ds1511_rtc_read_time,
-	.set_time	= ds1511_rtc_set_time,
-	.read_alarm	= ds1511_rtc_read_alarm,
-	.set_alarm	= ds1511_rtc_set_alarm,
-	.ioctl		= ds1511_rtc_ioctl,
+	.read_time		= ds1511_rtc_read_time,
+	.set_time		= ds1511_rtc_set_time,
+	.read_alarm		= ds1511_rtc_read_alarm,
+	.set_alarm		= ds1511_rtc_set_alarm,
+	.alarm_irq_enable	= ds1511_rtc_alarm_irq_enable,
+	.update_irq_enable	= ds1511_rtc_update_irq_enable,
 };
 
  static ssize_t
@@ -492,29 +494,23 @@
 {
 	struct rtc_device *rtc;
 	struct resource *res;
-	struct rtc_plat_data *pdata = NULL;
+	struct rtc_plat_data *pdata;
 	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		return -ENODEV;
 	}
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
 		return -ENOMEM;
-	}
 	pdata->size = res->end - res->start + 1;
-	if (!request_mem_region(res->start, pdata->size, pdev->name)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	pdata->baseaddr = res->start;
-	pdata->size = pdata->size;
-	ds1511_base = ioremap(pdata->baseaddr, pdata->size);
-	if (!ds1511_base) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
+			pdev->name))
+		return -EBUSY;
+	ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size);
+	if (!ds1511_base)
+		return -ENOMEM;
 	pdata->ioaddr = ds1511_base;
 	pdata->irq = platform_get_irq(pdev, 0);
 
@@ -540,13 +536,15 @@
 		dev_warn(&pdev->dev, "voltage-low detected.\n");
 	}
 
+	spin_lock_init(&pdata->lock);
+	platform_set_drvdata(pdev, pdata);
 	/*
 	 * if the platform has an interrupt in mind for this device,
 	 * then by all means, set it
 	 */
 	if (pdata->irq > 0) {
 		rtc_read(RTC_CMD1);
-		if (request_irq(pdata->irq, ds1511_interrupt,
+		if (devm_request_irq(&pdev->dev, pdata->irq, ds1511_interrupt,
 			IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) {
 
 			dev_warn(&pdev->dev, "interrupt not available.\n");
@@ -556,33 +554,13 @@
 
 	rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops,
 		THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
-		goto out;
-	}
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
-	platform_set_drvdata(pdev, pdata);
-	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
-	if (ret) {
-		goto out;
-	}
-	return 0;
- out:
-	if (pdata->rtc) {
-		rtc_device_unregister(pdata->rtc);
-	}
-	if (pdata->irq > 0) {
-		free_irq(pdata->irq, pdev);
-	}
-	if (ds1511_base) {
-		iounmap(ds1511_base);
-		ds1511_base = NULL;
-	}
-	if (pdata->baseaddr) {
-		release_mem_region(pdata->baseaddr, pdata->size);
-	}
 
-	kfree(pdata);
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
+	if (ret)
+		rtc_device_unregister(pdata->rtc);
 	return ret;
 }
 
@@ -593,19 +571,13 @@
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
 	rtc_device_unregister(pdata->rtc);
-	pdata->rtc = NULL;
 	if (pdata->irq > 0) {
 		/*
 		 * disable the alarm interrupt
 		 */
 		rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD);
 		rtc_read(RTC_CMD1);
-		free_irq(pdata->irq, pdev);
 	}
-	iounmap(pdata->ioaddr);
-	ds1511_base = NULL;
-	release_mem_region(pdata->baseaddr, pdata->size);
-	kfree(pdata);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 7172885..ed1ef7c 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -18,7 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#define DRV_VERSION "0.2"
+#define DRV_VERSION "0.3"
 
 #define RTC_REG_SIZE		0x2000
 #define RTC_OFFSET		0x1ff0
@@ -61,7 +61,6 @@
 struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
-	resource_size_t baseaddr;
 	unsigned long last_jiffies;
 	int irq;
 	unsigned int irqen;
@@ -69,6 +68,7 @@
 	int alrm_min;
 	int alrm_hour;
 	int alrm_mday;
+	spinlock_t lock;
 };
 
 static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -139,7 +139,7 @@
 	void __iomem *ioaddr = pdata->ioaddr;
 	unsigned long flags;
 
-	spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+	spin_lock_irqsave(&pdata->lock, flags);
 	writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
 	       0x80 : bin2bcd(pdata->alrm_mday),
 	       ioaddr + RTC_DATE_ALARM);
@@ -154,7 +154,7 @@
 	       ioaddr + RTC_SECONDS_ALARM);
 	writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
 	readb(ioaddr + RTC_FLAGS);	/* clear interrupts */
-	spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+	spin_unlock_irqrestore(&pdata->lock, flags);
 }
 
 static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -194,64 +194,69 @@
 	struct platform_device *pdev = dev_id;
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
-	unsigned long events = RTC_IRQF;
+	unsigned long events = 0;
 
+	spin_lock(&pdata->lock);
 	/* read and clear interrupt */
-	if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF))
-		return IRQ_NONE;
-	if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
-		events |= RTC_UF;
-	else
-		events |= RTC_AF;
-	rtc_update_irq(pdata->rtc, 1, events);
-	return IRQ_HANDLED;
+	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) {
+		events = RTC_IRQF;
+		if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
+			events |= RTC_UF;
+		else
+			events |= RTC_AF;
+		if (likely(pdata->rtc))
+			rtc_update_irq(pdata->rtc, 1, events);
+	}
+	spin_unlock(&pdata->lock);
+	return events ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
-			    unsigned long arg)
+static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	if (pdata->irq <= 0)
-		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
-	switch (cmd) {
-	case RTC_AIE_OFF:
-		pdata->irqen &= ~RTC_AF;
-		ds1553_rtc_update_alarm(pdata);
-		break;
-	case RTC_AIE_ON:
+		return -EINVAL;
+	if (enabled)
 		pdata->irqen |= RTC_AF;
-		ds1553_rtc_update_alarm(pdata);
-		break;
-	case RTC_UIE_OFF:
-		pdata->irqen &= ~RTC_UF;
-		ds1553_rtc_update_alarm(pdata);
-		break;
-	case RTC_UIE_ON:
+	else
+		pdata->irqen &= ~RTC_AF;
+	ds1553_rtc_update_alarm(pdata);
+	return 0;
+}
+
+static int ds1553_rtc_update_irq_enable(struct device *dev,
+	unsigned int enabled)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq <= 0)
+		return -EINVAL;
+	if (enabled)
 		pdata->irqen |= RTC_UF;
-		ds1553_rtc_update_alarm(pdata);
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
+	else
+		pdata->irqen &= ~RTC_UF;
+	ds1553_rtc_update_alarm(pdata);
 	return 0;
 }
 
 static const struct rtc_class_ops ds1553_rtc_ops = {
-	.read_time	= ds1553_rtc_read_time,
-	.set_time	= ds1553_rtc_set_time,
-	.read_alarm	= ds1553_rtc_read_alarm,
-	.set_alarm	= ds1553_rtc_set_alarm,
-	.ioctl		= ds1553_rtc_ioctl,
+	.read_time		= ds1553_rtc_read_time,
+	.set_time		= ds1553_rtc_set_time,
+	.read_alarm		= ds1553_rtc_read_alarm,
+	.set_alarm		= ds1553_rtc_set_alarm,
+	.alarm_irq_enable	= ds1553_rtc_alarm_irq_enable,
+	.update_irq_enable	= ds1553_rtc_update_irq_enable,
 };
 
 static ssize_t ds1553_nvram_read(struct kobject *kobj,
 				 struct bin_attribute *bin_attr,
 				 char *buf, loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
 	ssize_t count;
@@ -265,8 +270,8 @@
 				  struct bin_attribute *bin_attr,
 				  char *buf, loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
 	ssize_t count;
@@ -291,26 +296,23 @@
 	struct rtc_device *rtc;
 	struct resource *res;
 	unsigned int cen, sec;
-	struct rtc_plat_data *pdata = NULL;
-	void __iomem *ioaddr = NULL;
+	struct rtc_plat_data *pdata;
+	void __iomem *ioaddr;
 	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
-	if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	pdata->baseaddr = res->start;
-	ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
-	if (!ioaddr) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
+			pdev->name))
+		return -EBUSY;
+
+	ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
+	if (!ioaddr)
+		return -ENOMEM;
 	pdata->ioaddr = ioaddr;
 	pdata->irq = platform_get_irq(pdev, 0);
 
@@ -326,9 +328,13 @@
 	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
 		dev_warn(&pdev->dev, "voltage-low detected.\n");
 
+	spin_lock_init(&pdata->lock);
+	pdata->last_jiffies = jiffies;
+	platform_set_drvdata(pdev, pdata);
 	if (pdata->irq > 0) {
 		writeb(0, ioaddr + RTC_INTERRUPTS);
-		if (request_irq(pdata->irq, ds1553_rtc_interrupt,
+		if (devm_request_irq(&pdev->dev, pdata->irq,
+				ds1553_rtc_interrupt,
 				IRQF_DISABLED, pdev->name, pdev) < 0) {
 			dev_warn(&pdev->dev, "interrupt not available.\n");
 			pdata->irq = 0;
@@ -337,27 +343,13 @@
 
 	rtc = rtc_device_register(pdev->name, &pdev->dev,
 				  &ds1553_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
-		goto out;
-	}
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
 	pdata->rtc = rtc;
-	pdata->last_jiffies = jiffies;
-	platform_set_drvdata(pdev, pdata);
+
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
 	if (ret)
-		goto out;
-	return 0;
- out:
-	if (pdata->rtc)
-		rtc_device_unregister(pdata->rtc);
-	if (pdata->irq > 0)
-		free_irq(pdata->irq, pdev);
-	if (ioaddr)
-		iounmap(ioaddr);
-	if (pdata->baseaddr)
-		release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
-	kfree(pdata);
+		rtc_device_unregister(rtc);
 	return ret;
 }
 
@@ -367,13 +359,8 @@
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
 	rtc_device_unregister(pdata->rtc);
-	if (pdata->irq > 0) {
+	if (pdata->irq > 0)
 		writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
-		free_irq(pdata->irq, pdev);
-	}
-	iounmap(pdata->ioaddr);
-	release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
-	kfree(pdata);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 0924945..a127336 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -21,7 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#define DRV_VERSION "0.3"
+#define DRV_VERSION "0.4"
 
 #define RTC_SIZE		8
 
@@ -55,7 +55,6 @@
 	void __iomem *ioaddr_rtc;
 	size_t size_nvram;
 	size_t size;
-	resource_size_t baseaddr;
 	unsigned long last_jiffies;
 	struct bin_attribute nvram_attr;
 };
@@ -132,8 +131,8 @@
 				 struct bin_attribute *bin_attr,
 				 char *buf, loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr_nvram;
 	ssize_t count;
@@ -147,8 +146,8 @@
 				  struct bin_attribute *bin_attr,
 				  char *buf, loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr_nvram;
 	ssize_t count;
@@ -163,27 +162,24 @@
 	struct rtc_device *rtc;
 	struct resource *res;
 	unsigned int cen, sec;
-	struct rtc_plat_data *pdata = NULL;
-	void __iomem *ioaddr = NULL;
+	struct rtc_plat_data *pdata;
+	void __iomem *ioaddr;
 	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 	pdata->size = res->end - res->start + 1;
-	if (!request_mem_region(res->start, pdata->size, pdev->name)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	pdata->baseaddr = res->start;
-	ioaddr = ioremap(pdata->baseaddr, pdata->size);
-	if (!ioaddr) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
+		pdev->name))
+		return -EBUSY;
+	ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size);
+	if (!ioaddr)
+		return -ENOMEM;
+
 	pdata->ioaddr_nvram = ioaddr;
 	pdata->size_nvram = pdata->size - RTC_SIZE;
 	pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
@@ -207,31 +203,19 @@
 	if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG))
 		dev_warn(&pdev->dev, "voltage-low detected.\n");
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
-				  &ds1742_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
-		goto out;
-	}
-	pdata->rtc = rtc;
 	pdata->last_jiffies = jiffies;
 	platform_set_drvdata(pdev, pdata);
+	rtc = rtc_device_register(pdev->name, &pdev->dev,
+				  &ds1742_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+	pdata->rtc = rtc;
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
 	if (ret) {
 		dev_err(&pdev->dev, "creating nvram file in sysfs failed\n");
-		goto out;
+		rtc_device_unregister(rtc);
 	}
-
-	return 0;
- out:
-	if (pdata->rtc)
-		rtc_device_unregister(pdata->rtc);
-	if (pdata->ioaddr_nvram)
-		iounmap(pdata->ioaddr_nvram);
-	if (pdata->baseaddr)
-		release_mem_region(pdata->baseaddr, pdata->size);
-	kfree(pdata);
 	return ret;
 }
 
@@ -241,9 +225,6 @@
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
 	rtc_device_unregister(pdata->rtc);
-	iounmap(pdata->ioaddr_nvram);
-	release_mem_region(pdata->baseaddr, pdata->size);
-	kfree(pdata);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index 0b21975..8cb5b89 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -142,7 +142,6 @@
 
 static int __devinit m48t35_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc;
 	struct resource *res;
 	struct m48t35_priv *priv;
 	int ret = 0;
@@ -171,20 +170,21 @@
 		ret = -ENOMEM;
 		goto out;
 	}
+
 	spin_lock_init(&priv->lock);
-	rtc = rtc_device_register("m48t35", &pdev->dev,
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->rtc = rtc_device_register("m48t35", &pdev->dev,
 				  &m48t35_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
+	if (IS_ERR(priv->rtc)) {
+		ret = PTR_ERR(priv->rtc);
 		goto out;
 	}
-	priv->rtc = rtc;
-	platform_set_drvdata(pdev, priv);
+
 	return 0;
 
 out:
-	if (priv->rtc)
-		rtc_device_unregister(priv->rtc);
 	if (priv->reg)
 		iounmap(priv->reg);
 	if (priv->baseaddr)
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 33921a6..ede43b8 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -481,6 +481,9 @@
 		goto out;
 	}
 
+	spin_lock_init(&m48t59->lock);
+	platform_set_drvdata(pdev, m48t59);
+
 	m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
 	if (IS_ERR(m48t59->rtc)) {
 		ret = PTR_ERR(m48t59->rtc);
@@ -490,16 +493,14 @@
 	m48t59_nvram_attr.size = pdata->offset;
 
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
-	if (ret)
+	if (ret) {
+		rtc_device_unregister(m48t59->rtc);
 		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)
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
new file mode 100644
index 0000000..850f983
--- /dev/null
+++ b/drivers/rtc/rtc-mc13783.c
@@ -0,0 +1,262 @@
+/*
+ * Real Time Clock driver for Freescale MC13783 PMIC
+ *
+ * (C) 2009 Sascha Hauer, Pengutronix
+ * (C) 2009 Uwe Kleine-Koenig, Pengutronix
+ *
+ * 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/mfd/mc13783.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define DRIVER_NAME "mc13783-rtc"
+
+#define MC13783_RTCTOD	20
+#define MC13783_RTCTODA	21
+#define MC13783_RTCDAY	22
+#define MC13783_RTCDAYA	23
+
+struct mc13783_rtc {
+	struct rtc_device *rtc;
+	struct mc13783 *mc13783;
+	int valid;
+};
+
+static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	unsigned int seconds, days1, days2;
+	unsigned long s1970;
+	int ret;
+
+	mc13783_lock(priv->mc13783);
+
+	if (!priv->valid) {
+		ret = -ENODATA;
+		goto out;
+	}
+
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days1);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTOD, &seconds);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days2);
+out:
+	mc13783_unlock(priv->mc13783);
+
+	if (ret)
+		return ret;
+
+	if (days2 == days1 + 1) {
+		if (seconds >= 86400 / 2)
+			days2 = days1;
+		else
+			days1 = days2;
+	}
+
+	if (days1 != days2)
+		return -EIO;
+
+	s1970 = days1 * 86400 + seconds;
+
+	rtc_time_to_tm(s1970, tm);
+
+	return rtc_valid_tm(tm);
+}
+
+static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	unsigned int seconds, days;
+	int ret;
+
+	seconds = secs % 86400;
+	days = secs / 86400;
+
+	mc13783_lock(priv->mc13783);
+
+	/*
+	 * first write seconds=0 to prevent a day switch between writing days
+	 * and seconds below
+	 */
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAY, days);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, seconds);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST);
+	if (unlikely(ret))
+		goto out;
+
+	ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
+out:
+	priv->valid = !ret;
+
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev)
+{
+	struct mc13783_rtc *priv = dev;
+	struct mc13783 *mc13783 = priv->mc13783;
+
+	dev_dbg(&priv->rtc->dev, "1HZ\n");
+
+	rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
+
+	mc13783_ackirq(mc13783, irq);
+
+	return IRQ_HANDLED;
+}
+
+static int mc13783_rtc_update_irq_enable(struct device *dev,
+		unsigned int enabled)
+{
+	struct mc13783_rtc *priv = dev_get_drvdata(dev);
+	int ret = -ENODATA;
+
+	mc13783_lock(priv->mc13783);
+	if (!priv->valid)
+		goto out;
+
+	ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783,
+			MC13783_IRQ_1HZ);
+out:
+	mc13783_unlock(priv->mc13783);
+
+	return ret;
+}
+
+static const struct rtc_class_ops mc13783_rtc_ops = {
+	.read_time = mc13783_rtc_read_time,
+	.set_mmss = mc13783_rtc_set_mmss,
+	.update_irq_enable = mc13783_rtc_update_irq_enable,
+};
+
+static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev)
+{
+	struct mc13783_rtc *priv = dev;
+	struct mc13783 *mc13783 = priv->mc13783;
+
+	dev_dbg(&priv->rtc->dev, "RTCRST\n");
+	priv->valid = 0;
+
+	mc13783_mask(mc13783, irq);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct mc13783_rtc *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+	platform_set_drvdata(pdev, priv);
+
+	priv->valid = 1;
+
+	mc13783_lock(priv->mc13783);
+
+	ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
+			mc13783_rtc_reset_handler, DRIVER_NAME, priv);
+	if (ret)
+		goto err_reset_irq_request;
+
+	ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
+			mc13783_rtc_update_handler, DRIVER_NAME, priv);
+	if (ret)
+		goto err_update_irq_request;
+
+	mc13783_unlock(priv->mc13783);
+
+	priv->rtc = rtc_device_register(pdev->name,
+			&pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(priv->rtc)) {
+		ret = PTR_ERR(priv->rtc);
+
+		mc13783_lock(priv->mc13783);
+
+		mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
+err_update_irq_request:
+
+		mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
+err_reset_irq_request:
+
+		mc13783_unlock(priv->mc13783);
+
+		platform_set_drvdata(pdev, NULL);
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
+{
+	struct mc13783_rtc *priv = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(priv->rtc);
+
+	mc13783_lock(priv->mc13783);
+
+	mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
+	mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
+
+	mc13783_unlock(priv->mc13783);
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver mc13783_rtc_driver = {
+	.remove = __devexit_p(mc13783_rtc_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mc13783_rtc_init(void)
+{
+	return platform_driver_probe(&mc13783_rtc_driver, &mc13783_rtc_probe);
+}
+module_init(mc13783_rtc_init);
+
+static void __exit mc13783_rtc_exit(void)
+{
+	platform_driver_unregister(&mc13783_rtc_driver);
+}
+module_exit(mc13783_rtc_exit);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("RTC driver for Freescale MC13783 PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index e0263d2..dc052ce 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -27,10 +27,17 @@
 #define RTC_MONTH_OFFS		8
 #define RTC_YEAR_OFFS		16
 
+#define RTC_ALARM_TIME_REG_OFFS	8
+#define RTC_ALARM_DATE_REG_OFFS	0xc
+#define RTC_ALARM_VALID		(1 << 7)
+
+#define RTC_ALARM_INTERRUPT_MASK_REG_OFFS	0x10
+#define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS	0x14
 
 struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
+	int		irq;
 };
 
 static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -84,12 +91,134 @@
 	return rtc_valid_tm(tm);
 }
 
+static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u32	rtc_time, rtc_date;
+	unsigned int year, month, day, hour, minute, second, wday;
+
+	rtc_time = readl(ioaddr + RTC_ALARM_TIME_REG_OFFS);
+	rtc_date = readl(ioaddr + RTC_ALARM_DATE_REG_OFFS);
+
+	second = rtc_time & 0x7f;
+	minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
+	hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
+	wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
+
+	day = rtc_date & 0x3f;
+	month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f;
+	year = (rtc_date >> RTC_YEAR_OFFS) & 0xff;
+
+	alm->time.tm_sec = bcd2bin(second);
+	alm->time.tm_min = bcd2bin(minute);
+	alm->time.tm_hour = bcd2bin(hour);
+	alm->time.tm_mday = bcd2bin(day);
+	alm->time.tm_wday = bcd2bin(wday);
+	alm->time.tm_mon = bcd2bin(month) - 1;
+	/* hw counts from year 2000, but tm_year is relative to 1900 */
+	alm->time.tm_year = bcd2bin(year) + 100;
+
+	if (rtc_valid_tm(&alm->time) < 0) {
+		dev_err(dev, "retrieved alarm date/time is not valid.\n");
+		rtc_time_to_tm(0, &alm->time);
+	}
+
+	alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
+	return 0;
+}
+
+static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u32 rtc_reg = 0;
+
+	if (alm->time.tm_sec >= 0)
+		rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_sec))
+			<< RTC_SECONDS_OFFS;
+	if (alm->time.tm_min >= 0)
+		rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_min))
+			<< RTC_MINUTES_OFFS;
+	if (alm->time.tm_hour >= 0)
+		rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_hour))
+			<< RTC_HOURS_OFFS;
+
+	writel(rtc_reg, ioaddr + RTC_ALARM_TIME_REG_OFFS);
+
+	if (alm->time.tm_mday >= 0)
+		rtc_reg = (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mday))
+			<< RTC_MDAY_OFFS;
+	else
+		rtc_reg = 0;
+
+	if (alm->time.tm_mon >= 0)
+		rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mon + 1))
+			<< RTC_MONTH_OFFS;
+
+	if (alm->time.tm_year >= 0)
+		rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_year % 100))
+			<< RTC_YEAR_OFFS;
+
+	writel(rtc_reg, ioaddr + RTC_ALARM_DATE_REG_OFFS);
+	writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS);
+	writel(alm->enabled ? 1 : 0,
+	       ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
+
+	return 0;
+}
+
+static int mv_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+
+	if (pdata->irq < 0)
+		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
+		break;
+	case RTC_AIE_ON:
+		writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static irqreturn_t mv_rtc_interrupt(int irq, void *data)
+{
+	struct rtc_plat_data *pdata = data;
+	void __iomem *ioaddr = pdata->ioaddr;
+
+	/* alarm irq? */
+	if (!readl(ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS))
+		return IRQ_NONE;
+
+	/* clear interrupt */
+	writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS);
+	rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF);
+	return IRQ_HANDLED;
+}
+
 static const struct rtc_class_ops mv_rtc_ops = {
 	.read_time	= mv_rtc_read_time,
 	.set_time	= mv_rtc_set_time,
 };
 
-static int __init mv_rtc_probe(struct platform_device *pdev)
+static const struct rtc_class_ops mv_rtc_alarm_ops = {
+	.read_time	= mv_rtc_read_time,
+	.set_time	= mv_rtc_set_time,
+	.read_alarm	= mv_rtc_read_alarm,
+	.set_alarm	= mv_rtc_set_alarm,
+	.ioctl		= mv_rtc_ioctl,
+};
+
+static int __devinit mv_rtc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct rtc_plat_data *pdata;
@@ -130,12 +259,31 @@
 		}
 	}
 
+	pdata->irq = platform_get_irq(pdev, 0);
+
 	platform_set_drvdata(pdev, pdata);
-	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
-					 &mv_rtc_ops, THIS_MODULE);
+
+	if (pdata->irq >= 0) {
+		device_init_wakeup(&pdev->dev, 1);
+		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+						 &mv_rtc_alarm_ops,
+						 THIS_MODULE);
+	} else
+		pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+						 &mv_rtc_ops, THIS_MODULE);
 	if (IS_ERR(pdata->rtc))
 		return PTR_ERR(pdata->rtc);
 
+	if (pdata->irq >= 0) {
+		writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
+		if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt,
+				     IRQF_DISABLED | IRQF_SHARED,
+				     pdev->name, pdata) < 0) {
+			dev_warn(&pdev->dev, "interrupt not available.\n");
+			pdata->irq = -1;
+		}
+	}
+
 	return 0;
 }
 
@@ -143,6 +291,9 @@
 {
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
+	if (pdata->irq >= 0)
+		device_init_wakeup(&pdev->dev, 0);
+
 	rtc_device_unregister(pdata->rtc);
 	return 0;
 }
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
new file mode 100644
index 0000000..bf59c9c
--- /dev/null
+++ b/drivers/rtc/rtc-nuc900.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2008-2009 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/bcd.h>
+
+/* RTC Control Registers */
+#define REG_RTC_INIR		0x00
+#define REG_RTC_AER		0x04
+#define REG_RTC_FCR		0x08
+#define REG_RTC_TLR		0x0C
+#define REG_RTC_CLR		0x10
+#define REG_RTC_TSSR		0x14
+#define REG_RTC_DWR		0x18
+#define REG_RTC_TAR		0x1C
+#define REG_RTC_CAR		0x20
+#define REG_RTC_LIR		0x24
+#define REG_RTC_RIER		0x28
+#define REG_RTC_RIIR		0x2C
+#define REG_RTC_TTR		0x30
+
+#define RTCSET			0x01
+#define AERRWENB		0x10000
+#define INIRRESET		0xa5eb1357
+#define AERPOWERON		0xA965
+#define AERPOWEROFF		0x0000
+#define LEAPYEAR		0x0001
+#define TICKENB			0x80
+#define TICKINTENB		0x0002
+#define ALARMINTENB		0x0001
+#define MODE24			0x0001
+
+struct nuc900_rtc {
+	int			irq_num;
+	void __iomem		*rtc_reg;
+	struct rtc_device	*rtcdev;
+};
+
+struct nuc900_bcd_time {
+	int bcd_sec;
+	int bcd_min;
+	int bcd_hour;
+	int bcd_mday;
+	int bcd_mon;
+	int bcd_year;
+};
+
+static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc)
+{
+	struct nuc900_rtc *rtc = _rtc;
+	unsigned long events = 0, rtc_irq;
+
+	rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR);
+
+	if (rtc_irq & ALARMINTENB) {
+		rtc_irq &= ~ALARMINTENB;
+		__raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR);
+		events |= RTC_AF | RTC_IRQF;
+	}
+
+	if (rtc_irq & TICKINTENB) {
+		rtc_irq &= ~TICKINTENB;
+		__raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR);
+		events |= RTC_UF | RTC_IRQF;
+	}
+
+	rtc_update_irq(rtc->rtcdev, 1, events);
+
+	return IRQ_HANDLED;
+}
+
+static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
+{
+	unsigned int i;
+	__raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR);
+
+	mdelay(10);
+
+	__raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER);
+
+	for (i = 0; i < 1000; i++) {
+		if (__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB)
+			return 0;
+	}
+
+	if ((__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) == 0x0)
+		return ERR_PTR(-ENODEV);
+
+	return ERR_PTR(-EPERM);
+}
+
+static void nuc900_rtc_bcd2bin(unsigned int timereg,
+				unsigned int calreg, struct rtc_time *tm)
+{
+	tm->tm_mday	= bcd2bin(calreg >> 0);
+	tm->tm_mon	= bcd2bin(calreg >> 8);
+	tm->tm_year	= bcd2bin(calreg >> 16) + 100;
+
+	tm->tm_sec	= bcd2bin(timereg >> 0);
+	tm->tm_min	= bcd2bin(timereg >> 8);
+	tm->tm_hour	= bcd2bin(timereg >> 16);
+
+	rtc_valid_tm(tm);
+}
+
+static void nuc900_rtc_bin2bcd(struct rtc_time *settm,
+						struct nuc900_bcd_time *gettm)
+{
+	gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0;
+	gettm->bcd_mon  = bin2bcd(settm->tm_mon) << 8;
+	gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16;
+
+	gettm->bcd_sec  = bin2bcd(settm->tm_sec) << 0;
+	gettm->bcd_min  = bin2bcd(settm->tm_min) << 8;
+	gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16;
+}
+
+static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+
+	if (enabled)
+		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)|
+				(TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
+	else
+		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)&
+				(~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
+
+	return 0;
+}
+
+static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+
+	if (enabled)
+		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)|
+				(ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER);
+	else
+		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)&
+				(~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER);
+
+	return 0;
+}
+
+static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int timeval, clrval;
+
+	timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR);
+	clrval	= __raw_readl(rtc->rtc_reg + REG_RTC_CLR);
+
+	nuc900_rtc_bcd2bin(timeval, clrval, tm);
+
+	return 0;
+}
+
+static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+	struct nuc900_bcd_time gettm;
+	unsigned long val;
+	int *err;
+
+	nuc900_rtc_bin2bcd(tm, &gettm);
+
+	err = check_rtc_access_enable(rtc);
+	if (IS_ERR(err))
+		return PTR_ERR(err);
+
+	val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year;
+	__raw_writel(val, rtc->rtc_reg + REG_RTC_CLR);
+
+	val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour;
+	__raw_writel(val, rtc->rtc_reg + REG_RTC_TLR);
+
+	return 0;
+}
+
+static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+	unsigned int timeval, carval;
+
+	timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR);
+	carval	= __raw_readl(rtc->rtc_reg + REG_RTC_CAR);
+
+	nuc900_rtc_bcd2bin(timeval, carval, &alrm->time);
+
+	return 0;
+}
+
+static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
+	struct nuc900_bcd_time tm;
+	unsigned long val;
+	int *err;
+
+	nuc900_rtc_bin2bcd(&alrm->time, &tm);
+
+	err = check_rtc_access_enable(rtc);
+	if (IS_ERR(err))
+		return PTR_ERR(err);
+
+	val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year;
+	__raw_writel(val, rtc->rtc_reg + REG_RTC_CAR);
+
+	val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour;
+	__raw_writel(val, rtc->rtc_reg + REG_RTC_TAR);
+
+	return 0;
+}
+
+static struct rtc_class_ops nuc900_rtc_ops = {
+	.read_time = nuc900_rtc_read_time,
+	.set_time = nuc900_rtc_set_time,
+	.read_alarm = nuc900_rtc_read_alarm,
+	.set_alarm = nuc900_rtc_set_alarm,
+	.alarm_irq_enable = nuc900_alarm_irq_enable,
+	.update_irq_enable = nuc900_update_irq_enable,
+};
+
+static int __devinit nuc900_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct nuc900_rtc *nuc900_rtc;
+	int err = 0;
+
+	nuc900_rtc = kzalloc(sizeof(struct nuc900_rtc), GFP_KERNEL);
+	if (!nuc900_rtc) {
+		dev_err(&pdev->dev, "kzalloc nuc900_rtc failed\n");
+		return -ENOMEM;
+	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "platform_get_resource failed\n");
+		err = -ENXIO;
+		goto fail1;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res),
+				pdev->name)) {
+		dev_err(&pdev->dev, "request_mem_region failed\n");
+		err = -EBUSY;
+		goto fail1;
+	}
+
+	nuc900_rtc->rtc_reg = ioremap(res->start, resource_size(res));
+	if (!nuc900_rtc->rtc_reg) {
+		dev_err(&pdev->dev, "ioremap rtc_reg failed\n");
+		err = -ENOMEM;
+		goto fail2;
+	}
+
+	nuc900_rtc->irq_num = platform_get_irq(pdev, 0);
+	if (request_irq(nuc900_rtc->irq_num, nuc900_rtc_interrupt,
+				IRQF_DISABLED, "nuc900rtc", nuc900_rtc)) {
+		dev_err(&pdev->dev, "NUC900 RTC request irq failed\n");
+		err = -EBUSY;
+		goto fail3;
+	}
+
+	nuc900_rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev,
+						&nuc900_rtc_ops, THIS_MODULE);
+	if (IS_ERR(nuc900_rtc->rtcdev)) {
+		dev_err(&pdev->dev, "rtc device register faild\n");
+		err = PTR_ERR(nuc900_rtc->rtcdev);
+		goto fail4;
+	}
+
+	platform_set_drvdata(pdev, nuc900_rtc);
+	__raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24,
+					nuc900_rtc->rtc_reg + REG_RTC_TSSR);
+
+	return 0;
+
+fail4:	free_irq(nuc900_rtc->irq_num, nuc900_rtc);
+fail3:	iounmap(nuc900_rtc->rtc_reg);
+fail2:	release_mem_region(res->start, resource_size(res));
+fail1:	kfree(nuc900_rtc);
+	return err;
+}
+
+static int __devexit nuc900_rtc_remove(struct platform_device *pdev)
+{
+	struct nuc900_rtc *nuc900_rtc = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	rtc_device_unregister(nuc900_rtc->rtcdev);
+	free_irq(nuc900_rtc->irq_num, nuc900_rtc);
+	iounmap(nuc900_rtc->rtc_reg);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(nuc900_rtc);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver nuc900_rtc_driver = {
+	.remove		= __devexit_p(nuc900_rtc_remove),
+	.driver		= {
+		.name	= "nuc900-rtc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init nuc900_rtc_init(void)
+{
+	return platform_driver_probe(&nuc900_rtc_driver, nuc900_rtc_probe);
+}
+
+static void __exit nuc900_rtc_exit(void)
+{
+	platform_driver_unregister(&nuc900_rtc_driver);
+}
+
+module_init(nuc900_rtc_init);
+module_exit(nuc900_rtc_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("nuc910/nuc920 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:nuc900-rtc");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 0587d53..64d9727 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -87,9 +87,10 @@
 #define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
 #define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
 
+static void __iomem	*rtc_base;
 
-#define rtc_read(addr)		omap_readb(OMAP_RTC_BASE + (addr))
-#define rtc_write(val, addr)	omap_writeb(val, OMAP_RTC_BASE + (addr))
+#define rtc_read(addr)		__raw_readb(rtc_base + (addr))
+#define rtc_write(val, addr)	__raw_writeb(val, rtc_base + (addr))
 
 
 /* we rely on the rtc framework to handle locking (rtc->ops_lock),
@@ -330,32 +331,31 @@
 		return -ENOENT;
 	}
 
-	/* NOTE:  using static mapping for RTC registers */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res && res->start != OMAP_RTC_BASE) {
-		pr_debug("%s: RTC registers at %08x, expected %08x\n",
-			pdev->name, (unsigned) res->start, OMAP_RTC_BASE);
+	if (!res) {
+		pr_debug("%s: RTC resource data missing\n", pdev->name);
 		return -ENOENT;
 	}
 
-	if (res)
-		mem = request_mem_region(res->start,
-				res->end - res->start + 1,
-				pdev->name);
-	else
-		mem = NULL;
+	mem = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (!mem) {
 		pr_debug("%s: RTC registers at %08x are not free\n",
-			pdev->name, OMAP_RTC_BASE);
+			pdev->name, res->start);
 		return -EBUSY;
 	}
 
+	rtc_base = ioremap(res->start, resource_size(res));
+	if (!rtc_base) {
+		pr_debug("%s: RTC registers can't be mapped\n", pdev->name);
+		goto fail;
+	}
+
 	rtc = rtc_device_register(pdev->name, &pdev->dev,
 			&omap_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		pr_debug("%s: can't register RTC device, err %ld\n",
 			pdev->name, PTR_ERR(rtc));
-		goto fail;
+		goto fail0;
 	}
 	platform_set_drvdata(pdev, rtc);
 	dev_set_drvdata(&rtc->dev, mem);
@@ -380,13 +380,14 @@
 			dev_name(&rtc->dev), rtc)) {
 		pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_timer);
-		goto fail0;
+		goto fail1;
 	}
-	if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
-			dev_name(&rtc->dev), rtc)) {
+	if ((omap_rtc_timer != omap_rtc_alarm) &&
+		(request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
+			dev_name(&rtc->dev), rtc))) {
 		pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
 			pdev->name, omap_rtc_alarm);
-		goto fail1;
+		goto fail2;
 	}
 
 	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
@@ -419,10 +420,12 @@
 
 	return 0;
 
-fail1:
+fail2:
 	free_irq(omap_rtc_timer, NULL);
-fail0:
+fail1:
 	rtc_device_unregister(rtc);
+fail0:
+	iounmap(rtc_base);
 fail:
 	release_resource(mem);
 	return -EIO;
@@ -438,7 +441,9 @@
 	rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
 
 	free_irq(omap_rtc_timer, rtc);
-	free_irq(omap_rtc_alarm, rtc);
+
+	if (omap_rtc_timer != omap_rtc_alarm)
+		free_irq(omap_rtc_alarm, rtc);
 
 	release_resource(dev_get_drvdata(&rtc->dev));
 	rtc_device_unregister(rtc);
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 9b74e9c..854c3cb 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -58,6 +58,7 @@
 struct pcf50633_rtc {
 	int alarm_enabled;
 	int second_enabled;
+	int alarm_pending;
 
 	struct pcf50633 *pcf;
 	struct rtc_device *rtc_dev;
@@ -209,6 +210,7 @@
 	rtc = dev_get_drvdata(dev);
 
 	alrm->enabled = rtc->alarm_enabled;
+	alrm->pending = rtc->alarm_pending;
 
 	ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
 				PCF50633_TI_EXTENT, &pcf_tm.time[0]);
@@ -244,6 +246,8 @@
 	/* Returns 0 on success */
 	ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
 				PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+	if (!alrm->enabled)
+		rtc->alarm_pending = 0;
 
 	if (!alarm_masked || alrm->enabled)
 		pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
@@ -268,6 +272,7 @@
 	switch (irq) {
 	case PCF50633_IRQ_ALARM:
 		rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+		rtc->alarm_pending = 1;
 		break;
 	case PCF50633_IRQ_SECOND:
 		rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index b725913..65f346b 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -212,6 +212,8 @@
 
 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
 
+	i2c_set_clientdata(client, pcf8563);
+
 	pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
 				&client->dev, &pcf8563_rtc_ops, THIS_MODULE);
 
@@ -220,8 +222,6 @@
 		goto exit_kfree;
 	}
 
-	i2c_set_clientdata(client, pcf8563);
-
 	return 0;
 
 exit_kfree:
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 7d33cda..2d201af 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -277,6 +277,8 @@
 	if (!pcf8583)
 		return -ENOMEM;
 
+	i2c_set_clientdata(client, pcf8583);
+
 	pcf8583->rtc = rtc_device_register(pcf8583_driver.driver.name,
 			&client->dev, &pcf8583_rtc_ops, THIS_MODULE);
 
@@ -285,7 +287,6 @@
 		goto exit_kfree;
 	}
 
-	i2c_set_clientdata(client, pcf8583);
 	return 0;
 
 exit_kfree:
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index f41873f..0264b11 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -51,10 +51,10 @@
 
 	switch (cmd) {
 	case RTC_AIE_OFF:
-		__raw_writel(1, ldata->base + RTC_MIS);
+		writel(1, ldata->base + RTC_MIS);
 		return 0;
 	case RTC_AIE_ON:
-		__raw_writel(0, ldata->base + RTC_MIS);
+		writel(0, ldata->base + RTC_MIS);
 		return 0;
 	}
 
@@ -65,7 +65,7 @@
 {
 	struct pl031_local *ldata = dev_get_drvdata(dev);
 
-	rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm);
+	rtc_time_to_tm(readl(ldata->base + RTC_DR), tm);
 
 	return 0;
 }
@@ -76,7 +76,7 @@
 	struct pl031_local *ldata = dev_get_drvdata(dev);
 
 	rtc_tm_to_time(tm, &time);
-	__raw_writel(time, ldata->base + RTC_LR);
+	writel(time, ldata->base + RTC_LR);
 
 	return 0;
 }
@@ -85,9 +85,9 @@
 {
 	struct pl031_local *ldata = dev_get_drvdata(dev);
 
-	rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time);
-	alarm->pending = __raw_readl(ldata->base + RTC_RIS);
-	alarm->enabled = __raw_readl(ldata->base + RTC_IMSC);
+	rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
+	alarm->pending = readl(ldata->base + RTC_RIS);
+	alarm->enabled = readl(ldata->base + RTC_IMSC);
 
 	return 0;
 }
@@ -99,8 +99,8 @@
 
 	rtc_tm_to_time(&alarm->time, &time);
 
-	__raw_writel(time, ldata->base + RTC_MR);
-	__raw_writel(!alarm->enabled, ldata->base + RTC_MIS);
+	writel(time, ldata->base + RTC_MR);
+	writel(!alarm->enabled, ldata->base + RTC_MIS);
 
 	return 0;
 }
@@ -180,8 +180,9 @@
 
 static struct amba_id pl031_ids[] __initdata = {
 	{
-		 .id = 0x00041031,
-	 	.mask = 0x000fffff, },
+		.id = 0x00041031,
+		.mask = 0x000fffff,
+	},
 	{0, 0},
 };
 
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index d491eb2..6770083 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -62,7 +62,6 @@
 struct rtc_plat_data {
 	struct rtc_device *rtc;
 	void __iomem *ioaddr;
-	unsigned long baseaddr;
 	unsigned long last_jiffies;
 	int irq;
 	unsigned int irqen;
@@ -70,6 +69,7 @@
 	int alrm_min;
 	int alrm_hour;
 	int alrm_mday;
+	spinlock_t lock;
 };
 
 static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -142,7 +142,7 @@
 	unsigned long irqflags;
 	u8 flags;
 
-	spin_lock_irqsave(&pdata->rtc->irq_lock, irqflags);
+	spin_lock_irqsave(&pdata->lock, irqflags);
 
 	flags = readb(ioaddr + RTC_FLAGS);
 	writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
@@ -162,7 +162,7 @@
 	writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS);
 	readb(ioaddr + RTC_FLAGS);	/* clear interrupts */
 	writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS);
-	spin_unlock_irqrestore(&pdata->rtc->irq_lock, irqflags);
+	spin_unlock_irqrestore(&pdata->lock, irqflags);
 }
 
 static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -202,56 +202,53 @@
 	struct platform_device *pdev = dev_id;
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
-	unsigned long events = RTC_IRQF;
+	unsigned long events = 0;
 
+	spin_lock(&pdata->lock);
 	/* read and clear interrupt */
-	if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF))
-		return IRQ_NONE;
-	if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
-		events |= RTC_UF;
-	else
-		events |= RTC_AF;
-	rtc_update_irq(pdata->rtc, 1, events);
-	return IRQ_HANDLED;
+	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) {
+		events = RTC_IRQF;
+		if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
+			events |= RTC_UF;
+		else
+			events |= RTC_AF;
+		if (likely(pdata->rtc))
+			rtc_update_irq(pdata->rtc, 1, events);
+	}
+	spin_unlock(&pdata->lock);
+	return events ? IRQ_HANDLED : IRQ_NONE;
 }
 
-static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd,
-			    unsigned long arg)
+static int stk17ta8_rtc_alarm_irq_enable(struct device *dev,
+	unsigned int enabled)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 
 	if (pdata->irq <= 0)
-		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
-	switch (cmd) {
-	case RTC_AIE_OFF:
-		pdata->irqen &= ~RTC_AF;
-		stk17ta8_rtc_update_alarm(pdata);
-		break;
-	case RTC_AIE_ON:
+		return -EINVAL;
+	if (enabled)
 		pdata->irqen |= RTC_AF;
-		stk17ta8_rtc_update_alarm(pdata);
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
+	else
+		pdata->irqen &= ~RTC_AF;
+	stk17ta8_rtc_update_alarm(pdata);
 	return 0;
 }
 
 static const struct rtc_class_ops stk17ta8_rtc_ops = {
-	.read_time	= stk17ta8_rtc_read_time,
-	.set_time	= stk17ta8_rtc_set_time,
-	.read_alarm	= stk17ta8_rtc_read_alarm,
-	.set_alarm	= stk17ta8_rtc_set_alarm,
-	.ioctl		= stk17ta8_rtc_ioctl,
+	.read_time		= stk17ta8_rtc_read_time,
+	.set_time		= stk17ta8_rtc_set_time,
+	.read_alarm		= stk17ta8_rtc_read_alarm,
+	.set_alarm		= stk17ta8_rtc_set_alarm,
+	.alarm_irq_enable	= stk17ta8_rtc_alarm_irq_enable,
 };
 
 static ssize_t stk17ta8_nvram_read(struct kobject *kobj,
 				 struct bin_attribute *attr, char *buf,
 				 loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
 	ssize_t count;
@@ -265,8 +262,8 @@
 				  struct bin_attribute *attr, char *buf,
 				  loff_t pos, size_t size)
 {
-	struct platform_device *pdev =
-		to_platform_device(container_of(kobj, struct device, kobj));
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
 	void __iomem *ioaddr = pdata->ioaddr;
 	ssize_t count;
@@ -288,31 +285,26 @@
 
 static int __devinit stk17ta8_rtc_probe(struct platform_device *pdev)
 {
-	struct rtc_device *rtc;
 	struct resource *res;
 	unsigned int cal;
 	unsigned int flags;
 	struct rtc_plat_data *pdata;
-	void __iomem *ioaddr = NULL;
+	void __iomem *ioaddr;
 	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 		return -ENODEV;
 
-	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
-	if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
-		ret = -EBUSY;
-		goto out;
-	}
-	pdata->baseaddr = res->start;
-	ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
-	if (!ioaddr) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
+			pdev->name))
+		return -EBUSY;
+	ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
+	if (!ioaddr)
+		return -ENOMEM;
 	pdata->ioaddr = ioaddr;
 	pdata->irq = platform_get_irq(pdev, 0);
 
@@ -328,9 +320,13 @@
 	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF)
 		dev_warn(&pdev->dev, "voltage-low detected.\n");
 
+	spin_lock_init(&pdata->lock);
+	pdata->last_jiffies = jiffies;
+	platform_set_drvdata(pdev, pdata);
 	if (pdata->irq > 0) {
 		writeb(0, ioaddr + RTC_INTERRUPTS);
-		if (request_irq(pdata->irq, stk17ta8_rtc_interrupt,
+		if (devm_request_irq(&pdev->dev, pdata->irq,
+				stk17ta8_rtc_interrupt,
 				IRQF_DISABLED | IRQF_SHARED,
 				pdev->name, pdev) < 0) {
 			dev_warn(&pdev->dev, "interrupt not available.\n");
@@ -338,29 +334,14 @@
 		}
 	}
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev,
+	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				  &stk17ta8_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
-		goto out;
-	}
-	pdata->rtc = rtc;
-	pdata->last_jiffies = jiffies;
-	platform_set_drvdata(pdev, pdata);
+	if (IS_ERR(pdata->rtc))
+		return PTR_ERR(pdata->rtc);
+
 	ret = sysfs_create_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
 	if (ret)
-		goto out;
-	return 0;
- out:
-	if (pdata->rtc)
 		rtc_device_unregister(pdata->rtc);
-	if (pdata->irq > 0)
-		free_irq(pdata->irq, pdev);
-	if (ioaddr)
-		iounmap(ioaddr);
-	if (pdata->baseaddr)
-		release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
-	kfree(pdata);
 	return ret;
 }
 
@@ -370,13 +351,8 @@
 
 	sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
 	rtc_device_unregister(pdata->rtc);
-	if (pdata->irq > 0) {
+	if (pdata->irq > 0)
 		writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
-		free_irq(pdata->irq, pdev);
-	}
-	iounmap(pdata->ioaddr);
-	release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
-	kfree(pdata);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index 4a6ed11..9ee81d8 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -17,6 +17,7 @@
 struct tx4939rtc_plat_data {
 	struct rtc_device *rtc;
 	struct tx4939_rtc_reg __iomem *rtcreg;
+	spinlock_t lock;
 };
 
 static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev)
@@ -52,14 +53,14 @@
 	buf[3] = secs >> 8;
 	buf[4] = secs >> 16;
 	buf[5] = secs >> 24;
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	__raw_writel(0, &rtcreg->adr);
 	for (i = 0; i < 6; i++)
 		__raw_writel(buf[i], &rtcreg->dat);
 	ret = tx4939_rtc_cmd(rtcreg,
 			     TX4939_RTCCTL_COMMAND_SETTIME |
 			     (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	return ret;
 }
 
@@ -71,18 +72,18 @@
 	unsigned long sec;
 	unsigned char buf[6];
 
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	ret = tx4939_rtc_cmd(rtcreg,
 			     TX4939_RTCCTL_COMMAND_GETTIME |
 			     (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
 	if (ret) {
-		spin_unlock_irq(&pdata->rtc->irq_lock);
+		spin_unlock_irq(&pdata->lock);
 		return ret;
 	}
 	__raw_writel(2, &rtcreg->adr);
 	for (i = 2; i < 6; i++)
 		buf[i] = __raw_readl(&rtcreg->dat);
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
 	rtc_time_to_tm(sec, tm);
 	return rtc_valid_tm(tm);
@@ -110,13 +111,13 @@
 	buf[3] = sec >> 8;
 	buf[4] = sec >> 16;
 	buf[5] = sec >> 24;
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	__raw_writel(0, &rtcreg->adr);
 	for (i = 0; i < 6; i++)
 		__raw_writel(buf[i], &rtcreg->dat);
 	ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM |
 			     (alrm->enabled ? TX4939_RTCCTL_ALME : 0));
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	return ret;
 }
 
@@ -129,12 +130,12 @@
 	unsigned char buf[6];
 	u32 ctl;
 
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	ret = tx4939_rtc_cmd(rtcreg,
 			     TX4939_RTCCTL_COMMAND_GETALARM |
 			     (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
 	if (ret) {
-		spin_unlock_irq(&pdata->rtc->irq_lock);
+		spin_unlock_irq(&pdata->lock);
 		return ret;
 	}
 	__raw_writel(2, &rtcreg->adr);
@@ -143,7 +144,7 @@
 	ctl = __raw_readl(&rtcreg->ctl);
 	alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
 	alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
 	rtc_time_to_tm(sec, &alrm->time);
 	return rtc_valid_tm(&alrm->time);
@@ -153,11 +154,11 @@
 {
 	struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
 
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	tx4939_rtc_cmd(pdata->rtcreg,
 		       TX4939_RTCCTL_COMMAND_NOP |
 		       (enabled ? TX4939_RTCCTL_ALME : 0));
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	return 0;
 }
 
@@ -167,13 +168,14 @@
 	struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 	unsigned long events = RTC_IRQF;
 
-	spin_lock(&pdata->rtc->irq_lock);
+	spin_lock(&pdata->lock);
 	if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) {
 		events |= RTC_AF;
 		tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 	}
-	spin_unlock(&pdata->rtc->irq_lock);
-	rtc_update_irq(pdata->rtc, 1, events);
+	spin_unlock(&pdata->lock);
+	if (likely(pdata->rtc))
+		rtc_update_irq(pdata->rtc, 1, events);
 	return IRQ_HANDLED;
 }
 
@@ -194,13 +196,13 @@
 	struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 	ssize_t count;
 
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
 	     count++, size--) {
 		__raw_writel(pos++, &rtcreg->adr);
 		*buf++ = __raw_readl(&rtcreg->dat);
 	}
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	return count;
 }
 
@@ -213,13 +215,13 @@
 	struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
 	ssize_t count;
 
-	spin_lock_irq(&pdata->rtc->irq_lock);
+	spin_lock_irq(&pdata->lock);
 	for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
 	     count++, size--) {
 		__raw_writel(pos++, &rtcreg->adr);
 		__raw_writel(*buf++, &rtcreg->dat);
 	}
-	spin_unlock_irq(&pdata->rtc->irq_lock);
+	spin_unlock_irq(&pdata->lock);
 	return count;
 }
 
@@ -259,6 +261,7 @@
 	if (!pdata->rtcreg)
 		return -EBUSY;
 
+	spin_lock_init(&pdata->lock);
 	tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
 	if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
 			     IRQF_DISABLED, pdev->name, &pdev->dev) < 0)
@@ -277,14 +280,12 @@
 static int __exit tx4939_rtc_remove(struct platform_device *pdev)
 {
 	struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
-	struct rtc_device *rtc = pdata->rtc;
 
-	spin_lock_irq(&rtc->irq_lock);
-	tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
-	spin_unlock_irq(&rtc->irq_lock);
 	sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
-	rtc_device_unregister(rtc);
-	platform_set_drvdata(pdev, NULL);
+	rtc_device_unregister(pdata->rtc);
+	spin_lock_irq(&pdata->lock);
+	tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
+	spin_unlock_irq(&pdata->lock);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index ad741af..bed4cab 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -304,7 +304,6 @@
 {
 	struct v3020_platform_data *pdata = pdev->dev.platform_data;
 	struct v3020 *chip;
-	struct rtc_device *rtc;
 	int retval = -EBUSY;
 	int i;
 	int temp;
@@ -353,13 +352,12 @@
 
 	platform_set_drvdata(pdev, chip);
 
-	rtc = rtc_device_register("v3020",
+	chip->rtc = rtc_device_register("v3020",
 				&pdev->dev, &v3020_rtc_ops, THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		retval = PTR_ERR(rtc);
+	if (IS_ERR(chip->rtc)) {
+		retval = PTR_ERR(chip->rtc);
 		goto err_io;
 	}
-	chip->rtc = rtc;
 
 	return 0;
 
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index fadddac..c324424 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -327,7 +327,7 @@
 	if (!res)
 		return -EBUSY;
 
-	rtc1_base = ioremap(res->start, res->end - res->start + 1);
+	rtc1_base = ioremap(res->start, resource_size(res));
 	if (!rtc1_base)
 		return -EBUSY;
 
@@ -337,7 +337,7 @@
 		goto err_rtc1_iounmap;
 	}
 
-	rtc2_base = ioremap(res->start, res->end - res->start + 1);
+	rtc2_base = ioremap(res->start, resource_size(res));
 	if (!rtc2_base) {
 		retval = -EBUSY;
 		goto err_rtc1_iounmap;
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index f164866..f1e44052 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -354,8 +354,9 @@
 };
 
 #ifdef CONFIG_PM
-static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8350_rtc_suspend(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
 	int ret = 0;
 	u16 reg;
@@ -373,8 +374,9 @@
 	return ret;
 }
 
-static int wm8350_rtc_resume(struct platform_device *pdev)
+static int wm8350_rtc_resume(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
 	int ret;
 
@@ -484,13 +486,17 @@
 	return 0;
 }
 
+static struct dev_pm_ops wm8350_rtc_pm_ops = {
+	.suspend = wm8350_rtc_suspend,
+	.resume = wm8350_rtc_resume,
+};
+
 static struct platform_driver wm8350_rtc_driver = {
 	.probe = wm8350_rtc_probe,
 	.remove = __devexit_p(wm8350_rtc_remove),
-	.suspend = wm8350_rtc_suspend,
-	.resume = wm8350_rtc_resume,
 	.driver = {
 		.name = "wm8350-rtc",
+		.pm = &wm8350_rtc_pm_ops,
 	},
 };
 
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 6583c1a..9aae491 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -155,11 +155,11 @@
 }
 
 static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
-			int datetoo, u8 reg_base, unsigned char alm_enable)
+			u8 reg_base, unsigned char alm_enable)
 {
-	int i, xfer, nbytes;
-	unsigned char buf[8];
+	int i, xfer;
 	unsigned char rdata[10] = { 0, reg_base };
+	unsigned char *buf = rdata + 2;
 
 	static const unsigned char wel[3] = { 0, X1205_REG_SR,
 						X1205_SR_WEL };
@@ -170,9 +170,9 @@
 	static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
 
 	dev_dbg(&client->dev,
-		"%s: secs=%d, mins=%d, hours=%d\n",
-		__func__,
-		tm->tm_sec, tm->tm_min, tm->tm_hour);
+		"%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n",
+		__func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday,
+		tm->tm_mon, tm->tm_year, tm->tm_wday);
 
 	buf[CCR_SEC] = bin2bcd(tm->tm_sec);
 	buf[CCR_MIN] = bin2bcd(tm->tm_min);
@@ -180,23 +180,15 @@
 	/* set hour and 24hr bit */
 	buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
 
-	/* should we also set the date? */
-	if (datetoo) {
-		dev_dbg(&client->dev,
-			"%s: mday=%d, mon=%d, year=%d, wday=%d\n",
-			__func__,
-			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+	buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
 
-		buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
+	/* month, 1 - 12 */
+	buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
 
-		/* month, 1 - 12 */
-		buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
-
-		/* year, since the rtc epoch*/
-		buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
-		buf[CCR_WDAY] = tm->tm_wday & 0x07;
-		buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);
-	}
+	/* year, since the rtc epoch*/
+	buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
+	buf[CCR_WDAY] = tm->tm_wday & 0x07;
+	buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);
 
 	/* If writing alarm registers, set compare bits on registers 0-4 */
 	if (reg_base < X1205_CCR_BASE)
@@ -214,17 +206,8 @@
 		return -EIO;
 	}
 
-
-	/* write register's data */
-	if (datetoo)
-		nbytes = 8;
-	else
-		nbytes = 3;
-	for (i = 0; i < nbytes; i++)
-		rdata[2+i] = buf[i];
-
-	xfer = i2c_master_send(client, rdata, nbytes+2);
-	if (xfer != nbytes+2) {
+	xfer = i2c_master_send(client, rdata, sizeof(rdata));
+	if (xfer != sizeof(rdata)) {
 		dev_err(&client->dev,
 			"%s: result=%d addr=%02x, data=%02x\n",
 			__func__,
@@ -282,7 +265,7 @@
 
 	memset(&tm, 0, sizeof(tm));
 
-	err = x1205_set_datetime(client, &tm, 1, X1205_CCR_BASE, 0);
+	err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0);
 	if (err < 0)
 		dev_err(&client->dev, "unable to restart the oscillator\n");
 
@@ -481,7 +464,7 @@
 static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	return x1205_set_datetime(to_i2c_client(dev),
-		&alrm->time, 1, X1205_ALM0_BASE, alrm->enabled);
+		&alrm->time, X1205_ALM0_BASE, alrm->enabled);
 }
 
 static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -493,7 +476,7 @@
 static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	return x1205_set_datetime(to_i2c_client(dev),
-		tm, 1, X1205_CCR_BASE, 0);
+		tm, X1205_CCR_BASE, 0);
 }
 
 static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3bf7592..84d3bba 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -76,6 +76,7 @@
                  Fix bug in twa_get_param() on 4GB+.
                  Use pci_resource_len() for ioremap().
    2.26.02.012 - Add power management support.
+   2.26.02.013 - Fix bug in twa_load_sgl().
 */
 
 #include <linux/module.h>
@@ -100,7 +101,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.012"
+#define TW_DRIVER_VERSION "2.26.02.013"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -1382,10 +1383,12 @@
 		newcommand = &full_command_packet->command.newcommand;
 		newcommand->request_id__lunl =
 			cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
-		newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
-		newcommand->sg_list[0].length = cpu_to_le32(length);
+		if (length) {
+			newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
+			newcommand->sg_list[0].length = cpu_to_le32(length);
+		}
 		newcommand->sgl_entries__lunh =
-			cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), 1));
+			cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), length ? 1 : 0));
 	} else {
 		oldcommand = &full_command_packet->command.oldcommand;
 		oldcommand->request_id = request_id;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 36900c7..9191d1e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -388,6 +388,16 @@
 	  Please read the comments at the top of
 	  <file:drivers/scsi/3w-xxxx.c>.
 
+config SCSI_HPSA
+	tristate "HP Smart Array SCSI driver"
+	depends on PCI && SCSI
+	help
+	  This driver supports HP Smart Array Controllers (circa 2009).
+	  It is a SCSI alternative to the cciss driver, which is a block
+	  driver.  Anyone wishing to use HP Smart Array controllers who
+	  would prefer the devices be presented to linux as SCSI devices,
+	  rather than as generic block devices should say Y here.
+
 config SCSI_3W_9XXX
 	tristate "3ware 9xxx SATA-RAID support"
 	depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 280d3c657..92a8c50 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -91,6 +91,7 @@
 obj-$(CONFIG_SCSI_PAS16)	+= pas16.o
 obj-$(CONFIG_SCSI_T128)		+= t128.o
 obj-$(CONFIG_SCSI_DMX3191D)	+= dmx3191d.o
+obj-$(CONFIG_SCSI_HPSA)		+= hpsa.o
 obj-$(CONFIG_SCSI_DTC3280)	+= dtc.o
 obj-$(CONFIG_SCSI_SYM53C8XX_2)	+= sym53c8xx_2/
 obj-$(CONFIG_SCSI_ZALON)	+= zalon7xx.o
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c
index 698a527..f008708 100644
--- a/drivers/scsi/be2iscsi/be_cmds.c
+++ b/drivers/scsi/be2iscsi/be_cmds.c
@@ -135,11 +135,15 @@
 	while ((compl = be_mcc_compl_get(phba))) {
 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
 			/* Interpret flags as an async trailer */
-			BUG_ON(!is_link_state_evt(compl->flags));
+			if (is_link_state_evt(compl->flags))
+				/* Interpret compl as a async link evt */
+				beiscsi_async_link_state_process(phba,
+				   (struct be_async_event_link_state *) compl);
+			else
+				SE_DEBUG(DBG_LVL_1,
+					 " Unsupported Async Event, flags"
+					 " = 0x%08x \n", compl->flags);
 
-			/* Interpret compl as a async link evt */
-			beiscsi_async_link_state_process(phba,
-				(struct be_async_event_link_state *) compl);
 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
 				status = be_mcc_compl_process(ctrl, compl);
 				atomic_dec(&phba->ctrl.mcc_obj.q.used);
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 2b973f3..6cf9dc3 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -684,6 +684,7 @@
 extern u64 iscsi_error_mask;
 extern unsigned int en_tcp_dack;
 extern unsigned int event_coal_div;
+extern unsigned int event_coal_min;
 
 extern struct scsi_transport_template *bnx2i_scsi_xport_template;
 extern struct iscsi_transport bnx2i_iscsi_transport;
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 5c8d763..1af578d 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -133,20 +133,38 @@
 {
 	struct bnx2i_5771x_cq_db *cq_db;
 	u16 cq_index;
+	u16 next_index;
+	u32 num_active_cmds;
 
+
+	/* Coalesce CQ entries only on 10G devices */
 	if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
 		return;
 
+	/* Do not update CQ DB multiple times before firmware writes
+	 * '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
+	 * interrupts and other unwanted results
+	 */
+	cq_db = (struct bnx2i_5771x_cq_db *) ep->qp.cq_pgtbl_virt;
+	if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
+		return;
+
 	if (action == CNIC_ARM_CQE) {
-		cq_index = ep->qp.cqe_exp_seq_sn +
-			   ep->num_active_cmds / event_coal_div;
-		cq_index %= (ep->qp.cqe_size * 2 + 1);
-		if (!cq_index) {
+		num_active_cmds = ep->num_active_cmds;
+		if (num_active_cmds <= event_coal_min)
+			next_index = 1;
+		else
+			next_index = event_coal_min +
+				(num_active_cmds - event_coal_min) / event_coal_div;
+		if (!next_index)
+			next_index = 1;
+		cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
+		if (cq_index > ep->qp.cqe_size * 2)
+			cq_index -= ep->qp.cqe_size * 2;
+		if (!cq_index)
 			cq_index = 1;
-			cq_db = (struct bnx2i_5771x_cq_db *)
-					ep->qp.cq_pgtbl_virt;
-			cq_db->sqn[0] = cq_index;
-		}
+
+		cq_db->sqn[0] = cq_index;
 	}
 }
 
@@ -366,6 +384,7 @@
 	struct bnx2i_cmd *bnx2i_cmd;
 	struct bnx2i_tmf_request *tmfabort_wqe;
 	u32 dword;
+	u32 scsi_lun[2];
 
 	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
 	tmfabort_hdr = (struct iscsi_tm *)mtask->hdr;
@@ -376,27 +395,35 @@
 	tmfabort_wqe->op_attr = 0;
 	tmfabort_wqe->op_attr =
 		ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK;
-	tmfabort_wqe->lun[0] = be32_to_cpu(tmfabort_hdr->lun[0]);
-	tmfabort_wqe->lun[1] = be32_to_cpu(tmfabort_hdr->lun[1]);
 
 	tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14));
 	tmfabort_wqe->reserved2 = 0;
 	tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn);
 
 	ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt);
-	if (!ctask || ctask->sc)
+	if (!ctask || !ctask->sc)
 		/*
 		 * the iscsi layer must have completed the cmd while this
 		 * was starting up.
+		 *
+		 * Note: In the case of a SCSI cmd timeout, the task's sc
+		 *       is still active; hence ctask->sc != 0
+		 *       In this case, the task must be aborted
 		 */
 		return 0;
+
 	ref_sc = ctask->sc;
 
+	/* Retrieve LUN directly from the ref_sc */
+	int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun);
+	tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
+	tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
+
 	if (ref_sc->sc_data_direction == DMA_TO_DEVICE)
 		dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
 	else
 		dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
-	tmfabort_wqe->ref_itt = (dword | tmfabort_hdr->rtt);
+	tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK));
 	tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn);
 
 	tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 0c4210d..6d8172e 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -17,8 +17,8 @@
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.0.1e"
-#define DRV_MODULE_RELDATE	"June 22, 2009"
+#define DRV_MODULE_VERSION	"2.1.0"
+#define DRV_MODULE_RELDATE	"Dec 06, 2009"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -32,6 +32,10 @@
 
 static DEFINE_MUTEX(bnx2i_dev_lock);
 
+unsigned int event_coal_min = 24;
+module_param(event_coal_min, int, 0664);
+MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
+
 unsigned int event_coal_div = 1;
 module_param(event_coal_div, int, 0664);
 MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
@@ -83,8 +87,12 @@
 		set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
 		hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
 	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711)
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E)
 		set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
+	else
+		printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
+				  hba->pci_did);
 }
 
 
@@ -363,7 +371,7 @@
 
 	printk(KERN_INFO "%s", version);
 
-	if (!is_power_of_2(sq_size))
+	if (sq_size && !is_power_of_2(sq_size))
 		sq_size = roundup_pow_of_two(sq_size);
 
 	mutex_init(&bnx2i_dev_lock);
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 132898c..33b2294 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -485,7 +485,6 @@
 		struct iscsi_task *task = session->cmds[i];
 		struct bnx2i_cmd *cmd = task->dd_data;
 
-		/* Anil */
 		task->hdr = &cmd->hdr;
 		task->hdr_max = sizeof(struct iscsi_hdr);
 
@@ -765,7 +764,6 @@
 	hba->pci_svid = hba->pcidev->subsystem_vendor;
 	hba->pci_func = PCI_FUNC(hba->pcidev->devfn);
 	hba->pci_devno = PCI_SLOT(hba->pcidev->devfn);
-	bnx2i_identify_device(hba);
 
 	bnx2i_identify_device(hba);
 	bnx2i_setup_host_queue_size(hba, shost);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
index c1d5be4..26ffdcd 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
@@ -291,7 +291,7 @@
 	c3cn_hold(c3cn);
 	spin_lock_bh(&c3cn->lock);
 	if (c3cn->state == C3CN_STATE_CONNECTING)
-		fail_act_open(c3cn, EHOSTUNREACH);
+		fail_act_open(c3cn, -EHOSTUNREACH);
 	spin_unlock_bh(&c3cn->lock);
 	c3cn_put(c3cn);
 	__kfree_skb(skb);
@@ -792,18 +792,18 @@
 {
 	switch (status) {
 	case CPL_ERR_CONN_RESET:
-		return ECONNREFUSED;
+		return -ECONNREFUSED;
 	case CPL_ERR_ARP_MISS:
-		return EHOSTUNREACH;
+		return -EHOSTUNREACH;
 	case CPL_ERR_CONN_TIMEDOUT:
-		return ETIMEDOUT;
+		return -ETIMEDOUT;
 	case CPL_ERR_TCAM_FULL:
-		return ENOMEM;
+		return -ENOMEM;
 	case CPL_ERR_CONN_EXIST:
 		cxgb3i_log_error("ACTIVE_OPEN_RPL: 4-tuple in use\n");
-		return EADDRINUSE;
+		return -EADDRINUSE;
 	default:
-		return EIO;
+		return -EIO;
 	}
 }
 
@@ -817,7 +817,7 @@
 	spin_lock_bh(&c3cn->lock);
 	skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC);
 	if (!skb)
-		fail_act_open(c3cn, ENOMEM);
+		fail_act_open(c3cn, -ENOMEM);
 	else {
 		skb->sk = (struct sock *)c3cn;
 		set_arp_failure_handler(skb, act_open_req_arp_failure);
@@ -966,14 +966,14 @@
 	case CPL_ERR_BAD_SYN: /* fall through */
 	case CPL_ERR_CONN_RESET:
 		return c3cn->state > C3CN_STATE_ESTABLISHED ?
-			EPIPE : ECONNRESET;
+			-EPIPE : -ECONNRESET;
 	case CPL_ERR_XMIT_TIMEDOUT:
 	case CPL_ERR_PERSIST_TIMEDOUT:
 	case CPL_ERR_FINWAIT2_TIMEDOUT:
 	case CPL_ERR_KEEPALIVE_TIMEDOUT:
-		return ETIMEDOUT;
+		return -ETIMEDOUT;
 	default:
-		return EIO;
+		return -EIO;
 	}
 }
 
@@ -1563,7 +1563,7 @@
 	s3_free_atid(cdev, c3cn->tid);
 	c3cn->tid = 0;
 out_err:
-	return -1;
+	return -EINVAL;
 }
 
 
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
index 7091050..1fe3b0f 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
@@ -388,8 +388,8 @@
 	if (err > 0) {
 		int pdulen = err;
 
-	cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
-			task, skb, skb->len, skb->data_len, err);
+		cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+				task, skb, skb->len, skb->data_len, err);
 
 		if (task->conn->hdrdgst_en)
 			pdulen += ISCSI_DIGEST_SIZE;
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 47cfe1c..1a66019 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -748,6 +748,8 @@
 	{"IBM", "1724"},
 	{"IBM", "1726"},
 	{"IBM", "1742"},
+	{"IBM", "1745"},
+	{"IBM", "1746"},
 	{"IBM", "1814"},
 	{"IBM", "1815"},
 	{"IBM", "1818"},
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index a30ffaa..e3896fc 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -101,6 +101,8 @@
 
 static int fcoe_create(const char *, struct kernel_param *);
 static int fcoe_destroy(const char *, struct kernel_param *);
+static int fcoe_enable(const char *, struct kernel_param *);
+static int fcoe_disable(const char *, struct kernel_param *);
 
 static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
 				      u32 did, struct fc_frame *,
@@ -115,10 +117,16 @@
 
 module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, "Create fcoe fcoe using net device passed in.");
+MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
 module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
 __MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, "Destroy fcoe fcoe");
+MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
+module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(enable, "string");
+MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
+module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(disable, "string");
+MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
 
 /* notification function for packets from net device */
 static struct notifier_block fcoe_notifier = {
@@ -545,6 +553,23 @@
 }
 
 /**
+ * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
+ * @netdev: the associated net device
+ * @wwn: the output WWN
+ * @type: the type of WWN (WWPN or WWNN)
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
+{
+	const struct net_device_ops *ops = netdev->netdev_ops;
+
+	if (ops->ndo_fcoe_get_wwn)
+		return ops->ndo_fcoe_get_wwn(netdev, wwn, type);
+	return -EINVAL;
+}
+
+/**
  * fcoe_netdev_config() - Set up net devive for SW FCoE
  * @lport:  The local port that is associated with the net device
  * @netdev: The associated net device
@@ -611,9 +636,13 @@
 		 */
 		if (netdev->priv_flags & IFF_802_1Q_VLAN)
 			vid = vlan_dev_vlan_id(netdev);
-		wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
+
+		if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
+			wwnn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 1, 0);
 		fc_set_wwnn(lport, wwnn);
-		wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr, 2, vid);
+		if (fcoe_get_wwn(netdev, &wwpn, NETDEV_FCOE_WWPN))
+			wwpn = fcoe_wwn_from_mac(fcoe->ctlr.ctl_src_addr,
+						 2, vid);
 		fc_set_wwpn(lport, wwpn);
 	}
 
@@ -1838,6 +1867,104 @@
 }
 
 /**
+ * fcoe_disable() - Disables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be disabled
+ * @kp:	    The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_disable(const char *buffer, struct kernel_param *kp)
+{
+	struct fcoe_interface *fcoe;
+	struct net_device *netdev;
+	int rc = 0;
+
+	mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module paramter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+
+	rtnl_lock();
+	fcoe = fcoe_hostlist_lookup_port(netdev);
+	rtnl_unlock();
+
+	if (fcoe)
+		fc_fabric_logoff(fcoe->ctlr.lp);
+	else
+		rc = -ENODEV;
+
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
+	return rc;
+}
+
+/**
+ * fcoe_enable() - Enables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be enabled
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_enable(const char *buffer, struct kernel_param *kp)
+{
+	struct fcoe_interface *fcoe;
+	struct net_device *netdev;
+	int rc = 0;
+
+	mutex_lock(&fcoe_config_mutex);
+#ifdef CONFIG_FCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module paramter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		rc = -ENODEV;
+		goto out_nodev;
+	}
+
+	rtnl_lock();
+	fcoe = fcoe_hostlist_lookup_port(netdev);
+	rtnl_unlock();
+
+	if (fcoe)
+		rc = fc_fabric_login(fcoe->ctlr.lp);
+	else
+		rc = -ENODEV;
+
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&fcoe_config_mutex);
+	return rc;
+}
+
+/**
  * fcoe_destroy() - Destroy a FCoE interface
  * @buffer: The name of the Ethernet interface to be destroyed
  * @kp:	    The associated kernel parameter
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
new file mode 100644
index 0000000..bb96fdd
--- /dev/null
+++ b/drivers/scsi/hpsa.c
@@ -0,0 +1,3531 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; 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, 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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/compat.h>
+#include <linux/blktrace_api.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <linux/cciss_ioctl.h>
+#include <linux/string.h>
+#include <linux/bitmap.h>
+#include <asm/atomic.h>
+#include <linux/kthread.h>
+#include "hpsa_cmd.h"
+#include "hpsa.h"
+
+/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */
+#define HPSA_DRIVER_VERSION "1.0.0"
+#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
+
+/* How long to wait (in milliseconds) for board to go into simple mode */
+#define MAX_CONFIG_WAIT 30000
+#define MAX_IOCTL_CONFIG_WAIT 1000
+
+/*define how many times we will try a command because of bus resets */
+#define MAX_CMD_RETRIES 3
+
+/* Embedded module documentation macros - see modules.h */
+MODULE_AUTHOR("Hewlett-Packard Company");
+MODULE_DESCRIPTION("Driver for HP Smart Array Controller version " \
+	HPSA_DRIVER_VERSION);
+MODULE_SUPPORTED_DEVICE("HP Smart Array Controllers");
+MODULE_VERSION(HPSA_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+static int hpsa_allow_any;
+module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hpsa_allow_any,
+		"Allow hpsa driver to access unknown HP Smart Array hardware");
+
+/* define the PCI info for the cards we can control */
+static const struct pci_device_id hpsa_pci_device_id[] = {
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3223},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3234},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x323D},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3241},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3243},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3245},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3247},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324a},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324b},
+	{PCI_VENDOR_ID_HP,     PCI_ANY_ID,             PCI_ANY_ID, PCI_ANY_ID,
+		PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id);
+
+/*  board_id = Subsystem Device ID & Vendor ID
+ *  product = Marketing Name for the board
+ *  access = Address of the struct of function pointers
+ */
+static struct board_type products[] = {
+	{0x3223103C, "Smart Array P800", &SA5_access},
+	{0x3234103C, "Smart Array P400", &SA5_access},
+	{0x323d103c, "Smart Array P700M", &SA5_access},
+	{0x3241103C, "Smart Array P212", &SA5_access},
+	{0x3243103C, "Smart Array P410", &SA5_access},
+	{0x3245103C, "Smart Array P410i", &SA5_access},
+	{0x3247103C, "Smart Array P411", &SA5_access},
+	{0x3249103C, "Smart Array P812", &SA5_access},
+	{0x324a103C, "Smart Array P712m", &SA5_access},
+	{0x324b103C, "Smart Array P711m", &SA5_access},
+	{0xFFFF103C, "Unknown Smart Array", &SA5_access},
+};
+
+static int number_of_controllers;
+
+static irqreturn_t do_hpsa_intr(int irq, void *dev_id);
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg);
+static void start_io(struct ctlr_info *h);
+
+#ifdef CONFIG_COMPAT
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg);
+#endif
+
+static void cmd_free(struct ctlr_info *h, struct CommandList *c);
+static void cmd_special_free(struct ctlr_info *h, struct CommandList *c);
+static struct CommandList *cmd_alloc(struct ctlr_info *h);
+static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
+static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
+	void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+	int cmd_type);
+
+static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
+		void (*done)(struct scsi_cmnd *));
+
+static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
+static int hpsa_slave_alloc(struct scsi_device *sdev);
+static void hpsa_slave_destroy(struct scsi_device *sdev);
+
+static ssize_t raid_level_show(struct device *dev,
+	struct device_attribute *attr, char *buf);
+static ssize_t lunid_show(struct device *dev,
+	struct device_attribute *attr, char *buf);
+static ssize_t unique_id_show(struct device *dev,
+	struct device_attribute *attr, char *buf);
+static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
+static ssize_t host_store_rescan(struct device *dev,
+	 struct device_attribute *attr, const char *buf, size_t count);
+static int check_for_unit_attention(struct ctlr_info *h,
+	struct CommandList *c);
+static void check_ioctl_unit_attention(struct ctlr_info *h,
+	struct CommandList *c);
+
+static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
+static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
+
+static struct device_attribute *hpsa_sdev_attrs[] = {
+	&dev_attr_raid_level,
+	&dev_attr_lunid,
+	&dev_attr_unique_id,
+	NULL,
+};
+
+static struct device_attribute *hpsa_shost_attrs[] = {
+	&dev_attr_rescan,
+	NULL,
+};
+
+static struct scsi_host_template hpsa_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "hpsa",
+	.proc_name		= "hpsa",
+	.queuecommand		= hpsa_scsi_queue_command,
+	.can_queue		= 512,
+	.this_id		= -1,
+	.sg_tablesize		= MAXSGENTRIES,
+	.cmd_per_lun		= 512,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.eh_device_reset_handler = hpsa_eh_device_reset_handler,
+	.ioctl			= hpsa_ioctl,
+	.slave_alloc		= hpsa_slave_alloc,
+	.slave_destroy		= hpsa_slave_destroy,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= hpsa_compat_ioctl,
+#endif
+	.sdev_attrs = hpsa_sdev_attrs,
+	.shost_attrs = hpsa_shost_attrs,
+};
+
+static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
+{
+	unsigned long *priv = shost_priv(sdev->host);
+	return (struct ctlr_info *) *priv;
+}
+
+static struct task_struct *hpsa_scan_thread;
+static DEFINE_MUTEX(hpsa_scan_mutex);
+static LIST_HEAD(hpsa_scan_q);
+static int hpsa_scan_func(void *data);
+
+/**
+ * add_to_scan_list() - add controller to rescan queue
+ * @h:		      Pointer to the controller.
+ *
+ * Adds the controller to the rescan queue if not already on the queue.
+ *
+ * returns 1 if added to the queue, 0 if skipped (could be on the
+ * queue already, or the controller could be initializing or shutting
+ * down).
+ **/
+static int add_to_scan_list(struct ctlr_info *h)
+{
+	struct ctlr_info *test_h;
+	int found = 0;
+	int ret = 0;
+
+	if (h->busy_initializing)
+		return 0;
+
+	/*
+	 * If we don't get the lock, it means the driver is unloading
+	 * and there's no point in scheduling a new scan.
+	 */
+	if (!mutex_trylock(&h->busy_shutting_down))
+		return 0;
+
+	mutex_lock(&hpsa_scan_mutex);
+	list_for_each_entry(test_h, &hpsa_scan_q, scan_list) {
+		if (test_h == h) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found && !h->busy_scanning) {
+		INIT_COMPLETION(h->scan_wait);
+		list_add_tail(&h->scan_list, &hpsa_scan_q);
+		ret = 1;
+	}
+	mutex_unlock(&hpsa_scan_mutex);
+	mutex_unlock(&h->busy_shutting_down);
+
+	return ret;
+}
+
+/**
+ * remove_from_scan_list() - remove controller from rescan queue
+ * @h:			   Pointer to the controller.
+ *
+ * Removes the controller from the rescan queue if present. Blocks if
+ * the controller is currently conducting a rescan.  The controller
+ * can be in one of three states:
+ * 1. Doesn't need a scan
+ * 2. On the scan list, but not scanning yet (we remove it)
+ * 3. Busy scanning (and not on the list). In this case we want to wait for
+ *    the scan to complete to make sure the scanning thread for this
+ *    controller is completely idle.
+ **/
+static void remove_from_scan_list(struct ctlr_info *h)
+{
+	struct ctlr_info *test_h, *tmp_h;
+
+	mutex_lock(&hpsa_scan_mutex);
+	list_for_each_entry_safe(test_h, tmp_h, &hpsa_scan_q, scan_list) {
+		if (test_h == h) { /* state 2. */
+			list_del(&h->scan_list);
+			complete_all(&h->scan_wait);
+			mutex_unlock(&hpsa_scan_mutex);
+			return;
+		}
+	}
+	if (h->busy_scanning) { /* state 3. */
+		mutex_unlock(&hpsa_scan_mutex);
+		wait_for_completion(&h->scan_wait);
+	} else { /* state 1, nothing to do. */
+		mutex_unlock(&hpsa_scan_mutex);
+	}
+}
+
+/* hpsa_scan_func() - kernel thread used to rescan controllers
+ * @data:	 Ignored.
+ *
+ * A kernel thread used scan for drive topology changes on
+ * controllers. The thread processes only one controller at a time
+ * using a queue.  Controllers are added to the queue using
+ * add_to_scan_list() and removed from the queue either after done
+ * processing or using remove_from_scan_list().
+ *
+ * returns 0.
+ **/
+static int hpsa_scan_func(__attribute__((unused)) void *data)
+{
+	struct ctlr_info *h;
+	int host_no;
+
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (kthread_should_stop())
+			break;
+
+		while (1) {
+			mutex_lock(&hpsa_scan_mutex);
+			if (list_empty(&hpsa_scan_q)) {
+				mutex_unlock(&hpsa_scan_mutex);
+				break;
+			}
+			h = list_entry(hpsa_scan_q.next, struct ctlr_info,
+					scan_list);
+			list_del(&h->scan_list);
+			h->busy_scanning = 1;
+			mutex_unlock(&hpsa_scan_mutex);
+			host_no = h->scsi_host ?  h->scsi_host->host_no : -1;
+			hpsa_update_scsi_devices(h, host_no);
+			complete_all(&h->scan_wait);
+			mutex_lock(&hpsa_scan_mutex);
+			h->busy_scanning = 0;
+			mutex_unlock(&hpsa_scan_mutex);
+		}
+	}
+	return 0;
+}
+
+static int check_for_unit_attention(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	if (c->err_info->SenseInfo[2] != UNIT_ATTENTION)
+		return 0;
+
+	switch (c->err_info->SenseInfo[12]) {
+	case STATE_CHANGED:
+		dev_warn(&h->pdev->dev, "hpsa%d: a state change "
+			"detected, command retried\n", h->ctlr);
+		break;
+	case LUN_FAILED:
+		dev_warn(&h->pdev->dev, "hpsa%d: LUN failure "
+			"detected, action required\n", h->ctlr);
+		break;
+	case REPORT_LUNS_CHANGED:
+		dev_warn(&h->pdev->dev, "hpsa%d: report LUN data "
+			"changed\n", h->ctlr);
+	/*
+	 * Here, we could call add_to_scan_list and wake up the scan thread,
+	 * except that it's quite likely that we will get more than one
+	 * REPORT_LUNS_CHANGED condition in quick succession, which means
+	 * that those which occur after the first one will likely happen
+	 * *during* the hpsa_scan_thread's rescan.  And the rescan code is not
+	 * robust enough to restart in the middle, undoing what it has already
+	 * done, and it's not clear that it's even possible to do this, since
+	 * part of what it does is notify the SCSI mid layer, which starts
+	 * doing it's own i/o to read partition tables and so on, and the
+	 * driver doesn't have visibility to know what might need undoing.
+	 * In any event, if possible, it is horribly complicated to get right
+	 * so we just don't do it for now.
+	 *
+	 * Note: this REPORT_LUNS_CHANGED condition only occurs on the MSA2012.
+	 */
+		break;
+	case POWER_OR_RESET:
+		dev_warn(&h->pdev->dev, "hpsa%d: a power on "
+			"or device reset detected\n", h->ctlr);
+		break;
+	case UNIT_ATTENTION_CLEARED:
+		dev_warn(&h->pdev->dev, "hpsa%d: unit attention "
+		    "cleared by another initiator\n", h->ctlr);
+		break;
+	default:
+		dev_warn(&h->pdev->dev, "hpsa%d: unknown "
+			"unit attention detected\n", h->ctlr);
+		break;
+	}
+	return 1;
+}
+
+static ssize_t host_store_rescan(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct ctlr_info *h;
+	struct Scsi_Host *shost = class_to_shost(dev);
+	unsigned long *priv = shost_priv(shost);
+	h = (struct ctlr_info *) *priv;
+	if (add_to_scan_list(h)) {
+		wake_up_process(hpsa_scan_thread);
+		wait_for_completion_interruptible(&h->scan_wait);
+	}
+	return count;
+}
+
+/* Enqueuing and dequeuing functions for cmdlists. */
+static inline void addQ(struct hlist_head *list, struct CommandList *c)
+{
+	hlist_add_head(&c->list, list);
+}
+
+static void enqueue_cmd_and_start_io(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&h->lock, flags);
+	addQ(&h->reqQ, c);
+	h->Qdepth++;
+	start_io(h);
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static inline void removeQ(struct CommandList *c)
+{
+	if (WARN_ON(hlist_unhashed(&c->list)))
+		return;
+	hlist_del_init(&c->list);
+}
+
+static inline int is_hba_lunid(unsigned char scsi3addr[])
+{
+	return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+}
+
+static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
+{
+	return (scsi3addr[3] & 0xC0) == 0x40;
+}
+
+static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
+	"UNKNOWN"
+};
+#define RAID_UNKNOWN (ARRAY_SIZE(raid_label) - 1)
+
+static ssize_t raid_level_show(struct device *dev,
+	     struct device_attribute *attr, char *buf)
+{
+	ssize_t l = 0;
+	int rlevel;
+	struct ctlr_info *h;
+	struct scsi_device *sdev;
+	struct hpsa_scsi_dev_t *hdev;
+	unsigned long flags;
+
+	sdev = to_scsi_device(dev);
+	h = sdev_to_hba(sdev);
+	spin_lock_irqsave(&h->lock, flags);
+	hdev = sdev->hostdata;
+	if (!hdev) {
+		spin_unlock_irqrestore(&h->lock, flags);
+		return -ENODEV;
+	}
+
+	/* Is this even a logical drive? */
+	if (!is_logical_dev_addr_mode(hdev->scsi3addr)) {
+		spin_unlock_irqrestore(&h->lock, flags);
+		l = snprintf(buf, PAGE_SIZE, "N/A\n");
+		return l;
+	}
+
+	rlevel = hdev->raid_level;
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (rlevel < 0 || rlevel > RAID_UNKNOWN)
+		rlevel = RAID_UNKNOWN;
+	l = snprintf(buf, PAGE_SIZE, "RAID %s\n", raid_label[rlevel]);
+	return l;
+}
+
+static ssize_t lunid_show(struct device *dev,
+	     struct device_attribute *attr, char *buf)
+{
+	struct ctlr_info *h;
+	struct scsi_device *sdev;
+	struct hpsa_scsi_dev_t *hdev;
+	unsigned long flags;
+	unsigned char lunid[8];
+
+	sdev = to_scsi_device(dev);
+	h = sdev_to_hba(sdev);
+	spin_lock_irqsave(&h->lock, flags);
+	hdev = sdev->hostdata;
+	if (!hdev) {
+		spin_unlock_irqrestore(&h->lock, flags);
+		return -ENODEV;
+	}
+	memcpy(lunid, hdev->scsi3addr, sizeof(lunid));
+	spin_unlock_irqrestore(&h->lock, flags);
+	return snprintf(buf, 20, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+		lunid[0], lunid[1], lunid[2], lunid[3],
+		lunid[4], lunid[5], lunid[6], lunid[7]);
+}
+
+static ssize_t unique_id_show(struct device *dev,
+	     struct device_attribute *attr, char *buf)
+{
+	struct ctlr_info *h;
+	struct scsi_device *sdev;
+	struct hpsa_scsi_dev_t *hdev;
+	unsigned long flags;
+	unsigned char sn[16];
+
+	sdev = to_scsi_device(dev);
+	h = sdev_to_hba(sdev);
+	spin_lock_irqsave(&h->lock, flags);
+	hdev = sdev->hostdata;
+	if (!hdev) {
+		spin_unlock_irqrestore(&h->lock, flags);
+		return -ENODEV;
+	}
+	memcpy(sn, hdev->device_id, sizeof(sn));
+	spin_unlock_irqrestore(&h->lock, flags);
+	return snprintf(buf, 16 * 2 + 2,
+			"%02X%02X%02X%02X%02X%02X%02X%02X"
+			"%02X%02X%02X%02X%02X%02X%02X%02X\n",
+			sn[0], sn[1], sn[2], sn[3],
+			sn[4], sn[5], sn[6], sn[7],
+			sn[8], sn[9], sn[10], sn[11],
+			sn[12], sn[13], sn[14], sn[15]);
+}
+
+static int hpsa_find_target_lun(struct ctlr_info *h,
+	unsigned char scsi3addr[], int bus, int *target, int *lun)
+{
+	/* finds an unused bus, target, lun for a new physical device
+	 * assumes h->devlock is held
+	 */
+	int i, found = 0;
+	DECLARE_BITMAP(lun_taken, HPSA_MAX_SCSI_DEVS_PER_HBA);
+
+	memset(&lun_taken[0], 0, HPSA_MAX_SCSI_DEVS_PER_HBA >> 3);
+
+	for (i = 0; i < h->ndevices; i++) {
+		if (h->dev[i]->bus == bus && h->dev[i]->target != -1)
+			set_bit(h->dev[i]->target, lun_taken);
+	}
+
+	for (i = 0; i < HPSA_MAX_SCSI_DEVS_PER_HBA; i++) {
+		if (!test_bit(i, lun_taken)) {
+			/* *bus = 1; */
+			*target = i;
+			*lun = 0;
+			found = 1;
+			break;
+		}
+	}
+	return !found;
+}
+
+/* Add an entry into h->dev[] array. */
+static int hpsa_scsi_add_entry(struct ctlr_info *h, int hostno,
+		struct hpsa_scsi_dev_t *device,
+		struct hpsa_scsi_dev_t *added[], int *nadded)
+{
+	/* assumes h->devlock is held */
+	int n = h->ndevices;
+	int i;
+	unsigned char addr1[8], addr2[8];
+	struct hpsa_scsi_dev_t *sd;
+
+	if (n >= HPSA_MAX_SCSI_DEVS_PER_HBA) {
+		dev_err(&h->pdev->dev, "too many devices, some will be "
+			"inaccessible.\n");
+		return -1;
+	}
+
+	/* physical devices do not have lun or target assigned until now. */
+	if (device->lun != -1)
+		/* Logical device, lun is already assigned. */
+		goto lun_assigned;
+
+	/* If this device a non-zero lun of a multi-lun device
+	 * byte 4 of the 8-byte LUN addr will contain the logical
+	 * unit no, zero otherise.
+	 */
+	if (device->scsi3addr[4] == 0) {
+		/* This is not a non-zero lun of a multi-lun device */
+		if (hpsa_find_target_lun(h, device->scsi3addr,
+			device->bus, &device->target, &device->lun) != 0)
+			return -1;
+		goto lun_assigned;
+	}
+
+	/* This is a non-zero lun of a multi-lun device.
+	 * Search through our list and find the device which
+	 * has the same 8 byte LUN address, excepting byte 4.
+	 * Assign the same bus and target for this new LUN.
+	 * Use the logical unit number from the firmware.
+	 */
+	memcpy(addr1, device->scsi3addr, 8);
+	addr1[4] = 0;
+	for (i = 0; i < n; i++) {
+		sd = h->dev[i];
+		memcpy(addr2, sd->scsi3addr, 8);
+		addr2[4] = 0;
+		/* differ only in byte 4? */
+		if (memcmp(addr1, addr2, 8) == 0) {
+			device->bus = sd->bus;
+			device->target = sd->target;
+			device->lun = device->scsi3addr[4];
+			break;
+		}
+	}
+	if (device->lun == -1) {
+		dev_warn(&h->pdev->dev, "physical device with no LUN=0,"
+			" suspect firmware bug or unsupported hardware "
+			"configuration.\n");
+			return -1;
+	}
+
+lun_assigned:
+
+	h->dev[n] = device;
+	h->ndevices++;
+	added[*nadded] = device;
+	(*nadded)++;
+
+	/* initially, (before registering with scsi layer) we don't
+	 * know our hostno and we don't want to print anything first
+	 * time anyway (the scsi layer's inquiries will show that info)
+	 */
+	/* if (hostno != -1) */
+		dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n",
+			scsi_device_type(device->devtype), hostno,
+			device->bus, device->target, device->lun);
+	return 0;
+}
+
+/* Remove an entry from h->dev[] array. */
+static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
+	struct hpsa_scsi_dev_t *removed[], int *nremoved)
+{
+	/* assumes h->devlock is held */
+	int i;
+	struct hpsa_scsi_dev_t *sd;
+
+	if (entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA)
+		BUG();
+
+	sd = h->dev[entry];
+	removed[*nremoved] = h->dev[entry];
+	(*nremoved)++;
+
+	for (i = entry; i < h->ndevices-1; i++)
+		h->dev[i] = h->dev[i+1];
+	h->ndevices--;
+	dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n",
+		scsi_device_type(sd->devtype), hostno, sd->bus, sd->target,
+		sd->lun);
+}
+
+#define SCSI3ADDR_EQ(a, b) ( \
+	(a)[7] == (b)[7] && \
+	(a)[6] == (b)[6] && \
+	(a)[5] == (b)[5] && \
+	(a)[4] == (b)[4] && \
+	(a)[3] == (b)[3] && \
+	(a)[2] == (b)[2] && \
+	(a)[1] == (b)[1] && \
+	(a)[0] == (b)[0])
+
+static void fixup_botched_add(struct ctlr_info *h,
+	struct hpsa_scsi_dev_t *added)
+{
+	/* called when scsi_add_device fails in order to re-adjust
+	 * h->dev[] to match the mid layer's view.
+	 */
+	unsigned long flags;
+	int i, j;
+
+	spin_lock_irqsave(&h->lock, flags);
+	for (i = 0; i < h->ndevices; i++) {
+		if (h->dev[i] == added) {
+			for (j = i; j < h->ndevices-1; j++)
+				h->dev[j] = h->dev[j+1];
+			h->ndevices--;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	kfree(added);
+}
+
+static inline int device_is_the_same(struct hpsa_scsi_dev_t *dev1,
+	struct hpsa_scsi_dev_t *dev2)
+{
+	if ((is_logical_dev_addr_mode(dev1->scsi3addr) ||
+		(dev1->lun != -1 && dev2->lun != -1)) &&
+		dev1->devtype != 0x0C)
+		return (memcmp(dev1, dev2, sizeof(*dev1)) == 0);
+
+	/* we compare everything except lun and target as these
+	 * are not yet assigned.  Compare parts likely
+	 * to differ first
+	 */
+	if (memcmp(dev1->scsi3addr, dev2->scsi3addr,
+		sizeof(dev1->scsi3addr)) != 0)
+		return 0;
+	if (memcmp(dev1->device_id, dev2->device_id,
+		sizeof(dev1->device_id)) != 0)
+		return 0;
+	if (memcmp(dev1->model, dev2->model, sizeof(dev1->model)) != 0)
+		return 0;
+	if (memcmp(dev1->vendor, dev2->vendor, sizeof(dev1->vendor)) != 0)
+		return 0;
+	if (memcmp(dev1->revision, dev2->revision, sizeof(dev1->revision)) != 0)
+		return 0;
+	if (dev1->devtype != dev2->devtype)
+		return 0;
+	if (dev1->raid_level != dev2->raid_level)
+		return 0;
+	if (dev1->bus != dev2->bus)
+		return 0;
+	return 1;
+}
+
+/* Find needle in haystack.  If exact match found, return DEVICE_SAME,
+ * and return needle location in *index.  If scsi3addr matches, but not
+ * vendor, model, serial num, etc. return DEVICE_CHANGED, and return needle
+ * location in *index.  If needle not found, return DEVICE_NOT_FOUND.
+ */
+static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
+	struct hpsa_scsi_dev_t *haystack[], int haystack_size,
+	int *index)
+{
+	int i;
+#define DEVICE_NOT_FOUND 0
+#define DEVICE_CHANGED 1
+#define DEVICE_SAME 2
+	for (i = 0; i < haystack_size; i++) {
+		if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) {
+			*index = i;
+			if (device_is_the_same(needle, haystack[i]))
+				return DEVICE_SAME;
+			else
+				return DEVICE_CHANGED;
+		}
+	}
+	*index = -1;
+	return DEVICE_NOT_FOUND;
+}
+
+static int adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
+	struct hpsa_scsi_dev_t *sd[], int nsds)
+{
+	/* sd contains scsi3 addresses and devtypes, and inquiry
+	 * data.  This function takes what's in sd to be the current
+	 * reality and updates h->dev[] to reflect that reality.
+	 */
+	int i, entry, device_change, changes = 0;
+	struct hpsa_scsi_dev_t *csd;
+	unsigned long flags;
+	struct hpsa_scsi_dev_t **added, **removed;
+	int nadded, nremoved;
+	struct Scsi_Host *sh = NULL;
+
+	added = kzalloc(sizeof(*added) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+		GFP_KERNEL);
+	removed = kzalloc(sizeof(*removed) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+		GFP_KERNEL);
+
+	if (!added || !removed) {
+		dev_warn(&h->pdev->dev, "out of memory in "
+			"adjust_hpsa_scsi_table\n");
+		goto free_and_out;
+	}
+
+	spin_lock_irqsave(&h->devlock, flags);
+
+	/* find any devices in h->dev[] that are not in
+	 * sd[] and remove them from h->dev[], and for any
+	 * devices which have changed, remove the old device
+	 * info and add the new device info.
+	 */
+	i = 0;
+	nremoved = 0;
+	nadded = 0;
+	while (i < h->ndevices) {
+		csd = h->dev[i];
+		device_change = hpsa_scsi_find_entry(csd, sd, nsds, &entry);
+		if (device_change == DEVICE_NOT_FOUND) {
+			changes++;
+			hpsa_scsi_remove_entry(h, hostno, i,
+				removed, &nremoved);
+			continue; /* remove ^^^, hence i not incremented */
+		} else if (device_change == DEVICE_CHANGED) {
+			changes++;
+			hpsa_scsi_remove_entry(h, hostno, i,
+				removed, &nremoved);
+			(void) hpsa_scsi_add_entry(h, hostno, sd[entry],
+				added, &nadded);
+			/* add can't fail, we just removed one. */
+			sd[entry] = NULL; /* prevent it from being freed */
+		}
+		i++;
+	}
+
+	/* Now, make sure every device listed in sd[] is also
+	 * listed in h->dev[], adding them if they aren't found
+	 */
+
+	for (i = 0; i < nsds; i++) {
+		if (!sd[i]) /* if already added above. */
+			continue;
+		device_change = hpsa_scsi_find_entry(sd[i], h->dev,
+					h->ndevices, &entry);
+		if (device_change == DEVICE_NOT_FOUND) {
+			changes++;
+			if (hpsa_scsi_add_entry(h, hostno, sd[i],
+				added, &nadded) != 0)
+				break;
+			sd[i] = NULL; /* prevent from being freed later. */
+		} else if (device_change == DEVICE_CHANGED) {
+			/* should never happen... */
+			changes++;
+			dev_warn(&h->pdev->dev,
+				"device unexpectedly changed.\n");
+			/* but if it does happen, we just ignore that device */
+		}
+	}
+	spin_unlock_irqrestore(&h->devlock, flags);
+
+	/* Don't notify scsi mid layer of any changes the first time through
+	 * (or if there are no changes) scsi_scan_host will do it later the
+	 * first time through.
+	 */
+	if (hostno == -1 || !changes)
+		goto free_and_out;
+
+	sh = h->scsi_host;
+	/* Notify scsi mid layer of any removed devices */
+	for (i = 0; i < nremoved; i++) {
+		struct scsi_device *sdev =
+			scsi_device_lookup(sh, removed[i]->bus,
+				removed[i]->target, removed[i]->lun);
+		if (sdev != NULL) {
+			scsi_remove_device(sdev);
+			scsi_device_put(sdev);
+		} else {
+			/* We don't expect to get here.
+			 * future cmds to this device will get selection
+			 * timeout as if the device was gone.
+			 */
+			dev_warn(&h->pdev->dev, "didn't find c%db%dt%dl%d "
+				" for removal.", hostno, removed[i]->bus,
+				removed[i]->target, removed[i]->lun);
+		}
+		kfree(removed[i]);
+		removed[i] = NULL;
+	}
+
+	/* Notify scsi mid layer of any added devices */
+	for (i = 0; i < nadded; i++) {
+		if (scsi_add_device(sh, added[i]->bus,
+			added[i]->target, added[i]->lun) == 0)
+			continue;
+		dev_warn(&h->pdev->dev, "scsi_add_device c%db%dt%dl%d failed, "
+			"device not added.\n", hostno, added[i]->bus,
+			added[i]->target, added[i]->lun);
+		/* now we have to remove it from h->dev,
+		 * since it didn't get added to scsi mid layer
+		 */
+		fixup_botched_add(h, added[i]);
+	}
+
+free_and_out:
+	kfree(added);
+	kfree(removed);
+	return 0;
+}
+
+/*
+ * Lookup bus/target/lun and retrun corresponding struct hpsa_scsi_dev_t *
+ * Assume's h->devlock is held.
+ */
+static struct hpsa_scsi_dev_t *lookup_hpsa_scsi_dev(struct ctlr_info *h,
+	int bus, int target, int lun)
+{
+	int i;
+	struct hpsa_scsi_dev_t *sd;
+
+	for (i = 0; i < h->ndevices; i++) {
+		sd = h->dev[i];
+		if (sd->bus == bus && sd->target == target && sd->lun == lun)
+			return sd;
+	}
+	return NULL;
+}
+
+/* link sdev->hostdata to our per-device structure. */
+static int hpsa_slave_alloc(struct scsi_device *sdev)
+{
+	struct hpsa_scsi_dev_t *sd;
+	unsigned long flags;
+	struct ctlr_info *h;
+
+	h = sdev_to_hba(sdev);
+	spin_lock_irqsave(&h->devlock, flags);
+	sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
+		sdev_id(sdev), sdev->lun);
+	if (sd != NULL)
+		sdev->hostdata = sd;
+	spin_unlock_irqrestore(&h->devlock, flags);
+	return 0;
+}
+
+static void hpsa_slave_destroy(struct scsi_device *sdev)
+{
+	return; /* nothing to do. */
+}
+
+static void hpsa_scsi_setup(struct ctlr_info *h)
+{
+	h->ndevices = 0;
+	h->scsi_host = NULL;
+	spin_lock_init(&h->devlock);
+	return;
+}
+
+static void complete_scsi_command(struct CommandList *cp,
+	int timeout, __u32 tag)
+{
+	struct scsi_cmnd *cmd;
+	struct ctlr_info *h;
+	struct ErrorInfo *ei;
+
+	unsigned char sense_key;
+	unsigned char asc;      /* additional sense code */
+	unsigned char ascq;     /* additional sense code qualifier */
+
+	ei = cp->err_info;
+	cmd = (struct scsi_cmnd *) cp->scsi_cmd;
+	h = cp->h;
+
+	scsi_dma_unmap(cmd); /* undo the DMA mappings */
+
+	cmd->result = (DID_OK << 16); 		/* host byte */
+	cmd->result |= (COMMAND_COMPLETE << 8);	/* msg byte */
+	cmd->result |= (ei->ScsiStatus << 1);
+
+	/* copy the sense data whether we need to or not. */
+	memcpy(cmd->sense_buffer, ei->SenseInfo,
+		ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
+			SCSI_SENSE_BUFFERSIZE :
+			ei->SenseLen);
+	scsi_set_resid(cmd, ei->ResidualCnt);
+
+	if (ei->CommandStatus == 0) {
+		cmd->scsi_done(cmd);
+		cmd_free(h, cp);
+		return;
+	}
+
+	/* an error has occurred */
+	switch (ei->CommandStatus) {
+
+	case CMD_TARGET_STATUS:
+		if (ei->ScsiStatus) {
+			/* Get sense key */
+			sense_key = 0xf & ei->SenseInfo[2];
+			/* Get additional sense code */
+			asc = ei->SenseInfo[12];
+			/* Get addition sense code qualifier */
+			ascq = ei->SenseInfo[13];
+		}
+
+		if (ei->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
+			if (check_for_unit_attention(h, cp)) {
+				cmd->result = DID_SOFT_ERROR << 16;
+				break;
+			}
+			if (sense_key == ILLEGAL_REQUEST) {
+				/*
+				 * SCSI REPORT_LUNS is commonly unsupported on
+				 * Smart Array.  Suppress noisy complaint.
+				 */
+				if (cp->Request.CDB[0] == REPORT_LUNS)
+					break;
+
+				/* If ASC/ASCQ indicate Logical Unit
+				 * Not Supported condition,
+				 */
+				if ((asc == 0x25) && (ascq == 0x0)) {
+					dev_warn(&h->pdev->dev, "cp %p "
+						"has check condition\n", cp);
+					break;
+				}
+			}
+
+			if (sense_key == NOT_READY) {
+				/* If Sense is Not Ready, Logical Unit
+				 * Not ready, Manual Intervention
+				 * required
+				 */
+				if ((asc == 0x04) && (ascq == 0x03)) {
+					cmd->result = DID_NO_CONNECT << 16;
+					dev_warn(&h->pdev->dev, "cp %p "
+						"has check condition: unit "
+						"not ready, manual "
+						"intervention required\n", cp);
+					break;
+				}
+			}
+
+
+			/* Must be some other type of check condition */
+			dev_warn(&h->pdev->dev, "cp %p has check condition: "
+					"unknown type: "
+					"Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
+					"Returning result: 0x%x, "
+					"cmd=[%02x %02x %02x %02x %02x "
+					"%02x %02x %02x %02x %02x]\n",
+					cp, sense_key, asc, ascq,
+					cmd->result,
+					cmd->cmnd[0], cmd->cmnd[1],
+					cmd->cmnd[2], cmd->cmnd[3],
+					cmd->cmnd[4], cmd->cmnd[5],
+					cmd->cmnd[6], cmd->cmnd[7],
+					cmd->cmnd[8], cmd->cmnd[9]);
+			break;
+		}
+
+
+		/* Problem was not a check condition
+		 * Pass it up to the upper layers...
+		 */
+		if (ei->ScsiStatus) {
+			dev_warn(&h->pdev->dev, "cp %p has status 0x%x "
+				"Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
+				"Returning result: 0x%x\n",
+				cp, ei->ScsiStatus,
+				sense_key, asc, ascq,
+				cmd->result);
+		} else {  /* scsi status is zero??? How??? */
+			dev_warn(&h->pdev->dev, "cp %p SCSI status was 0. "
+				"Returning no connection.\n", cp),
+
+			/* Ordinarily, this case should never happen,
+			 * but there is a bug in some released firmware
+			 * revisions that allows it to happen if, for
+			 * example, a 4100 backplane loses power and
+			 * the tape drive is in it.  We assume that
+			 * it's a fatal error of some kind because we
+			 * can't show that it wasn't. We will make it
+			 * look like selection timeout since that is
+			 * the most common reason for this to occur,
+			 * and it's severe enough.
+			 */
+
+			cmd->result = DID_NO_CONNECT << 16;
+		}
+		break;
+
+	case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
+		break;
+	case CMD_DATA_OVERRUN:
+		dev_warn(&h->pdev->dev, "cp %p has"
+			" completed with data overrun "
+			"reported\n", cp);
+		break;
+	case CMD_INVALID: {
+		/* print_bytes(cp, sizeof(*cp), 1, 0);
+		print_cmd(cp); */
+		/* We get CMD_INVALID if you address a non-existent device
+		 * instead of a selection timeout (no response).  You will
+		 * see this if you yank out a drive, then try to access it.
+		 * This is kind of a shame because it means that any other
+		 * CMD_INVALID (e.g. driver bug) will get interpreted as a
+		 * missing target. */
+		cmd->result = DID_NO_CONNECT << 16;
+	}
+		break;
+	case CMD_PROTOCOL_ERR:
+		dev_warn(&h->pdev->dev, "cp %p has "
+			"protocol error \n", cp);
+		break;
+	case CMD_HARDWARE_ERR:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "cp %p had  hardware error\n", cp);
+		break;
+	case CMD_CONNECTION_LOST:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "cp %p had connection lost\n", cp);
+		break;
+	case CMD_ABORTED:
+		cmd->result = DID_ABORT << 16;
+		dev_warn(&h->pdev->dev, "cp %p was aborted with status 0x%x\n",
+				cp, ei->ScsiStatus);
+		break;
+	case CMD_ABORT_FAILED:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp);
+		break;
+	case CMD_UNSOLICITED_ABORT:
+		cmd->result = DID_ABORT << 16;
+		dev_warn(&h->pdev->dev, "cp %p aborted do to an unsolicited "
+			"abort\n", cp);
+		break;
+	case CMD_TIMEOUT:
+		cmd->result = DID_TIME_OUT << 16;
+		dev_warn(&h->pdev->dev, "cp %p timedout\n", cp);
+		break;
+	default:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n",
+				cp, ei->CommandStatus);
+	}
+	cmd->scsi_done(cmd);
+	cmd_free(h, cp);
+}
+
+static int hpsa_scsi_detect(struct ctlr_info *h)
+{
+	struct Scsi_Host *sh;
+	int error;
+
+	sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
+	if (sh == NULL)
+		goto fail;
+
+	sh->io_port = 0;
+	sh->n_io_port = 0;
+	sh->this_id = -1;
+	sh->max_channel = 3;
+	sh->max_cmd_len = MAX_COMMAND_SIZE;
+	sh->max_lun = HPSA_MAX_LUN;
+	sh->max_id = HPSA_MAX_LUN;
+	h->scsi_host = sh;
+	sh->hostdata[0] = (unsigned long) h;
+	sh->irq = h->intr[SIMPLE_MODE_INT];
+	sh->unique_id = sh->irq;
+	error = scsi_add_host(sh, &h->pdev->dev);
+	if (error)
+		goto fail_host_put;
+	scsi_scan_host(sh);
+	return 0;
+
+ fail_host_put:
+	dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_add_host"
+		" failed for controller %d\n", h->ctlr);
+	scsi_host_put(sh);
+	return -1;
+ fail:
+	dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_host_alloc"
+		" failed for controller %d\n", h->ctlr);
+	return -1;
+}
+
+static void hpsa_pci_unmap(struct pci_dev *pdev,
+	struct CommandList *c, int sg_used, int data_direction)
+{
+	int i;
+	union u64bit addr64;
+
+	for (i = 0; i < sg_used; i++) {
+		addr64.val32.lower = c->SG[i].Addr.lower;
+		addr64.val32.upper = c->SG[i].Addr.upper;
+		pci_unmap_single(pdev, (dma_addr_t) addr64.val, c->SG[i].Len,
+			data_direction);
+	}
+}
+
+static void hpsa_map_one(struct pci_dev *pdev,
+		struct CommandList *cp,
+		unsigned char *buf,
+		size_t buflen,
+		int data_direction)
+{
+	__u64 addr64;
+
+	if (buflen == 0 || data_direction == PCI_DMA_NONE) {
+		cp->Header.SGList = 0;
+		cp->Header.SGTotal = 0;
+		return;
+	}
+
+	addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
+	cp->SG[0].Addr.lower =
+	  (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+	cp->SG[0].Addr.upper =
+	  (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+	cp->SG[0].Len = buflen;
+	cp->Header.SGList = (__u8) 1;   /* no. SGs contig in this cmd */
+	cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
+}
+
+static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+
+	c->waiting = &wait;
+	enqueue_cmd_and_start_io(h, c);
+	wait_for_completion(&wait);
+}
+
+static void hpsa_scsi_do_simple_cmd_with_retry(struct ctlr_info *h,
+	struct CommandList *c, int data_direction)
+{
+	int retry_count = 0;
+
+	do {
+		memset(c->err_info, 0, sizeof(c->err_info));
+		hpsa_scsi_do_simple_cmd_core(h, c);
+		retry_count++;
+	} while (check_for_unit_attention(h, c) && retry_count <= 3);
+	hpsa_pci_unmap(h->pdev, c, 1, data_direction);
+}
+
+static void hpsa_scsi_interpret_error(struct CommandList *cp)
+{
+	struct ErrorInfo *ei;
+	struct device *d = &cp->h->pdev->dev;
+
+	ei = cp->err_info;
+	switch (ei->CommandStatus) {
+	case CMD_TARGET_STATUS:
+		dev_warn(d, "cmd %p has completed with errors\n", cp);
+		dev_warn(d, "cmd %p has SCSI Status = %x\n", cp,
+				ei->ScsiStatus);
+		if (ei->ScsiStatus == 0)
+			dev_warn(d, "SCSI status is abnormally zero.  "
+			"(probably indicates selection timeout "
+			"reported incorrectly due to a known "
+			"firmware bug, circa July, 2001.)\n");
+		break;
+	case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
+			dev_info(d, "UNDERRUN\n");
+		break;
+	case CMD_DATA_OVERRUN:
+		dev_warn(d, "cp %p has completed with data overrun\n", cp);
+		break;
+	case CMD_INVALID: {
+		/* controller unfortunately reports SCSI passthru's
+		 * to non-existent targets as invalid commands.
+		 */
+		dev_warn(d, "cp %p is reported invalid (probably means "
+			"target device no longer present)\n", cp);
+		/* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0);
+		print_cmd(cp);  */
+		}
+		break;
+	case CMD_PROTOCOL_ERR:
+		dev_warn(d, "cp %p has protocol error \n", cp);
+		break;
+	case CMD_HARDWARE_ERR:
+		/* cmd->result = DID_ERROR << 16; */
+		dev_warn(d, "cp %p had hardware error\n", cp);
+		break;
+	case CMD_CONNECTION_LOST:
+		dev_warn(d, "cp %p had connection lost\n", cp);
+		break;
+	case CMD_ABORTED:
+		dev_warn(d, "cp %p was aborted\n", cp);
+		break;
+	case CMD_ABORT_FAILED:
+		dev_warn(d, "cp %p reports abort failed\n", cp);
+		break;
+	case CMD_UNSOLICITED_ABORT:
+		dev_warn(d, "cp %p aborted due to an unsolicited abort\n", cp);
+		break;
+	case CMD_TIMEOUT:
+		dev_warn(d, "cp %p timed out\n", cp);
+		break;
+	default:
+		dev_warn(d, "cp %p returned unknown status %x\n", cp,
+				ei->CommandStatus);
+	}
+}
+
+static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
+			unsigned char page, unsigned char *buf,
+			unsigned char bufsize)
+{
+	int rc = IO_OK;
+	struct CommandList *c;
+	struct ErrorInfo *ei;
+
+	c = cmd_special_alloc(h);
+
+	if (c == NULL) {			/* trouble... */
+		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		return -1;
+	}
+
+	fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD);
+	hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
+	ei = c->err_info;
+	if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) {
+		hpsa_scsi_interpret_error(c);
+		rc = -1;
+	}
+	cmd_special_free(h, c);
+	return rc;
+}
+
+static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr)
+{
+	int rc = IO_OK;
+	struct CommandList *c;
+	struct ErrorInfo *ei;
+
+	c = cmd_special_alloc(h);
+
+	if (c == NULL) {			/* trouble... */
+		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		return -1;
+	}
+
+	fill_cmd(c, HPSA_DEVICE_RESET_MSG, h, NULL, 0, 0, scsi3addr, TYPE_MSG);
+	hpsa_scsi_do_simple_cmd_core(h, c);
+	/* no unmap needed here because no data xfer. */
+
+	ei = c->err_info;
+	if (ei->CommandStatus != 0) {
+		hpsa_scsi_interpret_error(c);
+		rc = -1;
+	}
+	cmd_special_free(h, c);
+	return rc;
+}
+
+static void hpsa_get_raid_level(struct ctlr_info *h,
+	unsigned char *scsi3addr, unsigned char *raid_level)
+{
+	int rc;
+	unsigned char *buf;
+
+	*raid_level = RAID_UNKNOWN;
+	buf = kzalloc(64, GFP_KERNEL);
+	if (!buf)
+		return;
+	rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0xC1, buf, 64);
+	if (rc == 0)
+		*raid_level = buf[8];
+	if (*raid_level > RAID_UNKNOWN)
+		*raid_level = RAID_UNKNOWN;
+	kfree(buf);
+	return;
+}
+
+/* Get the device id from inquiry page 0x83 */
+static int hpsa_get_device_id(struct ctlr_info *h, unsigned char *scsi3addr,
+	unsigned char *device_id, int buflen)
+{
+	int rc;
+	unsigned char *buf;
+
+	if (buflen > 16)
+		buflen = 16;
+	buf = kzalloc(64, GFP_KERNEL);
+	if (!buf)
+		return -1;
+	rc = hpsa_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
+	if (rc == 0)
+		memcpy(device_id, &buf[8], buflen);
+	kfree(buf);
+	return rc != 0;
+}
+
+static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
+		struct ReportLUNdata *buf, int bufsize,
+		int extended_response)
+{
+	int rc = IO_OK;
+	struct CommandList *c;
+	unsigned char scsi3addr[8];
+	struct ErrorInfo *ei;
+
+	c = cmd_special_alloc(h);
+	if (c == NULL) {			/* trouble... */
+		dev_err(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		return -1;
+	}
+
+	memset(&scsi3addr[0], 0, 8); /* address the controller */
+
+	fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h,
+		buf, bufsize, 0, scsi3addr, TYPE_CMD);
+	if (extended_response)
+		c->Request.CDB[1] = extended_response;
+	hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE);
+	ei = c->err_info;
+	if (ei->CommandStatus != 0 &&
+	    ei->CommandStatus != CMD_DATA_UNDERRUN) {
+		hpsa_scsi_interpret_error(c);
+		rc = -1;
+	}
+	cmd_special_free(h, c);
+	return rc;
+}
+
+static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
+		struct ReportLUNdata *buf,
+		int bufsize, int extended_response)
+{
+	return hpsa_scsi_do_report_luns(h, 0, buf, bufsize, extended_response);
+}
+
+static inline int hpsa_scsi_do_report_log_luns(struct ctlr_info *h,
+		struct ReportLUNdata *buf, int bufsize)
+{
+	return hpsa_scsi_do_report_luns(h, 1, buf, bufsize, 0);
+}
+
+static inline void hpsa_set_bus_target_lun(struct hpsa_scsi_dev_t *device,
+	int bus, int target, int lun)
+{
+	device->bus = bus;
+	device->target = target;
+	device->lun = lun;
+}
+
+static int hpsa_update_device_info(struct ctlr_info *h,
+	unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device)
+{
+#define OBDR_TAPE_INQ_SIZE 49
+	unsigned char *inq_buff = NULL;
+
+	inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
+	if (!inq_buff)
+		goto bail_out;
+
+	memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
+	/* Do an inquiry to the device to see what it is. */
+	if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
+		(unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
+		/* Inquiry failed (msg printed already) */
+		dev_err(&h->pdev->dev,
+			"hpsa_update_device_info: inquiry failed\n");
+		goto bail_out;
+	}
+
+	/* As a side effect, record the firmware version number
+	 * if we happen to be talking to the RAID controller.
+	 */
+	if (is_hba_lunid(scsi3addr))
+		memcpy(h->firm_ver, &inq_buff[32], 4);
+
+	this_device->devtype = (inq_buff[0] & 0x1f);
+	memcpy(this_device->scsi3addr, scsi3addr, 8);
+	memcpy(this_device->vendor, &inq_buff[8],
+		sizeof(this_device->vendor));
+	memcpy(this_device->model, &inq_buff[16],
+		sizeof(this_device->model));
+	memcpy(this_device->revision, &inq_buff[32],
+		sizeof(this_device->revision));
+	memset(this_device->device_id, 0,
+		sizeof(this_device->device_id));
+	hpsa_get_device_id(h, scsi3addr, this_device->device_id,
+		sizeof(this_device->device_id));
+
+	if (this_device->devtype == TYPE_DISK &&
+		is_logical_dev_addr_mode(scsi3addr))
+		hpsa_get_raid_level(h, scsi3addr, &this_device->raid_level);
+	else
+		this_device->raid_level = RAID_UNKNOWN;
+
+	kfree(inq_buff);
+	return 0;
+
+bail_out:
+	kfree(inq_buff);
+	return 1;
+}
+
+static unsigned char *msa2xxx_model[] = {
+	"MSA2012",
+	"MSA2024",
+	"MSA2312",
+	"MSA2324",
+	NULL,
+};
+
+static int is_msa2xxx(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
+{
+	int i;
+
+	for (i = 0; msa2xxx_model[i]; i++)
+		if (strncmp(device->model, msa2xxx_model[i],
+			strlen(msa2xxx_model[i])) == 0)
+			return 1;
+	return 0;
+}
+
+/* Helper function to assign bus, target, lun mapping of devices.
+ * Puts non-msa2xxx logical volumes on bus 0, msa2xxx logical
+ * volumes on bus 1, physical devices on bus 2. and the hba on bus 3.
+ * Logical drive target and lun are assigned at this time, but
+ * physical device lun and target assignment are deferred (assigned
+ * in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
+ */
+static void figure_bus_target_lun(struct ctlr_info *h,
+	__u8 *lunaddrbytes, int *bus, int *target, int *lun,
+	struct hpsa_scsi_dev_t *device)
+{
+
+	__u32 lunid;
+
+	if (is_logical_dev_addr_mode(lunaddrbytes)) {
+		/* logical device */
+		memcpy(&lunid, lunaddrbytes, sizeof(lunid));
+		lunid = le32_to_cpu(lunid);
+
+		if (is_msa2xxx(h, device)) {
+			*bus = 1;
+			*target = (lunid >> 16) & 0x3fff;
+			*lun = lunid & 0x00ff;
+		} else {
+			*bus = 0;
+			*lun = 0;
+			*target = lunid & 0x3fff;
+		}
+	} else {
+		/* physical device */
+		if (is_hba_lunid(lunaddrbytes))
+			*bus = 3;
+		else
+			*bus = 2;
+		*target = -1;
+		*lun = -1; /* we will fill these in later. */
+	}
+}
+
+/*
+ * If there is no lun 0 on a target, linux won't find any devices.
+ * For the MSA2xxx boxes, we have to manually detect the enclosure
+ * which is at lun zero, as CCISS_REPORT_PHYSICAL_LUNS doesn't report
+ * it for some reason.  *tmpdevice is the target we're adding,
+ * this_device is a pointer into the current element of currentsd[]
+ * that we're building up in update_scsi_devices(), below.
+ * lunzerobits is a bitmap that tracks which targets already have a
+ * lun 0 assigned.
+ * Returns 1 if an enclosure was added, 0 if not.
+ */
+static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
+	struct hpsa_scsi_dev_t *tmpdevice,
+	struct hpsa_scsi_dev_t *this_device, __u8 *lunaddrbytes,
+	int bus, int target, int lun, unsigned long lunzerobits[],
+	int *nmsa2xxx_enclosures)
+{
+	unsigned char scsi3addr[8];
+
+	if (test_bit(target, lunzerobits))
+		return 0; /* There is already a lun 0 on this target. */
+
+	if (!is_logical_dev_addr_mode(lunaddrbytes))
+		return 0; /* It's the logical targets that may lack lun 0. */
+
+	if (!is_msa2xxx(h, tmpdevice))
+		return 0; /* It's only the MSA2xxx that have this problem. */
+
+	if (lun == 0) /* if lun is 0, then obviously we have a lun 0. */
+		return 0;
+
+	if (is_hba_lunid(scsi3addr))
+		return 0; /* Don't add the RAID controller here. */
+
+#define MAX_MSA2XXX_ENCLOSURES 32
+	if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) {
+		dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX "
+			"enclosures exceeded.  Check your hardware "
+			"configuration.");
+		return 0;
+	}
+
+	memset(scsi3addr, 0, 8);
+	scsi3addr[3] = target;
+	if (hpsa_update_device_info(h, scsi3addr, this_device))
+		return 0;
+	(*nmsa2xxx_enclosures)++;
+	hpsa_set_bus_target_lun(this_device, bus, target, 0);
+	set_bit(target, lunzerobits);
+	return 1;
+}
+
+/*
+ * Do CISS_REPORT_PHYS and CISS_REPORT_LOG.  Data is returned in physdev,
+ * logdev.  The number of luns in physdev and logdev are returned in
+ * *nphysicals and *nlogicals, respectively.
+ * Returns 0 on success, -1 otherwise.
+ */
+static int hpsa_gather_lun_info(struct ctlr_info *h,
+	int reportlunsize,
+	struct ReportLUNdata *physdev, __u32 *nphysicals,
+	struct ReportLUNdata *logdev, __u32 *nlogicals)
+{
+	if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize, 0)) {
+		dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
+		return -1;
+	}
+	memcpy(nphysicals, &physdev->LUNListLength[0], sizeof(*nphysicals));
+	*nphysicals = be32_to_cpu(*nphysicals) / 8;
+#ifdef DEBUG
+	dev_info(&h->pdev->dev, "number of physical luns is %d\n", *nphysicals);
+#endif
+	if (*nphysicals > HPSA_MAX_PHYS_LUN) {
+		dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded."
+			"  %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
+			*nphysicals - HPSA_MAX_PHYS_LUN);
+		*nphysicals = HPSA_MAX_PHYS_LUN;
+	}
+	if (hpsa_scsi_do_report_log_luns(h, logdev, reportlunsize)) {
+		dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
+		return -1;
+	}
+	memcpy(nlogicals, &logdev->LUNListLength[0], sizeof(*nlogicals));
+	*nlogicals = be32_to_cpu(*nlogicals) / 8;
+#ifdef DEBUG
+	dev_info(&h->pdev->dev, "number of logical luns is %d\n", *nlogicals);
+#endif
+	/* Reject Logicals in excess of our max capability. */
+	if (*nlogicals > HPSA_MAX_LUN) {
+		dev_warn(&h->pdev->dev,
+			"maximum logical LUNs (%d) exceeded.  "
+			"%d LUNs ignored.\n", HPSA_MAX_LUN,
+			*nlogicals - HPSA_MAX_LUN);
+			*nlogicals = HPSA_MAX_LUN;
+	}
+	if (*nlogicals + *nphysicals > HPSA_MAX_PHYS_LUN) {
+		dev_warn(&h->pdev->dev,
+			"maximum logical + physical LUNs (%d) exceeded. "
+			"%d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
+			*nphysicals + *nlogicals - HPSA_MAX_PHYS_LUN);
+		*nlogicals = HPSA_MAX_PHYS_LUN - *nphysicals;
+	}
+	return 0;
+}
+
+static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
+{
+	/* the idea here is we could get notified
+	 * that some devices have changed, so we do a report
+	 * physical luns and report logical luns cmd, and adjust
+	 * our list of devices accordingly.
+	 *
+	 * The scsi3addr's of devices won't change so long as the
+	 * adapter is not reset.  That means we can rescan and
+	 * tell which devices we already know about, vs. new
+	 * devices, vs.  disappearing devices.
+	 */
+	struct ReportLUNdata *physdev_list = NULL;
+	struct ReportLUNdata *logdev_list = NULL;
+	unsigned char *inq_buff = NULL;
+	__u32 nphysicals = 0;
+	__u32 nlogicals = 0;
+	__u32 ndev_allocated = 0;
+	struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
+	int ncurrent = 0;
+	int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8;
+	int i, nmsa2xxx_enclosures, ndevs_to_allocate;
+	int bus, target, lun;
+	DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR);
+
+	currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA,
+		GFP_KERNEL);
+	physdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+	logdev_list = kzalloc(reportlunsize, GFP_KERNEL);
+	inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
+	tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
+
+	if (!currentsd || !physdev_list || !logdev_list ||
+		!inq_buff || !tmpdevice) {
+		dev_err(&h->pdev->dev, "out of memory\n");
+		goto out;
+	}
+	memset(lunzerobits, 0, sizeof(lunzerobits));
+
+	if (hpsa_gather_lun_info(h, reportlunsize, physdev_list, &nphysicals,
+			logdev_list, &nlogicals))
+		goto out;
+
+	/* We might see up to 32 MSA2xxx enclosures, actually 8 of them
+	 * but each of them 4 times through different paths.  The plus 1
+	 * is for the RAID controller.
+	 */
+	ndevs_to_allocate = nphysicals + nlogicals + MAX_MSA2XXX_ENCLOSURES + 1;
+
+	/* Allocate the per device structures */
+	for (i = 0; i < ndevs_to_allocate; i++) {
+		currentsd[i] = kzalloc(sizeof(*currentsd[i]), GFP_KERNEL);
+		if (!currentsd[i]) {
+			dev_warn(&h->pdev->dev, "out of memory at %s:%d\n",
+				__FILE__, __LINE__);
+			goto out;
+		}
+		ndev_allocated++;
+	}
+
+	/* adjust our table of devices */
+	nmsa2xxx_enclosures = 0;
+	for (i = 0; i < nphysicals + nlogicals + 1; i++) {
+		__u8 *lunaddrbytes;
+
+		/* Figure out where the LUN ID info is coming from */
+		if (i < nphysicals)
+			lunaddrbytes = &physdev_list->LUN[i][0];
+		else
+			if (i < nphysicals + nlogicals)
+				lunaddrbytes =
+					&logdev_list->LUN[i-nphysicals][0];
+			else /* jam in the RAID controller at the end */
+				lunaddrbytes = RAID_CTLR_LUNID;
+
+		/* skip masked physical devices. */
+		if (lunaddrbytes[3] & 0xC0 && i < nphysicals)
+			continue;
+
+		/* Get device type, vendor, model, device id */
+		if (hpsa_update_device_info(h, lunaddrbytes, tmpdevice))
+			continue; /* skip it if we can't talk to it. */
+		figure_bus_target_lun(h, lunaddrbytes, &bus, &target, &lun,
+			tmpdevice);
+		this_device = currentsd[ncurrent];
+
+		/*
+		 * For the msa2xxx boxes, we have to insert a LUN 0 which
+		 * doesn't show up in CCISS_REPORT_PHYSICAL data, but there
+		 * is nonetheless an enclosure device there.  We have to
+		 * present that otherwise linux won't find anything if
+		 * there is no lun 0.
+		 */
+		if (add_msa2xxx_enclosure_device(h, tmpdevice, this_device,
+				lunaddrbytes, bus, target, lun, lunzerobits,
+				&nmsa2xxx_enclosures)) {
+			ncurrent++;
+			this_device = currentsd[ncurrent];
+		}
+
+		*this_device = *tmpdevice;
+		hpsa_set_bus_target_lun(this_device, bus, target, lun);
+
+		switch (this_device->devtype) {
+		case TYPE_ROM: {
+			/* We don't *really* support actual CD-ROM devices,
+			 * just "One Button Disaster Recovery" tape drive
+			 * which temporarily pretends to be a CD-ROM drive.
+			 * So we check that the device is really an OBDR tape
+			 * device by checking for "$DR-10" in bytes 43-48 of
+			 * the inquiry data.
+			 */
+				char obdr_sig[7];
+#define OBDR_TAPE_SIG "$DR-10"
+				strncpy(obdr_sig, &inq_buff[43], 6);
+				obdr_sig[6] = '\0';
+				if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+					/* Not OBDR device, ignore it. */
+					break;
+			}
+			ncurrent++;
+			break;
+		case TYPE_DISK:
+			if (i < nphysicals)
+				break;
+			ncurrent++;
+			break;
+		case TYPE_TAPE:
+		case TYPE_MEDIUM_CHANGER:
+			ncurrent++;
+			break;
+		case TYPE_RAID:
+			/* Only present the Smartarray HBA as a RAID controller.
+			 * If it's a RAID controller other than the HBA itself
+			 * (an external RAID controller, MSA500 or similar)
+			 * don't present it.
+			 */
+			if (!is_hba_lunid(lunaddrbytes))
+				break;
+			ncurrent++;
+			break;
+		default:
+			break;
+		}
+		if (ncurrent >= HPSA_MAX_SCSI_DEVS_PER_HBA)
+			break;
+	}
+	adjust_hpsa_scsi_table(h, hostno, currentsd, ncurrent);
+out:
+	kfree(tmpdevice);
+	for (i = 0; i < ndev_allocated; i++)
+		kfree(currentsd[i]);
+	kfree(currentsd);
+	kfree(inq_buff);
+	kfree(physdev_list);
+	kfree(logdev_list);
+	return;
+}
+
+/* hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
+ * dma mapping  and fills in the scatter gather entries of the
+ * hpsa command, cp.
+ */
+static int hpsa_scatter_gather(struct pci_dev *pdev,
+		struct CommandList *cp,
+		struct scsi_cmnd *cmd)
+{
+	unsigned int len;
+	struct scatterlist *sg;
+	__u64 addr64;
+	int use_sg, i;
+
+	BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
+
+	use_sg = scsi_dma_map(cmd);
+	if (use_sg < 0)
+		return use_sg;
+
+	if (!use_sg)
+		goto sglist_finished;
+
+	scsi_for_each_sg(cmd, sg, use_sg, i) {
+		addr64 = (__u64) sg_dma_address(sg);
+		len  = sg_dma_len(sg);
+		cp->SG[i].Addr.lower =
+			(__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+		cp->SG[i].Addr.upper =
+			(__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+		cp->SG[i].Len = len;
+		cp->SG[i].Ext = 0;  /* we are not chaining */
+	}
+
+sglist_finished:
+
+	cp->Header.SGList = (__u8) use_sg;   /* no. SGs contig in this cmd */
+	cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
+	return 0;
+}
+
+
+static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
+	void (*done)(struct scsi_cmnd *))
+{
+	struct ctlr_info *h;
+	struct hpsa_scsi_dev_t *dev;
+	unsigned char scsi3addr[8];
+	struct CommandList *c;
+	unsigned long flags;
+
+	/* Get the ptr to our adapter structure out of cmd->host. */
+	h = sdev_to_hba(cmd->device);
+	dev = cmd->device->hostdata;
+	if (!dev) {
+		cmd->result = DID_NO_CONNECT << 16;
+		done(cmd);
+		return 0;
+	}
+	memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr));
+
+	/* Need a lock as this is being allocated from the pool */
+	spin_lock_irqsave(&h->lock, flags);
+	c = cmd_alloc(h);
+	spin_unlock_irqrestore(&h->lock, flags);
+	if (c == NULL) {			/* trouble... */
+		dev_err(&h->pdev->dev, "cmd_alloc returned NULL!\n");
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* Fill in the command list header */
+
+	cmd->scsi_done = done;    /* save this for use by completion code */
+
+	/* save c in case we have to abort it  */
+	cmd->host_scribble = (unsigned char *) c;
+
+	c->cmd_type = CMD_SCSI;
+	c->scsi_cmd = cmd;
+	c->Header.ReplyQueue = 0;  /* unused in simple mode */
+	memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
+	c->Header.Tag.lower = c->busaddr;  /* Use k. address of cmd as tag */
+
+	/* Fill in the request block... */
+
+	c->Request.Timeout = 0;
+	memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
+	BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
+	c->Request.CDBLen = cmd->cmd_len;
+	memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
+	c->Request.Type.Type = TYPE_CMD;
+	c->Request.Type.Attribute = ATTR_SIMPLE;
+	switch (cmd->sc_data_direction) {
+	case DMA_TO_DEVICE:
+		c->Request.Type.Direction = XFER_WRITE;
+		break;
+	case DMA_FROM_DEVICE:
+		c->Request.Type.Direction = XFER_READ;
+		break;
+	case DMA_NONE:
+		c->Request.Type.Direction = XFER_NONE;
+		break;
+	case DMA_BIDIRECTIONAL:
+		/* This can happen if a buggy application does a scsi passthru
+		 * and sets both inlen and outlen to non-zero. ( see
+		 * ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
+		 */
+
+		c->Request.Type.Direction = XFER_RSVD;
+		/* This is technically wrong, and hpsa controllers should
+		 * reject it with CMD_INVALID, which is the most correct
+		 * response, but non-fibre backends appear to let it
+		 * slide by, and give the same results as if this field
+		 * were set correctly.  Either way is acceptable for
+		 * our purposes here.
+		 */
+
+		break;
+
+	default:
+		dev_err(&h->pdev->dev, "unknown data direction: %d\n",
+			cmd->sc_data_direction);
+		BUG();
+		break;
+	}
+
+	if (hpsa_scatter_gather(h->pdev, c, cmd) < 0) { /* Fill SG list */
+		cmd_free(h, c);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+	enqueue_cmd_and_start_io(h, c);
+	/* the cmd'll come back via intr handler in complete_scsi_command()  */
+	return 0;
+}
+
+static void hpsa_unregister_scsi(struct ctlr_info *h)
+{
+	/* we are being forcibly unloaded, and may not refuse. */
+	scsi_remove_host(h->scsi_host);
+	scsi_host_put(h->scsi_host);
+	h->scsi_host = NULL;
+}
+
+static int hpsa_register_scsi(struct ctlr_info *h)
+{
+	int rc;
+
+	hpsa_update_scsi_devices(h, -1);
+	rc = hpsa_scsi_detect(h);
+	if (rc != 0)
+		dev_err(&h->pdev->dev, "hpsa_register_scsi: failed"
+			" hpsa_scsi_detect(), rc is %d\n", rc);
+	return rc;
+}
+
+static int wait_for_device_to_become_ready(struct ctlr_info *h,
+	unsigned char lunaddr[])
+{
+	int rc = 0;
+	int count = 0;
+	int waittime = 1; /* seconds */
+	struct CommandList *c;
+
+	c = cmd_special_alloc(h);
+	if (!c) {
+		dev_warn(&h->pdev->dev, "out of memory in "
+			"wait_for_device_to_become_ready.\n");
+		return IO_ERROR;
+	}
+
+	/* Send test unit ready until device ready, or give up. */
+	while (count < HPSA_TUR_RETRY_LIMIT) {
+
+		/* Wait for a bit.  do this first, because if we send
+		 * the TUR right away, the reset will just abort it.
+		 */
+		msleep(1000 * waittime);
+		count++;
+
+		/* Increase wait time with each try, up to a point. */
+		if (waittime < HPSA_MAX_WAIT_INTERVAL_SECS)
+			waittime = waittime * 2;
+
+		/* Send the Test Unit Ready */
+		fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, lunaddr, TYPE_CMD);
+		hpsa_scsi_do_simple_cmd_core(h, c);
+		/* no unmap needed here because no data xfer. */
+
+		if (c->err_info->CommandStatus == CMD_SUCCESS)
+			break;
+
+		if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+			c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION &&
+			(c->err_info->SenseInfo[2] == NO_SENSE ||
+			c->err_info->SenseInfo[2] == UNIT_ATTENTION))
+			break;
+
+		dev_warn(&h->pdev->dev, "waiting %d secs "
+			"for device to become ready.\n", waittime);
+		rc = 1; /* device not ready. */
+	}
+
+	if (rc)
+		dev_warn(&h->pdev->dev, "giving up on device.\n");
+	else
+		dev_warn(&h->pdev->dev, "device is ready.\n");
+
+	cmd_special_free(h, c);
+	return rc;
+}
+
+/* Need at least one of these error handlers to keep ../scsi/hosts.c from
+ * complaining.  Doing a host- or bus-reset can't do anything good here.
+ */
+static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
+{
+	int rc;
+	struct ctlr_info *h;
+	struct hpsa_scsi_dev_t *dev;
+
+	/* find the controller to which the command to be aborted was sent */
+	h = sdev_to_hba(scsicmd->device);
+	if (h == NULL) /* paranoia */
+		return FAILED;
+	dev_warn(&h->pdev->dev, "resetting drive\n");
+
+	dev = scsicmd->device->hostdata;
+	if (!dev) {
+		dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: "
+			"device lookup failed.\n");
+		return FAILED;
+	}
+	/* send a reset to the SCSI LUN which the command was sent to */
+	rc = hpsa_send_reset(h, dev->scsi3addr);
+	if (rc == 0 && wait_for_device_to_become_ready(h, dev->scsi3addr) == 0)
+		return SUCCESS;
+
+	dev_warn(&h->pdev->dev, "resetting device failed.\n");
+	return FAILED;
+}
+
+/*
+ * For operations that cannot sleep, a command block is allocated at init,
+ * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
+ * which ones are free or in use.  Lock must be held when calling this.
+ * cmd_free() is the complement.
+ */
+static struct CommandList *cmd_alloc(struct ctlr_info *h)
+{
+	struct CommandList *c;
+	int i;
+	union u64bit temp64;
+	dma_addr_t cmd_dma_handle, err_dma_handle;
+
+	do {
+		i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
+		if (i == h->nr_cmds)
+			return NULL;
+	} while (test_and_set_bit
+		 (i & (BITS_PER_LONG - 1),
+		  h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
+	c = h->cmd_pool + i;
+	memset(c, 0, sizeof(*c));
+	cmd_dma_handle = h->cmd_pool_dhandle
+	    + i * sizeof(*c);
+	c->err_info = h->errinfo_pool + i;
+	memset(c->err_info, 0, sizeof(*c->err_info));
+	err_dma_handle = h->errinfo_pool_dhandle
+	    + i * sizeof(*c->err_info);
+	h->nr_allocs++;
+
+	c->cmdindex = i;
+
+	INIT_HLIST_NODE(&c->list);
+	c->busaddr = (__u32) cmd_dma_handle;
+	temp64.val = (__u64) err_dma_handle;
+	c->ErrDesc.Addr.lower = temp64.val32.lower;
+	c->ErrDesc.Addr.upper = temp64.val32.upper;
+	c->ErrDesc.Len = sizeof(*c->err_info);
+
+	c->h = h;
+	return c;
+}
+
+/* For operations that can wait for kmalloc to possibly sleep,
+ * this routine can be called. Lock need not be held to call
+ * cmd_special_alloc. cmd_special_free() is the complement.
+ */
+static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
+{
+	struct CommandList *c;
+	union u64bit temp64;
+	dma_addr_t cmd_dma_handle, err_dma_handle;
+
+	c = pci_alloc_consistent(h->pdev, sizeof(*c), &cmd_dma_handle);
+	if (c == NULL)
+		return NULL;
+	memset(c, 0, sizeof(*c));
+
+	c->cmdindex = -1;
+
+	c->err_info = pci_alloc_consistent(h->pdev, sizeof(*c->err_info),
+		    &err_dma_handle);
+
+	if (c->err_info == NULL) {
+		pci_free_consistent(h->pdev,
+			sizeof(*c), c, cmd_dma_handle);
+		return NULL;
+	}
+	memset(c->err_info, 0, sizeof(*c->err_info));
+
+	INIT_HLIST_NODE(&c->list);
+	c->busaddr = (__u32) cmd_dma_handle;
+	temp64.val = (__u64) err_dma_handle;
+	c->ErrDesc.Addr.lower = temp64.val32.lower;
+	c->ErrDesc.Addr.upper = temp64.val32.upper;
+	c->ErrDesc.Len = sizeof(*c->err_info);
+
+	c->h = h;
+	return c;
+}
+
+static void cmd_free(struct ctlr_info *h, struct CommandList *c)
+{
+	int i;
+
+	i = c - h->cmd_pool;
+	clear_bit(i & (BITS_PER_LONG - 1),
+		  h->cmd_pool_bits + (i / BITS_PER_LONG));
+	h->nr_frees++;
+}
+
+static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
+{
+	union u64bit temp64;
+
+	temp64.val32.lower = c->ErrDesc.Addr.lower;
+	temp64.val32.upper = c->ErrDesc.Addr.upper;
+	pci_free_consistent(h->pdev, sizeof(*c->err_info),
+			    c->err_info, (dma_addr_t) temp64.val);
+	pci_free_consistent(h->pdev, sizeof(*c),
+			    c, (dma_addr_t) c->busaddr);
+}
+
+#ifdef CONFIG_COMPAT
+
+static int do_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = hpsa_ioctl(dev, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg);
+static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
+	int cmd, void *arg);
+
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+	switch (cmd) {
+	case CCISS_GETPCIINFO:
+	case CCISS_GETINTINFO:
+	case CCISS_SETINTINFO:
+	case CCISS_GETNODENAME:
+	case CCISS_SETNODENAME:
+	case CCISS_GETHEARTBEAT:
+	case CCISS_GETBUSTYPES:
+	case CCISS_GETFIRMVER:
+	case CCISS_GETDRIVVER:
+	case CCISS_REVALIDVOLS:
+	case CCISS_DEREGDISK:
+	case CCISS_REGNEWDISK:
+	case CCISS_REGNEWD:
+	case CCISS_RESCANDISK:
+	case CCISS_GETLUNINFO:
+		return do_ioctl(dev, cmd, arg);
+
+	case CCISS_PASSTHRU32:
+		return hpsa_ioctl32_passthru(dev, cmd, arg);
+	case CCISS_BIG_PASSTHRU32:
+		return hpsa_ioctl32_big_passthru(dev, cmd, arg);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
+{
+	IOCTL32_Command_struct __user *arg32 =
+	    (IOCTL32_Command_struct __user *) arg;
+	IOCTL_Command_struct arg64;
+	IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
+	int err;
+	u32 cp;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+			   sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request,
+			   sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info,
+			   sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(cp, &arg32->buf);
+	arg64.buf = compat_ptr(cp);
+	err |= copy_to_user(p, &arg64, sizeof(arg64));
+
+	if (err)
+		return -EFAULT;
+
+	err = do_ioctl(dev, CCISS_PASSTHRU, (void *)p);
+	if (err)
+		return err;
+	err |= copy_in_user(&arg32->error_info, &p->error_info,
+			 sizeof(arg32->error_info));
+	if (err)
+		return -EFAULT;
+	return err;
+}
+
+static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
+	int cmd, void *arg)
+{
+	BIG_IOCTL32_Command_struct __user *arg32 =
+	    (BIG_IOCTL32_Command_struct __user *) arg;
+	BIG_IOCTL_Command_struct arg64;
+	BIG_IOCTL_Command_struct __user *p =
+	    compat_alloc_user_space(sizeof(arg64));
+	int err;
+	u32 cp;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+			   sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request,
+			   sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info,
+			   sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.malloc_size, &arg32->malloc_size);
+	err |= get_user(cp, &arg32->buf);
+	arg64.buf = compat_ptr(cp);
+	err |= copy_to_user(p, &arg64, sizeof(arg64));
+
+	if (err)
+		return -EFAULT;
+
+	err = do_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
+	if (err)
+		return err;
+	err |= copy_in_user(&arg32->error_info, &p->error_info,
+			 sizeof(arg32->error_info));
+	if (err)
+		return -EFAULT;
+	return err;
+}
+#endif
+
+static int hpsa_getpciinfo_ioctl(struct ctlr_info *h, void __user *argp)
+{
+	struct hpsa_pci_info pciinfo;
+
+	if (!argp)
+		return -EINVAL;
+	pciinfo.domain = pci_domain_nr(h->pdev->bus);
+	pciinfo.bus = h->pdev->bus->number;
+	pciinfo.dev_fn = h->pdev->devfn;
+	pciinfo.board_id = h->board_id;
+	if (copy_to_user(argp, &pciinfo, sizeof(pciinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int hpsa_getdrivver_ioctl(struct ctlr_info *h, void __user *argp)
+{
+	DriverVer_type DriverVer;
+	unsigned char vmaj, vmin, vsubmin;
+	int rc;
+
+	rc = sscanf(HPSA_DRIVER_VERSION, "%hhu.%hhu.%hhu",
+		&vmaj, &vmin, &vsubmin);
+	if (rc != 3) {
+		dev_info(&h->pdev->dev, "driver version string '%s' "
+			"unrecognized.", HPSA_DRIVER_VERSION);
+		vmaj = 0;
+		vmin = 0;
+		vsubmin = 0;
+	}
+	DriverVer = (vmaj << 16) | (vmin << 8) | vsubmin;
+	if (!argp)
+		return -EINVAL;
+	if (copy_to_user(argp, &DriverVer, sizeof(DriverVer_type)))
+		return -EFAULT;
+	return 0;
+}
+
+static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+{
+	IOCTL_Command_struct iocommand;
+	struct CommandList *c;
+	char *buff = NULL;
+	union u64bit temp64;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+	if (copy_from_user(&iocommand, argp, sizeof(iocommand)))
+		return -EFAULT;
+	if ((iocommand.buf_size < 1) &&
+	    (iocommand.Request.Type.Direction != XFER_NONE)) {
+		return -EINVAL;
+	}
+	if (iocommand.buf_size > 0) {
+		buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+		if (buff == NULL)
+			return -EFAULT;
+	}
+	if (iocommand.Request.Type.Direction == XFER_WRITE) {
+		/* Copy the data into the buffer we created */
+		if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
+			kfree(buff);
+			return -EFAULT;
+		}
+	} else
+		memset(buff, 0, iocommand.buf_size);
+	c = cmd_special_alloc(h);
+	if (c == NULL) {
+		kfree(buff);
+		return -ENOMEM;
+	}
+	/* Fill in the command type */
+	c->cmd_type = CMD_IOCTL_PEND;
+	/* Fill in Command Header */
+	c->Header.ReplyQueue = 0; /* unused in simple mode */
+	if (iocommand.buf_size > 0) {	/* buffer to fill */
+		c->Header.SGList = 1;
+		c->Header.SGTotal = 1;
+	} else	{ /* no buffers to fill */
+		c->Header.SGList = 0;
+		c->Header.SGTotal = 0;
+	}
+	memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN));
+	/* use the kernel address the cmd block for tag */
+	c->Header.Tag.lower = c->busaddr;
+
+	/* Fill in Request block */
+	memcpy(&c->Request, &iocommand.Request,
+		sizeof(c->Request));
+
+	/* Fill in the scatter gather information */
+	if (iocommand.buf_size > 0) {
+		temp64.val = pci_map_single(h->pdev, buff,
+			iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+		c->SG[0].Addr.lower = temp64.val32.lower;
+		c->SG[0].Addr.upper = temp64.val32.upper;
+		c->SG[0].Len = iocommand.buf_size;
+		c->SG[0].Ext = 0; /* we are not chaining*/
+	}
+	hpsa_scsi_do_simple_cmd_core(h, c);
+	hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
+	check_ioctl_unit_attention(h, c);
+
+	/* Copy the error information out */
+	memcpy(&iocommand.error_info, c->err_info,
+		sizeof(iocommand.error_info));
+	if (copy_to_user(argp, &iocommand, sizeof(iocommand))) {
+		kfree(buff);
+		cmd_special_free(h, c);
+		return -EFAULT;
+	}
+
+	if (iocommand.Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
+			kfree(buff);
+			cmd_special_free(h, c);
+			return -EFAULT;
+		}
+	}
+	kfree(buff);
+	cmd_special_free(h, c);
+	return 0;
+}
+
+static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
+{
+	BIG_IOCTL_Command_struct *ioc;
+	struct CommandList *c;
+	unsigned char **buff = NULL;
+	int *buff_size = NULL;
+	union u64bit temp64;
+	BYTE sg_used = 0;
+	int status = 0;
+	int i;
+	__u32 left;
+	__u32 sz;
+	BYTE __user *data_ptr;
+
+	if (!argp)
+		return -EINVAL;
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+	ioc = (BIG_IOCTL_Command_struct *)
+	    kmalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if ((ioc->buf_size < 1) &&
+	    (ioc->Request.Type.Direction != XFER_NONE)) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	/* Check kmalloc limits  using all SGs */
+	if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+		status = -EINVAL;
+		goto cleanup1;
+	}
+	buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+	if (!buff) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	buff_size = kmalloc(MAXSGENTRIES * sizeof(int), GFP_KERNEL);
+	if (!buff_size) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	left = ioc->buf_size;
+	data_ptr = ioc->buf;
+	while (left) {
+		sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
+		buff_size[sg_used] = sz;
+		buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+		if (buff[sg_used] == NULL) {
+			status = -ENOMEM;
+			goto cleanup1;
+		}
+		if (ioc->Request.Type.Direction == XFER_WRITE) {
+			if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+				status = -ENOMEM;
+				goto cleanup1;
+			}
+		} else
+			memset(buff[sg_used], 0, sz);
+		left -= sz;
+		data_ptr += sz;
+		sg_used++;
+	}
+	c = cmd_special_alloc(h);
+	if (c == NULL) {
+		status = -ENOMEM;
+		goto cleanup1;
+	}
+	c->cmd_type = CMD_IOCTL_PEND;
+	c->Header.ReplyQueue = 0;
+
+	if (ioc->buf_size > 0) {
+		c->Header.SGList = sg_used;
+		c->Header.SGTotal = sg_used;
+	} else {
+		c->Header.SGList = 0;
+		c->Header.SGTotal = 0;
+	}
+	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
+	c->Header.Tag.lower = c->busaddr;
+	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
+	if (ioc->buf_size > 0) {
+		int i;
+		for (i = 0; i < sg_used; i++) {
+			temp64.val = pci_map_single(h->pdev, buff[i],
+				    buff_size[i], PCI_DMA_BIDIRECTIONAL);
+			c->SG[i].Addr.lower = temp64.val32.lower;
+			c->SG[i].Addr.upper = temp64.val32.upper;
+			c->SG[i].Len = buff_size[i];
+			/* we are not chaining */
+			c->SG[i].Ext = 0;
+		}
+	}
+	hpsa_scsi_do_simple_cmd_core(h, c);
+	hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
+	check_ioctl_unit_attention(h, c);
+	/* Copy the error information out */
+	memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
+	if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+		cmd_special_free(h, c);
+		status = -EFAULT;
+		goto cleanup1;
+	}
+	if (ioc->Request.Type.Direction == XFER_READ) {
+		/* Copy the data out of the buffer we created */
+		BYTE __user *ptr = ioc->buf;
+		for (i = 0; i < sg_used; i++) {
+			if (copy_to_user(ptr, buff[i], buff_size[i])) {
+				cmd_special_free(h, c);
+				status = -EFAULT;
+				goto cleanup1;
+			}
+			ptr += buff_size[i];
+		}
+	}
+	cmd_special_free(h, c);
+	status = 0;
+cleanup1:
+	if (buff) {
+		for (i = 0; i < sg_used; i++)
+			kfree(buff[i]);
+		kfree(buff);
+	}
+	kfree(buff_size);
+	kfree(ioc);
+	return status;
+}
+
+static void check_ioctl_unit_attention(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
+			c->err_info->ScsiStatus != SAM_STAT_CHECK_CONDITION)
+		(void) check_for_unit_attention(h, c);
+}
+/*
+ * ioctl
+ */
+static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+	struct ctlr_info *h;
+	void __user *argp = (void __user *)arg;
+
+	h = sdev_to_hba(dev);
+
+	switch (cmd) {
+	case CCISS_DEREGDISK:
+	case CCISS_REGNEWDISK:
+	case CCISS_REGNEWD:
+		hpsa_update_scsi_devices(h, dev->host->host_no);
+		return 0;
+	case CCISS_GETPCIINFO:
+		return hpsa_getpciinfo_ioctl(h, argp);
+	case CCISS_GETDRIVVER:
+		return hpsa_getdrivver_ioctl(h, argp);
+	case CCISS_PASSTHRU:
+		return hpsa_passthru_ioctl(h, argp);
+	case CCISS_BIG_PASSTHRU:
+		return hpsa_big_passthru_ioctl(h, argp);
+	default:
+		return -ENOTTY;
+	}
+}
+
+static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
+	void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+	int cmd_type)
+{
+	int pci_dir = XFER_NONE;
+
+	c->cmd_type = CMD_IOCTL_PEND;
+	c->Header.ReplyQueue = 0;
+	if (buff != NULL && size > 0) {
+		c->Header.SGList = 1;
+		c->Header.SGTotal = 1;
+	} else {
+		c->Header.SGList = 0;
+		c->Header.SGTotal = 0;
+	}
+	c->Header.Tag.lower = c->busaddr;
+	memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8);
+
+	c->Request.Type.Type = cmd_type;
+	if (cmd_type == TYPE_CMD) {
+		switch (cmd) {
+		case HPSA_INQUIRY:
+			/* are we trying to read a vital product page */
+			if (page_code != 0) {
+				c->Request.CDB[1] = 0x01;
+				c->Request.CDB[2] = page_code;
+			}
+			c->Request.CDBLen = 6;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_READ;
+			c->Request.Timeout = 0;
+			c->Request.CDB[0] = HPSA_INQUIRY;
+			c->Request.CDB[4] = size & 0xFF;
+			break;
+		case HPSA_REPORT_LOG:
+		case HPSA_REPORT_PHYS:
+			/* Talking to controller so It's a physical command
+			   mode = 00 target = 0.  Nothing to write.
+			 */
+			c->Request.CDBLen = 12;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_READ;
+			c->Request.Timeout = 0;
+			c->Request.CDB[0] = cmd;
+			c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */
+			c->Request.CDB[7] = (size >> 16) & 0xFF;
+			c->Request.CDB[8] = (size >> 8) & 0xFF;
+			c->Request.CDB[9] = size & 0xFF;
+			break;
+
+		case HPSA_READ_CAPACITY:
+			c->Request.CDBLen = 10;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_READ;
+			c->Request.Timeout = 0;
+			c->Request.CDB[0] = cmd;
+			break;
+		case HPSA_CACHE_FLUSH:
+			c->Request.CDBLen = 12;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_WRITE;
+			c->Request.Timeout = 0;
+			c->Request.CDB[0] = BMIC_WRITE;
+			c->Request.CDB[6] = BMIC_CACHE_FLUSH;
+			break;
+		case TEST_UNIT_READY:
+			c->Request.CDBLen = 6;
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_NONE;
+			c->Request.Timeout = 0;
+			break;
+		default:
+			dev_warn(&h->pdev->dev, "unknown command 0x%c\n", cmd);
+			BUG();
+			return;
+		}
+	} else if (cmd_type == TYPE_MSG) {
+		switch (cmd) {
+
+		case  HPSA_DEVICE_RESET_MSG:
+			c->Request.CDBLen = 16;
+			c->Request.Type.Type =  1; /* It is a MSG not a CMD */
+			c->Request.Type.Attribute = ATTR_SIMPLE;
+			c->Request.Type.Direction = XFER_NONE;
+			c->Request.Timeout = 0; /* Don't time out */
+			c->Request.CDB[0] =  0x01; /* RESET_MSG is 0x01 */
+			c->Request.CDB[1] = 0x03;  /* Reset target above */
+			/* If bytes 4-7 are zero, it means reset the */
+			/* LunID device */
+			c->Request.CDB[4] = 0x00;
+			c->Request.CDB[5] = 0x00;
+			c->Request.CDB[6] = 0x00;
+			c->Request.CDB[7] = 0x00;
+		break;
+
+		default:
+			dev_warn(&h->pdev->dev, "unknown message type %d\n",
+				cmd);
+			BUG();
+		}
+	} else {
+		dev_warn(&h->pdev->dev, "unknown command type %d\n", cmd_type);
+		BUG();
+	}
+
+	switch (c->Request.Type.Direction) {
+	case XFER_READ:
+		pci_dir = PCI_DMA_FROMDEVICE;
+		break;
+	case XFER_WRITE:
+		pci_dir = PCI_DMA_TODEVICE;
+		break;
+	case XFER_NONE:
+		pci_dir = PCI_DMA_NONE;
+		break;
+	default:
+		pci_dir = PCI_DMA_BIDIRECTIONAL;
+	}
+
+	hpsa_map_one(h->pdev, c, buff, size, pci_dir);
+
+	return;
+}
+
+/*
+ * Map (physical) PCI mem into (virtual) kernel space
+ */
+static void __iomem *remap_pci_mem(ulong base, ulong size)
+{
+	ulong page_base = ((ulong) base) & PAGE_MASK;
+	ulong page_offs = ((ulong) base) - page_base;
+	void __iomem *page_remapped = ioremap(page_base, page_offs + size);
+
+	return page_remapped ? (page_remapped + page_offs) : NULL;
+}
+
+/* Takes cmds off the submission queue and sends them to the hardware,
+ * then puts them on the queue of cmds waiting for completion.
+ */
+static void start_io(struct ctlr_info *h)
+{
+	struct CommandList *c;
+
+	while (!hlist_empty(&h->reqQ)) {
+		c = hlist_entry(h->reqQ.first, struct CommandList, list);
+		/* can't do anything if fifo is full */
+		if ((h->access.fifo_full(h))) {
+			dev_warn(&h->pdev->dev, "fifo full\n");
+			break;
+		}
+
+		/* Get the first entry from the Request Q */
+		removeQ(c);
+		h->Qdepth--;
+
+		/* Tell the controller execute command */
+		h->access.submit_command(h, c);
+
+		/* Put job onto the completed Q */
+		addQ(&h->cmpQ, c);
+	}
+}
+
+static inline unsigned long get_next_completion(struct ctlr_info *h)
+{
+	return h->access.command_completed(h);
+}
+
+static inline int interrupt_pending(struct ctlr_info *h)
+{
+	return h->access.intr_pending(h);
+}
+
+static inline long interrupt_not_for_us(struct ctlr_info *h)
+{
+	return ((h->access.intr_pending(h) == 0) ||
+		 (h->interrupts_enabled == 0));
+}
+
+static inline int bad_tag(struct ctlr_info *h, __u32 tag_index,
+	__u32 raw_tag)
+{
+	if (unlikely(tag_index >= h->nr_cmds)) {
+		dev_warn(&h->pdev->dev, "bad tag 0x%08x ignored.\n", raw_tag);
+		return 1;
+	}
+	return 0;
+}
+
+static inline void finish_cmd(struct CommandList *c, __u32 raw_tag)
+{
+	removeQ(c);
+	if (likely(c->cmd_type == CMD_SCSI))
+		complete_scsi_command(c, 0, raw_tag);
+	else if (c->cmd_type == CMD_IOCTL_PEND)
+		complete(c->waiting);
+}
+
+static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
+{
+	struct ctlr_info *h = dev_id;
+	struct CommandList *c;
+	unsigned long flags;
+	__u32 raw_tag, tag, tag_index;
+	struct hlist_node *tmp;
+
+	if (interrupt_not_for_us(h))
+		return IRQ_NONE;
+	spin_lock_irqsave(&h->lock, flags);
+	while (interrupt_pending(h)) {
+		while ((raw_tag = get_next_completion(h)) != FIFO_EMPTY) {
+			if (likely(HPSA_TAG_CONTAINS_INDEX(raw_tag))) {
+				tag_index = HPSA_TAG_TO_INDEX(raw_tag);
+				if (bad_tag(h, tag_index, raw_tag))
+					return IRQ_HANDLED;
+				c = h->cmd_pool + tag_index;
+				finish_cmd(c, raw_tag);
+				continue;
+			}
+			tag = HPSA_TAG_DISCARD_ERROR_BITS(raw_tag);
+			c = NULL;
+			hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+				if (c->busaddr == tag) {
+					finish_cmd(c, raw_tag);
+					break;
+				}
+			}
+		}
+	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	return IRQ_HANDLED;
+}
+
+/* Send a message CDB to the firmware. */
+static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
+						unsigned char type)
+{
+	struct Command {
+		struct CommandListHeader CommandHeader;
+		struct RequestBlock Request;
+		struct ErrDescriptor ErrorDescriptor;
+	};
+	struct Command *cmd;
+	static const size_t cmd_sz = sizeof(*cmd) +
+					sizeof(cmd->ErrorDescriptor);
+	dma_addr_t paddr64;
+	uint32_t paddr32, tag;
+	void __iomem *vaddr;
+	int i, err;
+
+	vaddr = pci_ioremap_bar(pdev, 0);
+	if (vaddr == NULL)
+		return -ENOMEM;
+
+	/* The Inbound Post Queue only accepts 32-bit physical addresses for the
+	 * CCISS commands, so they must be allocated from the lower 4GiB of
+	 * memory.
+	 */
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		iounmap(vaddr);
+		return -ENOMEM;
+	}
+
+	cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);
+	if (cmd == NULL) {
+		iounmap(vaddr);
+		return -ENOMEM;
+	}
+
+	/* This must fit, because of the 32-bit consistent DMA mask.  Also,
+	 * although there's no guarantee, we assume that the address is at
+	 * least 4-byte aligned (most likely, it's page-aligned).
+	 */
+	paddr32 = paddr64;
+
+	cmd->CommandHeader.ReplyQueue = 0;
+	cmd->CommandHeader.SGList = 0;
+	cmd->CommandHeader.SGTotal = 0;
+	cmd->CommandHeader.Tag.lower = paddr32;
+	cmd->CommandHeader.Tag.upper = 0;
+	memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
+
+	cmd->Request.CDBLen = 16;
+	cmd->Request.Type.Type = TYPE_MSG;
+	cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
+	cmd->Request.Type.Direction = XFER_NONE;
+	cmd->Request.Timeout = 0; /* Don't time out */
+	cmd->Request.CDB[0] = opcode;
+	cmd->Request.CDB[1] = type;
+	memset(&cmd->Request.CDB[2], 0, 14); /* rest of the CDB is reserved */
+	cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(*cmd);
+	cmd->ErrorDescriptor.Addr.upper = 0;
+	cmd->ErrorDescriptor.Len = sizeof(struct ErrorInfo);
+
+	writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
+
+	for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
+		tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
+		if (HPSA_TAG_DISCARD_ERROR_BITS(tag) == paddr32)
+			break;
+		msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
+	}
+
+	iounmap(vaddr);
+
+	/* we leak the DMA buffer here ... no choice since the controller could
+	 *  still complete the command.
+	 */
+	if (i == HPSA_MSG_SEND_RETRY_LIMIT) {
+		dev_err(&pdev->dev, "controller message %02x:%02x timed out\n",
+			opcode, type);
+		return -ETIMEDOUT;
+	}
+
+	pci_free_consistent(pdev, cmd_sz, cmd, paddr64);
+
+	if (tag & HPSA_ERROR_BIT) {
+		dev_err(&pdev->dev, "controller message %02x:%02x failed\n",
+			opcode, type);
+		return -EIO;
+	}
+
+	dev_info(&pdev->dev, "controller message %02x:%02x succeeded\n",
+		opcode, type);
+	return 0;
+}
+
+#define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
+#define hpsa_noop(p) hpsa_message(p, 3, 0)
+
+static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
+{
+/* the #defines are stolen from drivers/pci/msi.h. */
+#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
+
+	int pos;
+	u16 control = 0;
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+	if (pos) {
+		pci_read_config_word(pdev, msi_control_reg(pos), &control);
+		if (control & PCI_MSI_FLAGS_ENABLE) {
+			dev_info(&pdev->dev, "resetting MSI\n");
+			pci_write_config_word(pdev, msi_control_reg(pos),
+					control & ~PCI_MSI_FLAGS_ENABLE);
+		}
+	}
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+	if (pos) {
+		pci_read_config_word(pdev, msi_control_reg(pos), &control);
+		if (control & PCI_MSIX_FLAGS_ENABLE) {
+			dev_info(&pdev->dev, "resetting MSI-X\n");
+			pci_write_config_word(pdev, msi_control_reg(pos),
+					control & ~PCI_MSIX_FLAGS_ENABLE);
+		}
+	}
+
+	return 0;
+}
+
+/* This does a hard reset of the controller using PCI power management
+ * states.
+ */
+static __devinit int hpsa_hard_reset_controller(struct pci_dev *pdev)
+{
+	u16 pmcsr, saved_config_space[32];
+	int i, pos;
+
+	dev_info(&pdev->dev, "using PCI PM to reset controller\n");
+
+	/* This is very nearly the same thing as
+	 *
+	 * pci_save_state(pci_dev);
+	 * pci_set_power_state(pci_dev, PCI_D3hot);
+	 * pci_set_power_state(pci_dev, PCI_D0);
+	 * pci_restore_state(pci_dev);
+	 *
+	 * but we can't use these nice canned kernel routines on
+	 * kexec, because they also check the MSI/MSI-X state in PCI
+	 * configuration space and do the wrong thing when it is
+	 * set/cleared.  Also, the pci_save/restore_state functions
+	 * violate the ordering requirements for restoring the
+	 * configuration space from the CCISS document (see the
+	 * comment below).  So we roll our own ....
+	 */
+
+	for (i = 0; i < 32; i++)
+		pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
+
+	pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
+	if (pos == 0) {
+		dev_err(&pdev->dev,
+			"hpsa_reset_controller: PCI PM not supported\n");
+		return -ENODEV;
+	}
+
+	/* Quoting from the Open CISS Specification: "The Power
+	 * Management Control/Status Register (CSR) controls the power
+	 * state of the device.  The normal operating state is D0,
+	 * CSR=00h.  The software off state is D3, CSR=03h.  To reset
+	 * the controller, place the interface device in D3 then to
+	 * D0, this causes a secondary PCI reset which will reset the
+	 * controller."
+	 */
+
+	/* enter the D3hot power management state */
+	pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+	pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+	pmcsr |= PCI_D3hot;
+	pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+	msleep(500);
+
+	/* enter the D0 power management state */
+	pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+	pmcsr |= PCI_D0;
+	pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+	msleep(500);
+
+	/* Restore the PCI configuration space.  The Open CISS
+	 * Specification says, "Restore the PCI Configuration
+	 * Registers, offsets 00h through 60h. It is important to
+	 * restore the command register, 16-bits at offset 04h,
+	 * last. Do not restore the configuration status register,
+	 * 16-bits at offset 06h."  Note that the offset is 2*i.
+	 */
+	for (i = 0; i < 32; i++) {
+		if (i == 2 || i == 3)
+			continue;
+		pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+	}
+	wmb();
+	pci_write_config_word(pdev, 4, saved_config_space[2]);
+
+	return 0;
+}
+
+/*
+ *  We cannot read the structure directly, for portability we must use
+ *   the io functions.
+ *   This is for debug only.
+ */
+#ifdef HPSA_DEBUG
+static void print_cfg_table(struct device *dev, struct CfgTable *tb)
+{
+	int i;
+	char temp_name[17];
+
+	dev_info(dev, "Controller Configuration information\n");
+	dev_info(dev, "------------------------------------\n");
+	for (i = 0; i < 4; i++)
+		temp_name[i] = readb(&(tb->Signature[i]));
+	temp_name[4] = '\0';
+	dev_info(dev, "   Signature = %s\n", temp_name);
+	dev_info(dev, "   Spec Number = %d\n", readl(&(tb->SpecValence)));
+	dev_info(dev, "   Transport methods supported = 0x%x\n",
+	       readl(&(tb->TransportSupport)));
+	dev_info(dev, "   Transport methods active = 0x%x\n",
+	       readl(&(tb->TransportActive)));
+	dev_info(dev, "   Requested transport Method = 0x%x\n",
+	       readl(&(tb->HostWrite.TransportRequest)));
+	dev_info(dev, "   Coalesce Interrupt Delay = 0x%x\n",
+	       readl(&(tb->HostWrite.CoalIntDelay)));
+	dev_info(dev, "   Coalesce Interrupt Count = 0x%x\n",
+	       readl(&(tb->HostWrite.CoalIntCount)));
+	dev_info(dev, "   Max outstanding commands = 0x%d\n",
+	       readl(&(tb->CmdsOutMax)));
+	dev_info(dev, "   Bus Types = 0x%x\n", readl(&(tb->BusTypes)));
+	for (i = 0; i < 16; i++)
+		temp_name[i] = readb(&(tb->ServerName[i]));
+	temp_name[16] = '\0';
+	dev_info(dev, "   Server Name = %s\n", temp_name);
+	dev_info(dev, "   Heartbeat Counter = 0x%x\n\n\n",
+		readl(&(tb->HeartBeat)));
+}
+#endif				/* HPSA_DEBUG */
+
+static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
+{
+	int i, offset, mem_type, bar_type;
+
+	if (pci_bar_addr == PCI_BASE_ADDRESS_0)	/* looking for BAR zero? */
+		return 0;
+	offset = 0;
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE;
+		if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
+			offset += 4;
+		else {
+			mem_type = pci_resource_flags(pdev, i) &
+			    PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+			switch (mem_type) {
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
+			case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+				offset += 4;	/* 32 bit */
+				break;
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				offset += 8;
+				break;
+			default:	/* reserved in PCI 2.2 */
+				dev_warn(&pdev->dev,
+				       "base address is invalid\n");
+				return -1;
+				break;
+			}
+		}
+		if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
+			return i + 1;
+	}
+	return -1;
+}
+
+/* If MSI/MSI-X is supported by the kernel we will try to enable it on
+ * controllers that are capable. If not, we use IO-APIC mode.
+ */
+
+static void __devinit hpsa_interrupt_mode(struct ctlr_info *h,
+					   struct pci_dev *pdev, __u32 board_id)
+{
+#ifdef CONFIG_PCI_MSI
+	int err;
+	struct msix_entry hpsa_msix_entries[4] = { {0, 0}, {0, 1},
+	{0, 2}, {0, 3}
+	};
+
+	/* Some boards advertise MSI but don't really support it */
+	if ((board_id == 0x40700E11) ||
+	    (board_id == 0x40800E11) ||
+	    (board_id == 0x40820E11) || (board_id == 0x40830E11))
+		goto default_int_mode;
+	if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+		dev_info(&pdev->dev, "MSIX\n");
+		err = pci_enable_msix(pdev, hpsa_msix_entries, 4);
+		if (!err) {
+			h->intr[0] = hpsa_msix_entries[0].vector;
+			h->intr[1] = hpsa_msix_entries[1].vector;
+			h->intr[2] = hpsa_msix_entries[2].vector;
+			h->intr[3] = hpsa_msix_entries[3].vector;
+			h->msix_vector = 1;
+			return;
+		}
+		if (err > 0) {
+			dev_warn(&pdev->dev, "only %d MSI-X vectors "
+			       "available\n", err);
+			goto default_int_mode;
+		} else {
+			dev_warn(&pdev->dev, "MSI-X init failed %d\n",
+			       err);
+			goto default_int_mode;
+		}
+	}
+	if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+		dev_info(&pdev->dev, "MSI\n");
+		if (!pci_enable_msi(pdev))
+			h->msi_vector = 1;
+		else
+			dev_warn(&pdev->dev, "MSI init failed\n");
+	}
+default_int_mode:
+#endif				/* CONFIG_PCI_MSI */
+	/* if we get here we're going to use the default interrupt mode */
+	h->intr[SIMPLE_MODE_INT] = pdev->irq;
+	return;
+}
+
+static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
+{
+	ushort subsystem_vendor_id, subsystem_device_id, command;
+	__u32 board_id, scratchpad = 0;
+	__u64 cfg_offset;
+	__u32 cfg_base_addr;
+	__u64 cfg_base_addr_index;
+	int i, prod_index, err;
+
+	subsystem_vendor_id = pdev->subsystem_vendor;
+	subsystem_device_id = pdev->subsystem_device;
+	board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
+		    subsystem_vendor_id);
+
+	for (i = 0; i < ARRAY_SIZE(products); i++)
+		if (board_id == products[i].board_id)
+			break;
+
+	prod_index = i;
+
+	if (prod_index == ARRAY_SIZE(products)) {
+		prod_index--;
+		if (subsystem_vendor_id != PCI_VENDOR_ID_HP ||
+				!hpsa_allow_any) {
+			dev_warn(&pdev->dev, "unrecognized board ID:"
+				" 0x%08lx, ignoring.\n",
+				(unsigned long) board_id);
+			return -ENODEV;
+		}
+	}
+	/* check to see if controller has been disabled
+	 * BEFORE trying to enable it
+	 */
+	(void)pci_read_config_word(pdev, PCI_COMMAND, &command);
+	if (!(command & 0x02)) {
+		dev_warn(&pdev->dev, "controller appears to be disabled\n");
+		return -ENODEV;
+	}
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_warn(&pdev->dev, "unable to enable PCI device\n");
+		return err;
+	}
+
+	err = pci_request_regions(pdev, "hpsa");
+	if (err) {
+		dev_err(&pdev->dev, "cannot obtain PCI resources, aborting\n");
+		return err;
+	}
+
+	/* If the kernel supports MSI/MSI-X we will try to enable that,
+	 * else we use the IO-APIC interrupt assigned to us by system ROM.
+	 */
+	hpsa_interrupt_mode(h, pdev, board_id);
+
+	/* find the memory BAR */
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM)
+			break;
+	}
+	if (i == DEVICE_COUNT_RESOURCE) {
+		dev_warn(&pdev->dev, "no memory BAR found\n");
+		err = -ENODEV;
+		goto err_out_free_res;
+	}
+
+	h->paddr = pci_resource_start(pdev, i); /* addressing mode bits
+						 * already removed
+						 */
+
+	h->vaddr = remap_pci_mem(h->paddr, 0x250);
+
+	/* Wait for the board to become ready.  */
+	for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) {
+		scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (scratchpad == HPSA_FIRMWARE_READY)
+			break;
+		msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS);
+	}
+	if (scratchpad != HPSA_FIRMWARE_READY) {
+		dev_warn(&pdev->dev, "board not ready, timed out.\n");
+		err = -ENODEV;
+		goto err_out_free_res;
+	}
+
+	/* get the address index number */
+	cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET);
+	cfg_base_addr &= (__u32) 0x0000ffff;
+	cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
+	if (cfg_base_addr_index == -1) {
+		dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n");
+		err = -ENODEV;
+		goto err_out_free_res;
+	}
+
+	cfg_offset = readl(h->vaddr + SA5_CTMEM_OFFSET);
+	h->cfgtable = remap_pci_mem(pci_resource_start(pdev,
+			       cfg_base_addr_index) + cfg_offset,
+				sizeof(h->cfgtable));
+	h->board_id = board_id;
+
+	/* Query controller for max supported commands: */
+	h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+
+	h->product_name = products[prod_index].product_name;
+	h->access = *(products[prod_index].access);
+	/* Allow room for some ioctls */
+	h->nr_cmds = h->max_commands - 4;
+
+	if ((readb(&h->cfgtable->Signature[0]) != 'C') ||
+	    (readb(&h->cfgtable->Signature[1]) != 'I') ||
+	    (readb(&h->cfgtable->Signature[2]) != 'S') ||
+	    (readb(&h->cfgtable->Signature[3]) != 'S')) {
+		dev_warn(&pdev->dev, "not a valid CISS config table\n");
+		err = -ENODEV;
+		goto err_out_free_res;
+	}
+#ifdef CONFIG_X86
+	{
+		/* Need to enable prefetch in the SCSI core for 6400 in x86 */
+		__u32 prefetch;
+		prefetch = readl(&(h->cfgtable->SCSI_Prefetch));
+		prefetch |= 0x100;
+		writel(prefetch, &(h->cfgtable->SCSI_Prefetch));
+	}
+#endif
+
+	/* Disabling DMA prefetch for the P600
+	 * An ASIC bug may result in a prefetch beyond
+	 * physical memory.
+	 */
+	if (board_id == 0x3225103C) {
+		__u32 dma_prefetch;
+		dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG);
+		dma_prefetch |= 0x8000;
+		writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
+	}
+
+	h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+	/* Update the field, and then ring the doorbell */
+	writel(CFGTBL_Trans_Simple, &(h->cfgtable->HostWrite.TransportRequest));
+	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+
+	/* under certain very rare conditions, this can take awhile.
+	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
+	 * as we enter this code.)
+	 */
+	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
+		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+			break;
+		/* delay and try again */
+		msleep(10);
+	}
+
+#ifdef HPSA_DEBUG
+	print_cfg_table(&pdev->dev, h->cfgtable);
+#endif				/* HPSA_DEBUG */
+
+	if (!(readl(&(h->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
+		dev_warn(&pdev->dev, "unable to get board into simple mode\n");
+		err = -ENODEV;
+		goto err_out_free_res;
+	}
+	return 0;
+
+err_out_free_res:
+	/*
+	 * Deliberately omit pci_disable_device(): it does something nasty to
+	 * Smart Array controllers that pci_enable_device does not undo
+	 */
+	pci_release_regions(pdev);
+	return err;
+}
+
+static int __devinit hpsa_init_one(struct pci_dev *pdev,
+				    const struct pci_device_id *ent)
+{
+	int i;
+	int dac;
+	struct ctlr_info *h;
+
+	if (number_of_controllers == 0)
+		printk(KERN_INFO DRIVER_NAME "\n");
+	if (reset_devices) {
+		/* Reset the controller with a PCI power-cycle */
+		if (hpsa_hard_reset_controller(pdev) || hpsa_reset_msi(pdev))
+			return -ENODEV;
+
+		/* Some devices (notably the HP Smart Array 5i Controller)
+		   need a little pause here */
+		msleep(HPSA_POST_RESET_PAUSE_MSECS);
+
+		/* Now try to get the controller to respond to a no-op */
+		for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
+			if (hpsa_noop(pdev) == 0)
+				break;
+			else
+				dev_warn(&pdev->dev, "no-op failed%s\n",
+						(i < 11 ? "; re-trying" : ""));
+		}
+	}
+
+	BUILD_BUG_ON(sizeof(struct CommandList) % 8);
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -1;
+
+	h->busy_initializing = 1;
+	INIT_HLIST_HEAD(&h->cmpQ);
+	INIT_HLIST_HEAD(&h->reqQ);
+	mutex_init(&h->busy_shutting_down);
+	init_completion(&h->scan_wait);
+	if (hpsa_pci_init(h, pdev) != 0)
+		goto clean1;
+
+	sprintf(h->devname, "hpsa%d", number_of_controllers);
+	h->ctlr = number_of_controllers;
+	number_of_controllers++;
+	h->pdev = pdev;
+
+	/* configure PCI DMA stuff */
+	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
+		dac = 1;
+	else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
+		dac = 0;
+	else {
+		dev_err(&pdev->dev, "no suitable DMA available\n");
+		goto clean1;
+	}
+
+	/* make sure the board interrupts are off */
+	h->access.set_intr_mask(h, HPSA_INTR_OFF);
+	if (request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr,
+			IRQF_DISABLED | IRQF_SHARED, h->devname, h)) {
+		dev_err(&pdev->dev, "unable to get irq %d for %s\n",
+		       h->intr[SIMPLE_MODE_INT], h->devname);
+		goto clean2;
+	}
+
+	dev_info(&pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
+	       h->devname, pdev->device, pci_name(pdev),
+	       h->intr[SIMPLE_MODE_INT], dac ? "" : " not");
+
+	h->cmd_pool_bits =
+	    kmalloc(((h->nr_cmds + BITS_PER_LONG -
+		      1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
+	h->cmd_pool = pci_alloc_consistent(h->pdev,
+		    h->nr_cmds * sizeof(*h->cmd_pool),
+		    &(h->cmd_pool_dhandle));
+	h->errinfo_pool = pci_alloc_consistent(h->pdev,
+		    h->nr_cmds * sizeof(*h->errinfo_pool),
+		    &(h->errinfo_pool_dhandle));
+	if ((h->cmd_pool_bits == NULL)
+	    || (h->cmd_pool == NULL)
+	    || (h->errinfo_pool == NULL)) {
+		dev_err(&pdev->dev, "out of memory");
+		goto clean4;
+	}
+	spin_lock_init(&h->lock);
+
+	pci_set_drvdata(pdev, h);
+	memset(h->cmd_pool_bits, 0,
+	       ((h->nr_cmds + BITS_PER_LONG -
+		 1) / BITS_PER_LONG) * sizeof(unsigned long));
+
+	hpsa_scsi_setup(h);
+
+	/* Turn the interrupts on so we can service requests */
+	h->access.set_intr_mask(h, HPSA_INTR_ON);
+
+	hpsa_register_scsi(h);	/* hook ourselves into SCSI subsystem */
+	h->busy_initializing = 0;
+	return 1;
+
+clean4:
+	kfree(h->cmd_pool_bits);
+	if (h->cmd_pool)
+		pci_free_consistent(h->pdev,
+			    h->nr_cmds * sizeof(struct CommandList),
+			    h->cmd_pool, h->cmd_pool_dhandle);
+	if (h->errinfo_pool)
+		pci_free_consistent(h->pdev,
+			    h->nr_cmds * sizeof(struct ErrorInfo),
+			    h->errinfo_pool,
+			    h->errinfo_pool_dhandle);
+	free_irq(h->intr[SIMPLE_MODE_INT], h);
+clean2:
+clean1:
+	h->busy_initializing = 0;
+	kfree(h);
+	return -1;
+}
+
+static void hpsa_flush_cache(struct ctlr_info *h)
+{
+	char *flush_buf;
+	struct CommandList *c;
+
+	flush_buf = kzalloc(4, GFP_KERNEL);
+	if (!flush_buf)
+		return;
+
+	c = cmd_special_alloc(h);
+	if (!c) {
+		dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
+		goto out_of_memory;
+	}
+	fill_cmd(c, HPSA_CACHE_FLUSH, h, flush_buf, 4, 0,
+		RAID_CTLR_LUNID, TYPE_CMD);
+	hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_TODEVICE);
+	if (c->err_info->CommandStatus != 0)
+		dev_warn(&h->pdev->dev,
+			"error flushing cache on controller\n");
+	cmd_special_free(h, c);
+out_of_memory:
+	kfree(flush_buf);
+}
+
+static void hpsa_shutdown(struct pci_dev *pdev)
+{
+	struct ctlr_info *h;
+
+	h = pci_get_drvdata(pdev);
+	/* Turn board interrupts off  and send the flush cache command
+	 * sendcmd will turn off interrupt, and send the flush...
+	 * To write all data in the battery backed cache to disks
+	 */
+	hpsa_flush_cache(h);
+	h->access.set_intr_mask(h, HPSA_INTR_OFF);
+	free_irq(h->intr[2], h);
+#ifdef CONFIG_PCI_MSI
+	if (h->msix_vector)
+		pci_disable_msix(h->pdev);
+	else if (h->msi_vector)
+		pci_disable_msi(h->pdev);
+#endif				/* CONFIG_PCI_MSI */
+}
+
+static void __devexit hpsa_remove_one(struct pci_dev *pdev)
+{
+	struct ctlr_info *h;
+
+	if (pci_get_drvdata(pdev) == NULL) {
+		dev_err(&pdev->dev, "unable to remove device \n");
+		return;
+	}
+	h = pci_get_drvdata(pdev);
+	mutex_lock(&h->busy_shutting_down);
+	remove_from_scan_list(h);
+	hpsa_unregister_scsi(h);	/* unhook from SCSI subsystem */
+	hpsa_shutdown(pdev);
+	iounmap(h->vaddr);
+	pci_free_consistent(h->pdev,
+		h->nr_cmds * sizeof(struct CommandList),
+		h->cmd_pool, h->cmd_pool_dhandle);
+	pci_free_consistent(h->pdev,
+		h->nr_cmds * sizeof(struct ErrorInfo),
+		h->errinfo_pool, h->errinfo_pool_dhandle);
+	kfree(h->cmd_pool_bits);
+	/*
+	 * Deliberately omit pci_disable_device(): it does something nasty to
+	 * Smart Array controllers that pci_enable_device does not undo
+	 */
+	pci_release_regions(pdev);
+	pci_set_drvdata(pdev, NULL);
+	mutex_unlock(&h->busy_shutting_down);
+	kfree(h);
+}
+
+static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev,
+	__attribute__((unused)) pm_message_t state)
+{
+	return -ENOSYS;
+}
+
+static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev)
+{
+	return -ENOSYS;
+}
+
+static struct pci_driver hpsa_pci_driver = {
+	.name = "hpsa",
+	.probe = hpsa_init_one,
+	.remove = __devexit_p(hpsa_remove_one),
+	.id_table = hpsa_pci_device_id,	/* id_table */
+	.shutdown = hpsa_shutdown,
+	.suspend = hpsa_suspend,
+	.resume = hpsa_resume,
+};
+
+/*
+ *  This is it.  Register the PCI driver information for the cards we control
+ *  the OS will call our registered routines when it finds one of our cards.
+ */
+static int __init hpsa_init(void)
+{
+	int err;
+	/* Start the scan thread */
+	hpsa_scan_thread = kthread_run(hpsa_scan_func, NULL, "hpsa_scan");
+	if (IS_ERR(hpsa_scan_thread)) {
+		err = PTR_ERR(hpsa_scan_thread);
+		return -ENODEV;
+	}
+	err = pci_register_driver(&hpsa_pci_driver);
+	if (err)
+		kthread_stop(hpsa_scan_thread);
+	return err;
+}
+
+static void __exit hpsa_cleanup(void)
+{
+	pci_unregister_driver(&hpsa_pci_driver);
+	kthread_stop(hpsa_scan_thread);
+}
+
+module_init(hpsa_init);
+module_exit(hpsa_cleanup);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
new file mode 100644
index 0000000..6bd1949
--- /dev/null
+++ b/drivers/scsi/hpsa.h
@@ -0,0 +1,273 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; 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, 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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+#ifndef HPSA_H
+#define HPSA_H
+
+#include <scsi/scsicam.h>
+
+#define IO_OK		0
+#define IO_ERROR	1
+
+struct ctlr_info;
+
+struct access_method {
+	void (*submit_command)(struct ctlr_info *h,
+		struct CommandList *c);
+	void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
+	unsigned long (*fifo_full)(struct ctlr_info *h);
+	unsigned long (*intr_pending)(struct ctlr_info *h);
+	unsigned long (*command_completed)(struct ctlr_info *h);
+};
+
+struct hpsa_scsi_dev_t {
+	int devtype;
+	int bus, target, lun;		/* as presented to the OS */
+	unsigned char scsi3addr[8];	/* as presented to the HW */
+#define RAID_CTLR_LUNID "\0\0\0\0\0\0\0\0"
+	unsigned char device_id[16];    /* from inquiry pg. 0x83 */
+	unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
+	unsigned char model[16];        /* bytes 16-31 of inquiry data */
+	unsigned char revision[4];      /* bytes 32-35 of inquiry data */
+	unsigned char raid_level;	/* from inquiry page 0xC1 */
+};
+
+struct ctlr_info {
+	int	ctlr;
+	char	devname[8];
+	char    *product_name;
+	char	firm_ver[4]; /* Firmware version */
+	struct pci_dev *pdev;
+	__u32	board_id;
+	void __iomem *vaddr;
+	unsigned long paddr;
+	int 	nr_cmds; /* Number of commands allowed on this controller */
+	struct CfgTable __iomem *cfgtable;
+	int	interrupts_enabled;
+	int	major;
+	int 	max_commands;
+	int	commands_outstanding;
+	int 	max_outstanding; /* Debug */
+	int	usage_count;  /* number of opens all all minor devices */
+#	define DOORBELL_INT	0
+#	define PERF_MODE_INT	1
+#	define SIMPLE_MODE_INT	2
+#	define MEMQ_MODE_INT	3
+	unsigned int intr[4];
+	unsigned int msix_vector;
+	unsigned int msi_vector;
+	struct access_method access;
+
+	/* queue and queue Info */
+	struct hlist_head reqQ;
+	struct hlist_head cmpQ;
+	unsigned int Qdepth;
+	unsigned int maxQsinceinit;
+	unsigned int maxSG;
+	spinlock_t lock;
+
+	/* pointers to command and error info pool */
+	struct CommandList 	*cmd_pool;
+	dma_addr_t		cmd_pool_dhandle;
+	struct ErrorInfo 	*errinfo_pool;
+	dma_addr_t		errinfo_pool_dhandle;
+	unsigned long  		*cmd_pool_bits;
+	int			nr_allocs;
+	int			nr_frees;
+	int			busy_initializing;
+	int			busy_scanning;
+	struct mutex		busy_shutting_down;
+	struct list_head	scan_list;
+	struct completion	scan_wait;
+
+	struct Scsi_Host *scsi_host;
+	spinlock_t devlock; /* to protect hba[ctlr]->dev[];  */
+	int ndevices; /* number of used elements in .dev[] array. */
+#define HPSA_MAX_SCSI_DEVS_PER_HBA 256
+	struct hpsa_scsi_dev_t *dev[HPSA_MAX_SCSI_DEVS_PER_HBA];
+};
+#define HPSA_ABORT_MSG 0
+#define HPSA_DEVICE_RESET_MSG 1
+#define HPSA_BUS_RESET_MSG 2
+#define HPSA_HOST_RESET_MSG 3
+#define HPSA_MSG_SEND_RETRY_LIMIT 10
+#define HPSA_MSG_SEND_RETRY_INTERVAL_MSECS 1000
+
+/* Maximum time in seconds driver will wait for command completions
+ * when polling before giving up.
+ */
+#define HPSA_MAX_POLL_TIME_SECS (20)
+
+/* During SCSI error recovery, HPSA_TUR_RETRY_LIMIT defines
+ * how many times to retry TEST UNIT READY on a device
+ * while waiting for it to become ready before giving up.
+ * HPSA_MAX_WAIT_INTERVAL_SECS is the max wait interval
+ * between sending TURs while waiting for a device
+ * to become ready.
+ */
+#define HPSA_TUR_RETRY_LIMIT (20)
+#define HPSA_MAX_WAIT_INTERVAL_SECS (30)
+
+/* HPSA_BOARD_READY_WAIT_SECS is how long to wait for a board
+ * to become ready, in seconds, before giving up on it.
+ * HPSA_BOARD_READY_POLL_INTERVAL_MSECS * is how long to wait
+ * between polling the board to see if it is ready, in
+ * milliseconds.  HPSA_BOARD_READY_POLL_INTERVAL and
+ * HPSA_BOARD_READY_ITERATIONS are derived from those.
+ */
+#define HPSA_BOARD_READY_WAIT_SECS (120)
+#define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
+#define HPSA_BOARD_READY_POLL_INTERVAL \
+	((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
+#define HPSA_BOARD_READY_ITERATIONS \
+	((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
+		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
+#define HPSA_POST_RESET_PAUSE_MSECS (3000)
+#define HPSA_POST_RESET_NOOP_RETRIES (12)
+
+/*  Defining the diffent access_menthods */
+/*
+ * Memory mapped FIFO interface (SMART 53xx cards)
+ */
+#define SA5_DOORBELL	0x20
+#define SA5_REQUEST_PORT_OFFSET	0x40
+#define SA5_REPLY_INTR_MASK_OFFSET	0x34
+#define SA5_REPLY_PORT_OFFSET		0x44
+#define SA5_INTR_STATUS		0x30
+#define SA5_SCRATCHPAD_OFFSET	0xB0
+
+#define SA5_CTCFG_OFFSET	0xB4
+#define SA5_CTMEM_OFFSET	0xB8
+
+#define SA5_INTR_OFF		0x08
+#define SA5B_INTR_OFF		0x04
+#define SA5_INTR_PENDING	0x08
+#define SA5B_INTR_PENDING	0x04
+#define FIFO_EMPTY		0xffffffff
+#define HPSA_FIRMWARE_READY	0xffff0000 /* value in scratchpad register */
+
+#define HPSA_ERROR_BIT		0x02
+#define HPSA_TAG_CONTAINS_INDEX(tag) ((tag) & 0x04)
+#define HPSA_TAG_TO_INDEX(tag) ((tag) >> 3)
+#define HPSA_TAG_DISCARD_ERROR_BITS(tag) ((tag) & ~3)
+
+#define HPSA_INTR_ON 	1
+#define HPSA_INTR_OFF	0
+/*
+	Send the command to the hardware
+*/
+static void SA5_submit_command(struct ctlr_info *h,
+	struct CommandList *c)
+{
+#ifdef HPSA_DEBUG
+	 printk(KERN_WARNING "hpsa: Sending %x - down to controller\n",
+		c->busaddr);
+#endif /* HPSA_DEBUG */
+	writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	h->commands_outstanding++;
+	if (h->commands_outstanding > h->max_outstanding)
+		h->max_outstanding = h->commands_outstanding;
+}
+
+/*
+ *  This card is the opposite of the other cards.
+ *   0 turns interrupts on...
+ *   0x08 turns them off...
+ */
+static void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
+{
+	if (val) { /* Turn interrupts on */
+		h->interrupts_enabled = 1;
+		writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+	} else { /* Turn them off */
+		h->interrupts_enabled = 0;
+		writel(SA5_INTR_OFF,
+			h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+	}
+}
+/*
+ *  Returns true if fifo is full.
+ *
+ */
+static unsigned long SA5_fifo_full(struct ctlr_info *h)
+{
+	if (h->commands_outstanding >= h->max_commands)
+		return 1;
+	else
+		return 0;
+
+}
+/*
+ *   returns value read from hardware.
+ *     returns FIFO_EMPTY if there is nothing to read
+ */
+static unsigned long SA5_completed(struct ctlr_info *h)
+{
+	unsigned long register_value
+		= readl(h->vaddr + SA5_REPLY_PORT_OFFSET);
+
+	if (register_value != FIFO_EMPTY)
+		h->commands_outstanding--;
+
+#ifdef HPSA_DEBUG
+	if (register_value != FIFO_EMPTY)
+		printk(KERN_INFO "hpsa:  Read %lx back from board\n",
+			register_value);
+	else
+		printk(KERN_INFO "hpsa:  FIFO Empty read\n");
+#endif
+
+	return register_value;
+}
+/*
+ *	Returns true if an interrupt is pending..
+ */
+static unsigned long SA5_intr_pending(struct ctlr_info *h)
+{
+	unsigned long register_value  =
+		readl(h->vaddr + SA5_INTR_STATUS);
+#ifdef HPSA_DEBUG
+	printk(KERN_INFO "hpsa: intr_pending %lx\n", register_value);
+#endif  /* HPSA_DEBUG */
+	if (register_value &  SA5_INTR_PENDING)
+		return  1;
+	return 0 ;
+}
+
+
+static struct access_method SA5_access = {
+	SA5_submit_command,
+	SA5_intr_mask,
+	SA5_fifo_full,
+	SA5_intr_pending,
+	SA5_completed,
+};
+
+struct board_type {
+	__u32	board_id;
+	char	*product_name;
+	struct access_method *access;
+};
+
+
+/* end of old hpsa_scsi.h file */
+
+#endif /* HPSA_H */
+
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
new file mode 100644
index 0000000..12d7138
--- /dev/null
+++ b/drivers/scsi/hpsa_cmd.h
@@ -0,0 +1,326 @@
+/*
+ *    Disk Array driver for HP Smart Array SAS controllers
+ *    Copyright 2000, 2009 Hewlett-Packard Development Company, L.P.
+ *
+ *    This program is free software; 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, 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.
+ *
+ *    Questions/Comments/Bugfixes to iss_storagedev@hp.com
+ *
+ */
+#ifndef HPSA_CMD_H
+#define HPSA_CMD_H
+
+/* general boundary defintions */
+#define SENSEINFOBYTES          32 /* may vary between hbas */
+#define MAXSGENTRIES            31
+#define MAXREPLYQS              256
+
+/* Command Status value */
+#define CMD_SUCCESS             0x0000
+#define CMD_TARGET_STATUS       0x0001
+#define CMD_DATA_UNDERRUN       0x0002
+#define CMD_DATA_OVERRUN        0x0003
+#define CMD_INVALID             0x0004
+#define CMD_PROTOCOL_ERR        0x0005
+#define CMD_HARDWARE_ERR        0x0006
+#define CMD_CONNECTION_LOST     0x0007
+#define CMD_ABORTED             0x0008
+#define CMD_ABORT_FAILED        0x0009
+#define CMD_UNSOLICITED_ABORT   0x000A
+#define CMD_TIMEOUT             0x000B
+#define CMD_UNABORTABLE		0x000C
+
+/* Unit Attentions ASC's as defined for the MSA2012sa */
+#define POWER_OR_RESET			0x29
+#define STATE_CHANGED			0x2a
+#define UNIT_ATTENTION_CLEARED		0x2f
+#define LUN_FAILED			0x3e
+#define REPORT_LUNS_CHANGED		0x3f
+
+/* Unit Attentions ASCQ's as defined for the MSA2012sa */
+
+	/* These ASCQ's defined for ASC = POWER_OR_RESET */
+#define POWER_ON_RESET			0x00
+#define POWER_ON_REBOOT			0x01
+#define SCSI_BUS_RESET			0x02
+#define MSA_TARGET_RESET		0x03
+#define CONTROLLER_FAILOVER		0x04
+#define TRANSCEIVER_SE			0x05
+#define TRANSCEIVER_LVD			0x06
+
+	/* These ASCQ's defined for ASC = STATE_CHANGED */
+#define RESERVATION_PREEMPTED		0x03
+#define ASYM_ACCESS_CHANGED		0x06
+#define LUN_CAPACITY_CHANGED		0x09
+
+/* transfer direction */
+#define XFER_NONE               0x00
+#define XFER_WRITE              0x01
+#define XFER_READ               0x02
+#define XFER_RSVD               0x03
+
+/* task attribute */
+#define ATTR_UNTAGGED           0x00
+#define ATTR_SIMPLE             0x04
+#define ATTR_HEADOFQUEUE        0x05
+#define ATTR_ORDERED            0x06
+#define ATTR_ACA                0x07
+
+/* cdb type */
+#define TYPE_CMD				0x00
+#define TYPE_MSG				0x01
+
+/* config space register offsets */
+#define CFG_VENDORID            0x00
+#define CFG_DEVICEID            0x02
+#define CFG_I2OBAR              0x10
+#define CFG_MEM1BAR             0x14
+
+/* i2o space register offsets */
+#define I2O_IBDB_SET            0x20
+#define I2O_IBDB_CLEAR          0x70
+#define I2O_INT_STATUS          0x30
+#define I2O_INT_MASK            0x34
+#define I2O_IBPOST_Q            0x40
+#define I2O_OBPOST_Q            0x44
+#define I2O_DMA1_CFG		0x214
+
+/* Configuration Table */
+#define CFGTBL_ChangeReq        0x00000001l
+#define CFGTBL_AccCmds          0x00000001l
+
+#define CFGTBL_Trans_Simple     0x00000002l
+
+#define CFGTBL_BusType_Ultra2   0x00000001l
+#define CFGTBL_BusType_Ultra3   0x00000002l
+#define CFGTBL_BusType_Fibre1G  0x00000100l
+#define CFGTBL_BusType_Fibre2G  0x00000200l
+struct vals32 {
+	__u32   lower;
+	__u32   upper;
+};
+
+union u64bit {
+	struct vals32 val32;
+	__u64 val;
+};
+
+/* FIXME this is a per controller value (barf!) */
+#define HPSA_MAX_TARGETS_PER_CTLR 16
+#define HPSA_MAX_LUN 256
+#define HPSA_MAX_PHYS_LUN 1024
+
+/* SCSI-3 Commands */
+#pragma pack(1)
+
+#define HPSA_INQUIRY 0x12
+struct InquiryData {
+	__u8 data_byte[36];
+};
+
+#define HPSA_REPORT_LOG 0xc2    /* Report Logical LUNs */
+#define HPSA_REPORT_PHYS 0xc3   /* Report Physical LUNs */
+struct ReportLUNdata {
+	__u8 LUNListLength[4];
+	__u32 reserved;
+	__u8 LUN[HPSA_MAX_LUN][8];
+};
+
+struct ReportExtendedLUNdata {
+	__u8 LUNListLength[4];
+	__u8 extended_response_flag;
+	__u8 reserved[3];
+	__u8 LUN[HPSA_MAX_LUN][24];
+};
+
+struct SenseSubsystem_info {
+	__u8 reserved[36];
+	__u8 portname[8];
+	__u8 reserved1[1108];
+};
+
+#define HPSA_READ_CAPACITY 0x25 /* Read Capacity */
+struct ReadCapdata {
+	__u8 total_size[4];	/* Total size in blocks */
+	__u8 block_size[4];	/* Size of blocks in bytes */
+};
+
+#if 0
+/* 12 byte commands not implemented in firmware yet. */
+#define HPSA_READ 	0xa8
+#define HPSA_WRITE	0xaa
+#endif
+
+#define HPSA_READ   0x28    /* Read(10) */
+#define HPSA_WRITE  0x2a    /* Write(10) */
+
+/* BMIC commands */
+#define BMIC_READ 0x26
+#define BMIC_WRITE 0x27
+#define BMIC_CACHE_FLUSH 0xc2
+#define HPSA_CACHE_FLUSH 0x01	/* C2 was already being used by HPSA */
+
+/* Command List Structure */
+union SCSI3Addr {
+	struct {
+		__u8 Dev;
+		__u8 Bus:6;
+		__u8 Mode:2;        /* b00 */
+	} PeripDev;
+	struct {
+		__u8 DevLSB;
+		__u8 DevMSB:6;
+		__u8 Mode:2;        /* b01 */
+	} LogDev;
+	struct {
+		__u8 Dev:5;
+		__u8 Bus:3;
+		__u8 Targ:6;
+		__u8 Mode:2;        /* b10 */
+	} LogUnit;
+};
+
+struct PhysDevAddr {
+	__u32             TargetId:24;
+	__u32             Bus:6;
+	__u32             Mode:2;
+	/* 2 level target device addr */
+	union SCSI3Addr  Target[2];
+};
+
+struct LogDevAddr {
+	__u32            VolId:30;
+	__u32            Mode:2;
+	__u8             reserved[4];
+};
+
+union LUNAddr {
+	__u8               LunAddrBytes[8];
+	union SCSI3Addr    SCSI3Lun[4];
+	struct PhysDevAddr PhysDev;
+	struct LogDevAddr  LogDev;
+};
+
+struct CommandListHeader {
+	__u8              ReplyQueue;
+	__u8              SGList;
+	__u16             SGTotal;
+	struct vals32     Tag;
+	union LUNAddr     LUN;
+};
+
+struct RequestBlock {
+	__u8   CDBLen;
+	struct {
+		__u8 Type:3;
+		__u8 Attribute:3;
+		__u8 Direction:2;
+	} Type;
+	__u16  Timeout;
+	__u8   CDB[16];
+};
+
+struct ErrDescriptor {
+	struct vals32 Addr;
+	__u32  Len;
+};
+
+struct SGDescriptor {
+	struct vals32 Addr;
+	__u32  Len;
+	__u32  Ext;
+};
+
+union MoreErrInfo {
+	struct {
+		__u8  Reserved[3];
+		__u8  Type;
+		__u32 ErrorInfo;
+	} Common_Info;
+	struct {
+		__u8  Reserved[2];
+		__u8  offense_size; /* size of offending entry */
+		__u8  offense_num;  /* byte # of offense 0-base */
+		__u32 offense_value;
+	} Invalid_Cmd;
+};
+struct ErrorInfo {
+	__u8               ScsiStatus;
+	__u8               SenseLen;
+	__u16              CommandStatus;
+	__u32              ResidualCnt;
+	union MoreErrInfo  MoreErrInfo;
+	__u8               SenseInfo[SENSEINFOBYTES];
+};
+/* Command types */
+#define CMD_IOCTL_PEND  0x01
+#define CMD_SCSI	0x03
+
+struct ctlr_info; /* defined in hpsa.h */
+/* The size of this structure needs to be divisible by 8
+ * od on all architectures, because the controller uses 2
+ * lower bits of the address, and the driver uses 1 lower
+ * bit (3 bits total.)
+ */
+struct CommandList {
+	struct CommandListHeader Header;
+	struct RequestBlock      Request;
+	struct ErrDescriptor     ErrDesc;
+	struct SGDescriptor      SG[MAXSGENTRIES];
+	/* information associated with the command */
+	__u32			   busaddr; /* physical addr of this record */
+	struct ErrorInfo *err_info; /* pointer to the allocated mem */
+	struct ctlr_info	   *h;
+	int			   cmd_type;
+	long			   cmdindex;
+	struct hlist_node list;
+	struct CommandList *prev;
+	struct CommandList *next;
+	struct request *rq;
+	struct completion *waiting;
+	int	 retry_count;
+	void   *scsi_cmd;
+};
+
+/* Configuration Table Structure */
+struct HostWrite {
+	__u32 TransportRequest;
+	__u32 Reserved;
+	__u32 CoalIntDelay;
+	__u32 CoalIntCount;
+};
+
+struct CfgTable {
+	__u8             Signature[4];
+	__u32            SpecValence;
+	__u32            TransportSupport;
+	__u32            TransportActive;
+	struct HostWrite HostWrite;
+	__u32            CmdsOutMax;
+	__u32            BusTypes;
+	__u32            Reserved;
+	__u8             ServerName[16];
+	__u32            HeartBeat;
+	__u32            SCSI_Prefetch;
+};
+
+struct hpsa_pci_info {
+	unsigned char	bus;
+	unsigned char	dev_fn;
+	unsigned short	domain;
+	__u32		board_id;
+};
+
+#pragma pack()
+#endif /* HPSA_CMD_H */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8643f50..9e52d16 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -6521,6 +6521,7 @@
 	int rc;
 
 	ENTER;
+	ioa_cfg->pdev->state_saved = true;
 	rc = pci_restore_state(ioa_cfg->pdev);
 
 	if (rc != PCIBIOS_SUCCESSFUL) {
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index c4b58d0..881d5df 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -68,18 +68,20 @@
 
 /**
  * struct fc_fcp_internal - FCP layer internal data
- * @scsi_pkt_pool:  Memory pool to draw FCP packets from
+ * @scsi_pkt_pool: Memory pool to draw FCP packets from
+ * @scsi_queue_lock: Protects the scsi_pkt_queue
  * @scsi_pkt_queue: Current FCP packets
  * @last_can_queue_ramp_down_time: ramp down time
  * @last_can_queue_ramp_up_time: ramp up time
  * @max_can_queue: max can_queue size
  */
 struct fc_fcp_internal {
-	mempool_t	 *scsi_pkt_pool;
-	struct list_head scsi_pkt_queue;
-	unsigned long last_can_queue_ramp_down_time;
-	unsigned long last_can_queue_ramp_up_time;
-	int max_can_queue;
+	mempool_t		*scsi_pkt_pool;
+	spinlock_t		scsi_queue_lock;
+	struct list_head	scsi_pkt_queue;
+	unsigned long		last_can_queue_ramp_down_time;
+	unsigned long		last_can_queue_ramp_up_time;
+	int			max_can_queue;
 };
 
 #define fc_get_scsi_internal(x)	((struct fc_fcp_internal *)(x)->scsi_priv)
@@ -410,12 +412,14 @@
 	unsigned long flags;
 
 	fp = fc_frame_alloc(lport, len);
-	if (!fp) {
-		spin_lock_irqsave(lport->host->host_lock, flags);
-		fc_fcp_can_queue_ramp_down(lport);
-		spin_unlock_irqrestore(lport->host->host_lock, flags);
-	}
-	return fp;
+	if (likely(fp))
+		return fp;
+
+	/* error case */
+	spin_lock_irqsave(lport->host->host_lock, flags);
+	fc_fcp_can_queue_ramp_down(lport);
+	spin_unlock_irqrestore(lport->host->host_lock, flags);
+	return NULL;
 }
 
 /**
@@ -990,7 +994,7 @@
 	struct scsi_cmnd *sc_cmd;
 	unsigned long flags;
 
-	spin_lock_irqsave(lport->host->host_lock, flags);
+	spin_lock_irqsave(&si->scsi_queue_lock, flags);
 restart:
 	list_for_each_entry(fsp, &si->scsi_pkt_queue, list) {
 		sc_cmd = fsp->cmd;
@@ -1001,7 +1005,7 @@
 			continue;
 
 		fc_fcp_pkt_hold(fsp);
-		spin_unlock_irqrestore(lport->host->host_lock, flags);
+		spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 
 		if (!fc_fcp_lock_pkt(fsp)) {
 			fc_fcp_cleanup_cmd(fsp, error);
@@ -1010,14 +1014,14 @@
 		}
 
 		fc_fcp_pkt_release(fsp);
-		spin_lock_irqsave(lport->host->host_lock, flags);
+		spin_lock_irqsave(&si->scsi_queue_lock, flags);
 		/*
 		 * while we dropped the lock multiple pkts could
 		 * have been released, so we have to start over.
 		 */
 		goto restart;
 	}
-	spin_unlock_irqrestore(lport->host->host_lock, flags);
+	spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 }
 
 /**
@@ -1035,11 +1039,12 @@
  * @fsp:   The FCP packet to send
  *
  * Return:  Zero for success and -1 for failure
- * Locks:   Called with the host lock and irqs disabled.
+ * Locks:   Called without locks held
  */
 static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
 {
 	struct fc_fcp_internal *si = fc_get_scsi_internal(lport);
+	unsigned long flags;
 	int rc;
 
 	fsp->cmd->SCp.ptr = (char *)fsp;
@@ -1049,13 +1054,16 @@
 	int_to_scsilun(fsp->cmd->device->lun,
 		       (struct scsi_lun *)fsp->cdb_cmd.fc_lun);
 	memcpy(fsp->cdb_cmd.fc_cdb, fsp->cmd->cmnd, fsp->cmd->cmd_len);
-	list_add_tail(&fsp->list, &si->scsi_pkt_queue);
 
-	spin_unlock_irq(lport->host->host_lock);
+	spin_lock_irqsave(&si->scsi_queue_lock, flags);
+	list_add_tail(&fsp->list, &si->scsi_pkt_queue);
+	spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 	rc = lport->tt.fcp_cmd_send(lport, fsp, fc_fcp_recv);
-	spin_lock_irq(lport->host->host_lock);
-	if (rc)
+	if (unlikely(rc)) {
+		spin_lock_irqsave(&si->scsi_queue_lock, flags);
 		list_del(&fsp->list);
+		spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
+	}
 
 	return rc;
 }
@@ -1752,6 +1760,7 @@
 	struct fcoe_dev_stats *stats;
 
 	lport = shost_priv(sc_cmd->device->host);
+	spin_unlock_irq(lport->host->host_lock);
 
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
@@ -1834,6 +1843,7 @@
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 out:
+	spin_lock_irq(lport->host->host_lock);
 	return rc;
 }
 EXPORT_SYMBOL(fc_queuecommand);
@@ -1864,11 +1874,8 @@
 
 	lport = fsp->lp;
 	si = fc_get_scsi_internal(lport);
-	spin_lock_irqsave(lport->host->host_lock, flags);
-	if (!fsp->cmd) {
-		spin_unlock_irqrestore(lport->host->host_lock, flags);
+	if (!fsp->cmd)
 		return;
-	}
 
 	/*
 	 * if can_queue ramp down is done then try can_queue ramp up
@@ -1880,10 +1887,8 @@
 	sc_cmd = fsp->cmd;
 	fsp->cmd = NULL;
 
-	if (!sc_cmd->SCp.ptr) {
-		spin_unlock_irqrestore(lport->host->host_lock, flags);
+	if (!sc_cmd->SCp.ptr)
 		return;
-	}
 
 	CMD_SCSI_STATUS(sc_cmd) = fsp->cdb_status;
 	switch (fsp->status_code) {
@@ -1945,10 +1950,11 @@
 		break;
 	}
 
+	spin_lock_irqsave(&si->scsi_queue_lock, flags);
 	list_del(&fsp->list);
+	spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
 	sc_cmd->SCp.ptr = NULL;
 	sc_cmd->scsi_done(sc_cmd);
-	spin_unlock_irqrestore(lport->host->host_lock, flags);
 
 	/* release ref from initial allocation in queue command */
 	fc_fcp_pkt_release(fsp);
@@ -2216,6 +2222,7 @@
 	lport->scsi_priv = si;
 	si->max_can_queue = lport->host->can_queue;
 	INIT_LIST_HEAD(&si->scsi_pkt_queue);
+	spin_lock_init(&si->scsi_queue_lock);
 
 	si->scsi_pkt_pool = mempool_create_slab_pool(2, scsi_pkt_cachep);
 	if (!si->scsi_pkt_pool) {
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 74338c8..0b16502 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -537,7 +537,9 @@
 	int rc = -1;
 
 	mutex_lock(&lport->lp_mutex);
-	if (lport->state == LPORT_ST_DISABLED) {
+	if (lport->state == LPORT_ST_DISABLED ||
+	    lport->state == LPORT_ST_LOGO) {
+		fc_lport_state_enter(lport, LPORT_ST_RESET);
 		fc_lport_enter_reset(lport);
 		rc = 0;
 	}
@@ -967,6 +969,9 @@
 	FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
 		     fc_lport_state(lport));
 
+	if (lport->state == LPORT_ST_DISABLED || lport->state == LPORT_ST_LOGO)
+		return;
+
 	if (lport->vport) {
 		if (lport->link_up)
 			fc_vport_set_state(lport->vport, FC_VPORT_INITIALIZING);
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index 35ca0e7..0230052 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -310,6 +310,7 @@
 				restart = 1;
 			else
 				list_del(&rdata->peers);
+			rdata->event = RPORT_EV_NONE;
 			mutex_unlock(&rdata->rp_mutex);
 			mutex_unlock(&lport->disc.disc_mutex);
 		}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 226920d..d4da6bd 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4506,9 +4506,13 @@
 		pdev = phba->pcidev;
 
 	/* Set the device DMA mask size */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+	 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+		 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
 			return error;
+		}
+	}
 
 	/* Get the bus address of Bar0 and Bar2 and the number of bytes
 	 * required by each mapping.
@@ -6021,9 +6025,13 @@
 		pdev = phba->pcidev;
 
 	/* Set the device DMA mask size */
-	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+	 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+		if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+		 || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
 			return error;
+		}
+	}
 
 	/* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
 	 * number of bytes required by each mapping. They are actually
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 134c63e..99ff99e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -2501,7 +2501,9 @@
 		instance->base_addr = pci_resource_start(instance->pdev, 0);
 	}
 
-	if (pci_request_regions(instance->pdev, "megasas: LSI")) {
+	if (pci_request_selected_regions(instance->pdev,
+		pci_select_bars(instance->pdev, IORESOURCE_MEM),
+		"megasas: LSI")) {
 		printk(KERN_DEBUG "megasas: IO memory region busy!\n");
 		return -EBUSY;
 	}
@@ -2642,7 +2644,8 @@
 	iounmap(instance->reg_set);
 
       fail_ioremap:
-	pci_release_regions(instance->pdev);
+	pci_release_selected_regions(instance->pdev,
+		pci_select_bars(instance->pdev, IORESOURCE_MEM));
 
 	return -EINVAL;
 }
@@ -2662,7 +2665,8 @@
 
 	iounmap(instance->reg_set);
 
-	pci_release_regions(instance->pdev);
+	pci_release_selected_regions(instance->pdev,
+		pci_select_bars(instance->pdev, IORESOURCE_MEM));
 }
 
 /**
@@ -2971,7 +2975,7 @@
 	/*
 	 * PCI prepping: enable device set bus mastering and dma mask
 	 */
-	rval = pci_enable_device(pdev);
+	rval = pci_enable_device_mem(pdev);
 
 	if (rval) {
 		return rval;
@@ -3276,7 +3280,7 @@
 	/*
 	 * PCI prepping: enable device set bus mastering and dma mask
 	 */
-	rval = pci_enable_device(pdev);
+	rval = pci_enable_device_mem(pdev);
 
 	if (rval) {
 		printk(KERN_ERR "megasas: Enable device failed\n");
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 6422e25..89d0240 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -3583,6 +3583,11 @@
 	ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
 	mutex_init(&ioc->transport_cmds.mutex);
 
+	/* scsih internal command bits */
+	ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+	ioc->scsih_cmds.status = MPT2_CMD_NOT_USED;
+	mutex_init(&ioc->scsih_cmds.mutex);
+
 	/* task management internal command bits */
 	ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
 	ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index c790d45..cae6b2c 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -657,6 +657,7 @@
 	{ PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
+	{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
 
 	{ }	/* terminate list */
 };
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 950202a..2422347 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -432,30 +432,23 @@
 	seg->alloc_size = 0;
 }
 
-static void _put_request(struct request *rq , bool is_async)
+static void _put_request(struct request *rq)
 {
-	if (is_async) {
-		WARN_ON(rq->bio);
-		__blk_put_request(rq->q, rq);
-	} else {
-		/*
-		 * If osd_finalize_request() was called but the request was not
-		 * executed through the block layer, then we must release BIOs.
-		 * TODO: Keep error code in or->async_error. Need to audit all
-		 *       code paths.
-		 */
-		if (unlikely(rq->bio))
-			blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
-		else
-			blk_put_request(rq);
-	}
+	/*
+	 * If osd_finalize_request() was called but the request was not
+	 * executed through the block layer, then we must release BIOs.
+	 * TODO: Keep error code in or->async_error. Need to audit all
+	 *       code paths.
+	 */
+	if (unlikely(rq->bio))
+		blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
+	else
+		blk_put_request(rq);
 }
 
 void osd_end_request(struct osd_request *or)
 {
 	struct request *rq = or->request;
-	/* IMPORTANT: make sure this agrees with osd_execute_request_async */
-	bool is_async = (or->request->end_io_data == or);
 
 	_osd_free_seg(or, &or->set_attr);
 	_osd_free_seg(or, &or->enc_get_attr);
@@ -463,20 +456,34 @@
 
 	if (rq) {
 		if (rq->next_rq) {
-			_put_request(rq->next_rq, is_async);
+			_put_request(rq->next_rq);
 			rq->next_rq = NULL;
 		}
 
-		_put_request(rq, is_async);
+		_put_request(rq);
 	}
 	_osd_request_free(or);
 }
 EXPORT_SYMBOL(osd_end_request);
 
+static void _set_error_resid(struct osd_request *or, struct request *req,
+			     int error)
+{
+	or->async_error = error;
+	or->req_errors = req->errors ? : error;
+	or->sense_len = req->sense_len;
+	if (or->out.req)
+		or->out.residual = or->out.req->resid_len;
+	if (or->in.req)
+		or->in.residual = or->in.req->resid_len;
+}
+
 int osd_execute_request(struct osd_request *or)
 {
-	return or->async_error =
-			blk_execute_rq(or->request->q, NULL, or->request, 0);
+	int error = blk_execute_rq(or->request->q, NULL, or->request, 0);
+
+	_set_error_resid(or, or->request, error);
+	return error;
 }
 EXPORT_SYMBOL(osd_execute_request);
 
@@ -484,15 +491,17 @@
 {
 	struct osd_request *or = req->end_io_data;
 
-	or->async_error = error;
-
-	if (unlikely(error)) {
-		OSD_DEBUG("osd_request_async_done error recieved %d "
-			  "errors 0x%x\n", error, req->errors);
-		if (!req->errors) /* don't miss out on this one */
-			req->errors = error;
+	_set_error_resid(or, req, error);
+	if (req->next_rq) {
+		__blk_put_request(req->q, req->next_rq);
+		req->next_rq = NULL;
 	}
 
+	__blk_put_request(req->q, req);
+	or->request = NULL;
+	or->in.req = NULL;
+	or->out.req = NULL;
+
 	if (or->async_done)
 		or->async_done(or, or->async_private);
 	else
@@ -1489,21 +1498,18 @@
 #endif
 	int ret;
 
-	if (likely(!or->request->errors)) {
-		osi->out_resid = 0;
-		osi->in_resid = 0;
+	if (likely(!or->req_errors))
 		return 0;
-	}
 
 	osi = osi ? : &local_osi;
 	memset(osi, 0, sizeof(*osi));
 
-	ssdb = or->request->sense;
-	sense_len = or->request->sense_len;
+	ssdb = (typeof(ssdb))or->sense;
+	sense_len = or->sense_len;
 	if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
 		OSD_ERR("Block-layer returned error(0x%x) but "
 			"sense_len(%u) || key(%d) is empty\n",
-			or->request->errors, sense_len, ssdb->sense_key);
+			or->req_errors, sense_len, ssdb->sense_key);
 		goto analyze;
 	}
 
@@ -1525,7 +1531,7 @@
 			"additional_code=0x%x async_error=%d errors=0x%x\n",
 			osi->key, original_sense_len, sense_len,
 			osi->additional_code, or->async_error,
-			or->request->errors);
+			or->req_errors);
 
 	if (original_sense_len < sense_len)
 		sense_len = original_sense_len;
@@ -1695,10 +1701,10 @@
 		ret = -EIO;
 	}
 
-	if (or->out.req)
-		osi->out_resid = or->out.req->resid_len ?: or->out.total_bytes;
-	if (or->in.req)
-		osi->in_resid = or->in.req->resid_len ?: or->in.total_bytes;
+	if (!or->out.residual)
+		or->out.residual = or->out.total_bytes;
+	if (!or->in.residual)
+		or->in.residual = or->in.total_bytes;
 
 	return ret;
 }
diff --git a/drivers/scsi/pm8001/pm8001_ctl.h b/drivers/scsi/pm8001/pm8001_ctl.h
index 22644de..63ad4aa 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.h
+++ b/drivers/scsi/pm8001/pm8001_ctl.h
@@ -45,16 +45,6 @@
 #define HEADER_LEN			28
 #define SIZE_OFFSET			16
 
-struct pm8001_ioctl_payload {
-	u32	signature;
-	u16	major_function;
-	u16	minor_function;
-	u16	length;
-	u16	status;
-	u16	offset;
-	u16	id;
-	u8	func_specific[1];
-};
 
 #define FLASH_OK                        0x000000
 #define FAIL_OPEN_BIOS_FILE             0x000100
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a3de306..9b44c6f 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -373,10 +373,7 @@
 static void __devinit
 mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
 {
-	u32 offset;
-	u32 value;
-	u32 i, j;
-	u32 bit_cnt;
+	u32 value, offset, i;
 
 #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000
 #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000
@@ -392,55 +389,35 @@
     */
 	if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR))
 		return;
-	/* set SSC bit of PHY 0 - 3 */
+
 	for (i = 0; i < 4; i++) {
 		offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i;
-		value = pm8001_cr32(pm8001_ha, 2, offset);
-		if (SSCbit) {
-			value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
-			value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
-		} else {
-			value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
-			value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
-		}
-		bit_cnt = 0;
-		for (j = 0; j < 31; j++)
-			if ((value >> j) & 0x00000001)
-				bit_cnt++;
-		if (bit_cnt % 2)
-			value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
-		else
-			value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
-
-		pm8001_cw32(pm8001_ha, 2, offset, value);
+		pm8001_cw32(pm8001_ha, 2, offset, 0x80001501);
 	}
-
 	/* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */
 	if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR))
 		return;
-
-	/* set SSC bit of PHY 4 - 7 */
 	for (i = 4; i < 8; i++) {
 		offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4);
-		value = pm8001_cr32(pm8001_ha, 2, offset);
-		if (SSCbit) {
-			value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
-			value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
-		} else {
-			value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
-			value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
-		}
-		bit_cnt = 0;
-		for (j = 0; j < 31; j++)
-			if ((value >> j) & 0x00000001)
-				bit_cnt++;
-		if (bit_cnt % 2)
-			value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
-		else
-			value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
-
-		pm8001_cw32(pm8001_ha, 2, offset, value);
+		pm8001_cw32(pm8001_ha, 2, offset, 0x80001501);
 	}
+	/*************************************************************
+	Change the SSC upspreading value to 0x0 so that upspreading is disabled.
+	Device MABC SMOD0 Controls
+	Address: (via MEMBASE-III):
+	Using shifted destination address 0x0_0000: with Offset 0xD8
+
+	31:28 R/W Reserved Do not change
+	27:24 R/W SAS_SMOD_SPRDUP 0000
+	23:20 R/W SAS_SMOD_SPRDDN 0000
+	19:0  R/W  Reserved Do not change
+	Upon power-up this register will read as 0x8990c016,
+	and I would like you to change the SAS_SMOD_SPRDUP bits to 0b0000
+	so that the written value will be 0x8090c016.
+	This will ensure only down-spreading SSC is enabled on the SPC.
+	*************************************************************/
+	value = pm8001_cr32(pm8001_ha, 2, 0xd8);
+	pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016);
 
 	/*set the shifted destination address to 0x0 to avoid error operation */
 	bar4_shift(pm8001_ha, 0x0);
@@ -1901,7 +1878,7 @@
 {
 	struct sas_task *t;
 	struct pm8001_ccb_info *ccb;
-	unsigned long flags;
+	unsigned long flags = 0;
 	u32 param;
 	u32 status;
 	u32 tag;
@@ -2040,7 +2017,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/*in order to force CPU ordering*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2058,7 +2037,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/*ditto*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2084,7 +2065,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/* ditto*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2149,7 +2132,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/*ditto*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2171,7 +2156,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/*ditto*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2200,11 +2187,20 @@
 			" resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			t, status, ts->resp, ts->stat));
 		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-	} else {
+	} else if (t->uldd_task) {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 		mb();/* ditto */
+		spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 		t->task_done(t);
+		spin_lock_irqsave(&pm8001_ha->lock, flags);
+	} else if (!t->uldd_task) {
+		spin_unlock_irqrestore(&t->task_state_lock, flags);
+		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		mb();/*ditto*/
+		spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+		t->task_done(t);
+		spin_lock_irqsave(&pm8001_ha->lock, flags);
 	}
 }
 
@@ -2212,7 +2208,7 @@
 static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
 {
 	struct sas_task *t;
-	unsigned long flags;
+	unsigned long flags = 0;
 	struct task_status_struct *ts;
 	struct pm8001_ccb_info *ccb;
 	struct pm8001_device *pm8001_dev;
@@ -2292,7 +2288,9 @@
 			ts->stat = SAS_QUEUE_FULL;
 			pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
 			mb();/*ditto*/
+			spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 			t->task_done(t);
+			spin_lock_irqsave(&pm8001_ha->lock, flags);
 			return;
 		}
 		break;
@@ -2401,11 +2399,20 @@
 			" resp 0x%x stat 0x%x but aborted by upper layer!\n",
 			t, event, ts->resp, ts->stat));
 		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-	} else {
+	} else if (t->uldd_task) {
 		spin_unlock_irqrestore(&t->task_state_lock, flags);
 		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-		mb();/* in order to force CPU ordering */
+		mb();/* ditto */
+		spin_unlock_irqrestore(&pm8001_ha->lock, flags);
 		t->task_done(t);
+		spin_lock_irqsave(&pm8001_ha->lock, flags);
+	} else if (!t->uldd_task) {
+		spin_unlock_irqrestore(&t->task_state_lock, flags);
+		pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
+		mb();/*ditto*/
+		spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+		t->task_done(t);
+		spin_lock_irqsave(&pm8001_ha->lock, flags);
 	}
 }
 
@@ -2876,15 +2883,20 @@
 		le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
 	u8 link_rate =
 		(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
+	u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
 	u8 phy_id =
 		(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
+	u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
+	u8 portstate = (u8)(npip_portstate & 0x0000000F);
+	struct pm8001_port *port = &pm8001_ha->port[port_id];
 	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	unsigned long flags;
 	u8 deviceType = pPayload->sas_identify.dev_type;
-
+	port->port_state =  portstate;
 	PM8001_MSG_DBG(pm8001_ha,
-		pm8001_printk("HW_EVENT_SAS_PHY_UP \n"));
+		pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n",
+		port_id, phy_id));
 
 	switch (deviceType) {
 	case SAS_PHY_UNUSED:
@@ -2895,16 +2907,19 @@
 		PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n"));
 		pm8001_chip_phy_ctl_req(pm8001_ha, phy_id,
 			PHY_NOTIFY_ENABLE_SPINUP);
+		port->port_attached = 1;
 		get_lrate_mode(phy, link_rate);
 		break;
 	case SAS_EDGE_EXPANDER_DEVICE:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk("expander device.\n"));
+		port->port_attached = 1;
 		get_lrate_mode(phy, link_rate);
 		break;
 	case SAS_FANOUT_EXPANDER_DEVICE:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk("fanout expander device.\n"));
+		port->port_attached = 1;
 		get_lrate_mode(phy, link_rate);
 		break;
 	default:
@@ -2946,11 +2961,20 @@
 		le32_to_cpu(pPayload->lr_evt_status_phyid_portid);
 	u8 link_rate =
 		(u8)((lr_evt_status_phyid_portid & 0xF0000000) >> 28);
+	u8 port_id = (u8)(lr_evt_status_phyid_portid & 0x0000000F);
 	u8 phy_id =
 		(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
+	u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
+	u8 portstate = (u8)(npip_portstate & 0x0000000F);
+	struct pm8001_port *port = &pm8001_ha->port[port_id];
 	struct sas_ha_struct *sas_ha = pm8001_ha->sas;
 	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
 	unsigned long flags;
+	PM8001_MSG_DBG(pm8001_ha,
+		pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d,"
+		" phy id = %d\n", port_id, phy_id));
+	port->port_state =  portstate;
+	port->port_attached = 1;
 	get_lrate_mode(phy, link_rate);
 	phy->phy_type |= PORT_TYPE_SATA;
 	phy->phy_attached = 1;
@@ -2984,7 +3008,13 @@
 		(u8)((lr_evt_status_phyid_portid & 0x000000F0) >> 4);
 	u32 npip_portstate = le32_to_cpu(pPayload->npip_portstate);
 	u8 portstate = (u8)(npip_portstate & 0x0000000F);
-
+	struct pm8001_port *port = &pm8001_ha->port[port_id];
+	struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+	port->port_state =  portstate;
+	phy->phy_type = 0;
+	phy->identify.device_type = 0;
+	phy->phy_attached = 0;
+	memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE);
 	switch (portstate) {
 	case PORT_VALID:
 		break;
@@ -2993,26 +3023,30 @@
 			pm8001_printk(" PortInvalid portID %d \n", port_id));
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" Last phy Down and port invalid\n"));
+		port->port_attached = 0;
 		pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
 			port_id, phy_id, 0, 0);
 		break;
 	case PORT_IN_RESET:
 		PM8001_MSG_DBG(pm8001_ha,
-			pm8001_printk(" PortInReset portID %d \n", port_id));
+			pm8001_printk(" Port In Reset portID %d \n", port_id));
 		break;
 	case PORT_NOT_ESTABLISHED:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n"));
+		port->port_attached = 0;
 		break;
 	case PORT_LOSTCOMM:
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" phy Down and PORT_LOSTCOMM\n"));
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" Last phy Down and port invalid\n"));
+		port->port_attached = 0;
 		pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN,
 			port_id, phy_id, 0, 0);
 		break;
 	default:
+		port->port_attached = 0;
 		PM8001_MSG_DBG(pm8001_ha,
 			pm8001_printk(" phy Down and(default) = %x\n",
 			portstate));
@@ -3770,7 +3804,8 @@
 	u32 opc = OPC_INB_SSPINIIOSTART;
 	memset(&ssp_cmd, 0, sizeof(ssp_cmd));
 	memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8);
-	ssp_cmd.dir_m_tlr = data_dir_flags[task->data_dir] << 8 | 0x0;/*0 for
+	ssp_cmd.dir_m_tlr =
+		cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0);/*0 for
 	SAS 1.1 compatible TLR*/
 	ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len);
 	ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id);
@@ -3841,7 +3876,7 @@
 		}
 	}
 	if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag))
-		ncg_tag = cpu_to_le32(hdr_tag);
+		ncg_tag = hdr_tag;
 	dir = data_dir_flags[task->data_dir] << 8;
 	sata_cmd.tag = cpu_to_le32(tag);
 	sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id);
@@ -3986,7 +4021,7 @@
 		((stp_sspsmp_sata & 0x03) * 0x10000000));
 	payload.firstburstsize_ITNexustimeout =
 		cpu_to_le32(ITNT | (firstBurstSize * 0x10000));
-	memcpy(&payload.sas_addr_hi, pm8001_dev->sas_device->sas_addr,
+	memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr,
 		SAS_ADDR_SIZE);
 	rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
 	return rc;
@@ -4027,7 +4062,7 @@
 	struct inbound_queue_table *circularQ;
 	int ret;
 	u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
-	memset((u8 *)&payload, 0, sizeof(payload));
+	memset(&payload, 0, sizeof(payload));
 	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 	payload.tag = 1;
 	payload.phyop_phyid =
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 96e4daa..833a520 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -242,8 +242,7 @@
 	__le32	phyid_portid;
 	__le32	dtype_dlr_retry;
 	__le32	firstburstsize_ITNexustimeout;
-	u32	sas_addr_hi;
-	u32	sas_addr_low;
+	u8	sas_addr[SAS_ADDR_SIZE];
 	__le32	upper_device_id;
 	u32	reserved[8];
 } __attribute__((packed, aligned(4)));
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index 42ebe72..c2f1032 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -200,8 +200,13 @@
 {
 	int i;
 	spin_lock_init(&pm8001_ha->lock);
-	for (i = 0; i < pm8001_ha->chip->n_phy; i++)
+	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
 		pm8001_phy_init(pm8001_ha, i);
+		pm8001_ha->port[i].wide_port_phymap = 0;
+		pm8001_ha->port[i].port_attached = 0;
+		pm8001_ha->port[i].port_state = 0;
+		INIT_LIST_HEAD(&pm8001_ha->port[i].list);
+	}
 
 	pm8001_ha->tags = kzalloc(PM8001_MAX_CCB, GFP_KERNEL);
 	if (!pm8001_ha->tags)
@@ -511,19 +516,23 @@
 	u8 i;
 #ifdef PM8001_READ_VPD
 	DECLARE_COMPLETION_ONSTACK(completion);
+	struct pm8001_ioctl_payload payload;
 	pm8001_ha->nvmd_completion = &completion;
-	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, 0, 0);
+	payload.minor_function = 0;
+	payload.length = 128;
+	payload.func_specific = kzalloc(128, GFP_KERNEL);
+	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
 	wait_for_completion(&completion);
 	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
 		memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr,
 			SAS_ADDR_SIZE);
 		PM8001_INIT_DBG(pm8001_ha,
-			pm8001_printk("phy %d sas_addr = %x \n", i,
-			(u64)pm8001_ha->phy[i].dev_sas_addr));
+			pm8001_printk("phy %d sas_addr = %016llx \n", i,
+			pm8001_ha->phy[i].dev_sas_addr));
 	}
 #else
 	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
-		pm8001_ha->phy[i].dev_sas_addr = 0x500e004010000004ULL;
+		pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL;
 		pm8001_ha->phy[i].dev_sas_addr =
 			cpu_to_be64((u64)
 				(*(u64 *)&pm8001_ha->phy[i].dev_sas_addr));
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 1f767a0..7f9c83a 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -329,6 +329,23 @@
 	}
 	return 0;
 }
+ /* Find the local port id that's attached to this device */
+static int sas_find_local_port_id(struct domain_device *dev)
+{
+	struct domain_device *pdev = dev->parent;
+
+	/* Directly attached device */
+	if (!pdev)
+		return dev->port->id;
+	while (pdev) {
+		struct domain_device *pdev_p = pdev->parent;
+		if (!pdev_p)
+			return pdev->port->id;
+		pdev = pdev->parent;
+	}
+	return 0;
+}
+
 /**
   * pm8001_task_exec - queue the task(ssp, smp && ata) to the hardware.
   * @task: the task to be execute.
@@ -346,11 +363,12 @@
 	struct domain_device *dev = task->dev;
 	struct pm8001_hba_info *pm8001_ha;
 	struct pm8001_device *pm8001_dev;
+	struct pm8001_port *port = NULL;
 	struct sas_task *t = task;
 	struct pm8001_ccb_info *ccb;
 	u32 tag = 0xdeadbeef, rc, n_elem = 0;
 	u32 n = num;
-	unsigned long flags = 0;
+	unsigned long flags = 0, flags_libsas = 0;
 
 	if (!dev->port) {
 		struct task_status_struct *tsm = &t->task_status;
@@ -379,6 +397,35 @@
 			rc = SAS_PHY_DOWN;
 			goto out_done;
 		}
+		port = &pm8001_ha->port[sas_find_local_port_id(dev)];
+		if (!port->port_attached) {
+			if (sas_protocol_ata(t->task_proto)) {
+				struct task_status_struct *ts = &t->task_status;
+				ts->resp = SAS_TASK_UNDELIVERED;
+				ts->stat = SAS_PHY_DOWN;
+
+				spin_unlock_irqrestore(&pm8001_ha->lock, flags);
+				spin_unlock_irqrestore(dev->sata_dev.ap->lock,
+						flags_libsas);
+				t->task_done(t);
+				spin_lock_irqsave(dev->sata_dev.ap->lock,
+					flags_libsas);
+				spin_lock_irqsave(&pm8001_ha->lock, flags);
+				if (n > 1)
+					t = list_entry(t->list.next,
+							struct sas_task, list);
+				continue;
+			} else {
+				struct task_status_struct *ts = &t->task_status;
+				ts->resp = SAS_TASK_UNDELIVERED;
+				ts->stat = SAS_PHY_DOWN;
+				t->task_done(t);
+				if (n > 1)
+					t = list_entry(t->list.next,
+							struct sas_task, list);
+				continue;
+			}
+		}
 		rc = pm8001_tag_alloc(pm8001_ha, &tag);
 		if (rc)
 			goto err_out;
@@ -569,11 +616,11 @@
 	spin_lock_irqsave(&pm8001_ha->lock, flags);
 
 	pm8001_device = pm8001_alloc_dev(pm8001_ha);
-	pm8001_device->sas_device = dev;
 	if (!pm8001_device) {
 		res = -1;
 		goto found_out;
 	}
+	pm8001_device->sas_device = dev;
 	dev->lldd_dev = pm8001_device;
 	pm8001_device->dev_type = dev->dev_type;
 	pm8001_device->dcompletion = &completion;
@@ -609,7 +656,7 @@
 	wait_for_completion(&completion);
 	if (dev->dev_type == SAS_END_DEV)
 		msleep(50);
-	pm8001_ha->flags = PM8001F_RUN_TIME ;
+	pm8001_ha->flags |= PM8001F_RUN_TIME ;
 	return 0;
 found_out:
 	spin_unlock_irqrestore(&pm8001_ha->lock, flags);
@@ -772,7 +819,7 @@
 		task->task_done = pm8001_task_done;
 		task->timer.data = (unsigned long)task;
 		task->timer.function = pm8001_tmf_timedout;
-		task->timer.expires = jiffies + PM8001_TASK_TIMEOUT*HZ;
+		task->timer.expires = jiffies + PM8001_TASK_TIMEOUT * HZ;
 		add_timer(&task->timer);
 
 		res = pm8001_tag_alloc(pm8001_ha, &ccb_tag);
@@ -897,6 +944,8 @@
 
 	if (dev_is_sata(dev)) {
 		DECLARE_COMPLETION_ONSTACK(completion_setstate);
+		if (scsi_is_sas_phy_local(phy))
+			return 0;
 		rc = sas_phy_reset(phy, 1);
 		msleep(2000);
 		rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 30f2ede..8e38ca8 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -59,11 +59,11 @@
 
 #define DRV_NAME		"pm8001"
 #define DRV_VERSION		"0.1.36"
-#define PM8001_FAIL_LOGGING	0x01 /* libsas EH function logging */
+#define PM8001_FAIL_LOGGING	0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING	0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING	0x04 /* discovery layer logging */
 #define PM8001_IO_LOGGING	0x08 /* I/O path logging */
-#define PM8001_EH_LOGGING	0x10 /* Error message logging */
+#define PM8001_EH_LOGGING	0x10 /* libsas EH function logging*/
 #define PM8001_IOCTL_LOGGING	0x20 /* IOCTL message logging */
 #define PM8001_MSG_LOGGING	0x40 /* misc message logging */
 #define pm8001_printk(format, arg...)	printk(KERN_INFO "%s %d:" format,\
@@ -100,6 +100,7 @@
 
 #define PM8001_USE_TASKLET
 #define PM8001_USE_MSIX
+#define PM8001_READ_VPD
 
 
 #define DEV_IS_EXPANDER(type)	((type == EDGE_DEV) || (type == FANOUT_DEV))
@@ -111,7 +112,22 @@
 struct pm8001_hba_info;
 struct pm8001_ccb_info;
 struct pm8001_device;
-struct pm8001_tmf_task;
+/* define task management IU */
+struct pm8001_tmf_task {
+	u8	tmf;
+	u32	tag_of_task_to_be_managed;
+};
+struct pm8001_ioctl_payload {
+	u32	signature;
+	u16	major_function;
+	u16	minor_function;
+	u16	length;
+	u16	status;
+	u16	offset;
+	u16	id;
+	u8	*func_specific;
+};
+
 struct pm8001_dispatch {
 	char *name;
 	int (*chip_init)(struct pm8001_hba_info *pm8001_ha);
@@ -164,6 +180,10 @@
 
 struct pm8001_port {
 	struct asd_sas_port	sas_port;
+	u8			port_attached;
+	u8			wide_port_phymap;
+	u8			port_state;
+	struct list_head	list;
 };
 
 struct pm8001_phy {
@@ -386,11 +406,7 @@
 	__be32 startup_entry;
 } __attribute__((packed, aligned(4)));
 
-/* define task management IU */
-struct pm8001_tmf_task {
-	u8	tmf;
-	u32	tag_of_task_to_be_managed;
-};
+
 /**
  * FW Flash Update status values
  */
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 34c6b89..e7d2688 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -1,7 +1,8 @@
 /*
  * pmcraid.c -- driver for PMC Sierra MaxRAID controller adapters
  *
- * Written By: PMC Sierra Corporation
+ * Written By: Anil Ravindranath<anil_ravindranath@pmc-sierra.com>
+ *             PMC-Sierra Inc
  *
  * Copyright (C) 2008, 2009 PMC Sierra Inc
  *
@@ -79,7 +80,7 @@
 /*
  * Module parameters
  */
-MODULE_AUTHOR("PMC Sierra Corporation, anil_ravindranath@pmc-sierra.com");
+MODULE_AUTHOR("Anil Ravindranath<anil_ravindranath@pmc-sierra.com>");
 MODULE_DESCRIPTION("PMC Sierra MaxRAID Controller Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(PMCRAID_DRIVER_VERSION);
@@ -162,10 +163,10 @@
 	spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
 	list_for_each_entry(temp, &pinstance->used_res_q, queue) {
 
-		/* do not expose VSETs with order-ids >= 240 */
+		/* do not expose VSETs with order-ids > MAX_VSET_TARGETS */
 		if (RES_IS_VSET(temp->cfg_entry)) {
 			target = temp->cfg_entry.unique_flags1;
-			if (target >= PMCRAID_MAX_VSET_TARGETS)
+			if (target > PMCRAID_MAX_VSET_TARGETS)
 				continue;
 			bus = PMCRAID_VSET_BUS_ID;
 			lun = 0;
@@ -1210,7 +1211,7 @@
 	int retval = 0;
 
 	if (cfgte->resource_type == RES_TYPE_VSET)
-		retval = ((cfgte->unique_flags1 & 0xFF) < 0xFE);
+		retval = ((cfgte->unique_flags1 & 0x80) == 0);
 	else if (cfgte->resource_type == RES_TYPE_GSCSI)
 		retval = (RES_BUS(cfgte->resource_address) !=
 				PMCRAID_VIRTUAL_ENCL_BUS_ID);
@@ -1361,6 +1362,7 @@
  * Return value:
  *  none
  */
+
 static void pmcraid_handle_config_change(struct pmcraid_instance *pinstance)
 {
 	struct pmcraid_config_table_entry *cfg_entry;
@@ -1368,9 +1370,10 @@
 	struct pmcraid_cmd *cmd;
 	struct pmcraid_cmd *cfgcmd;
 	struct pmcraid_resource_entry *res = NULL;
-	u32 new_entry = 1;
 	unsigned long lock_flags;
 	unsigned long host_lock_flags;
+	u32 new_entry = 1;
+	u32 hidden_entry = 0;
 	int rc;
 
 	ccn_hcam = (struct pmcraid_hcam_ccn *)pinstance->ccn.hcam;
@@ -1406,9 +1409,15 @@
 	}
 
 	/* If this resource is not going to be added to mid-layer, just notify
-	 * applications and return
+	 * applications and return. If this notification is about hiding a VSET
+	 * resource, check if it was exposed already.
 	 */
-	if (!pmcraid_expose_resource(cfg_entry))
+	if (pinstance->ccn.hcam->notification_type ==
+	    NOTIFICATION_TYPE_ENTRY_CHANGED &&
+	    cfg_entry->resource_type == RES_TYPE_VSET &&
+	    cfg_entry->unique_flags1 & 0x80) {
+		hidden_entry = 1;
+	} else if (!pmcraid_expose_resource(cfg_entry))
 		goto out_notify_apps;
 
 	spin_lock_irqsave(&pinstance->resource_lock, lock_flags);
@@ -1424,6 +1433,12 @@
 
 	if (new_entry) {
 
+		if (hidden_entry) {
+			spin_unlock_irqrestore(&pinstance->resource_lock,
+						lock_flags);
+			goto out_notify_apps;
+		}
+
 		/* If there are more number of resources than what driver can
 		 * manage, do not notify the applications about the CCN. Just
 		 * ignore this notifications and re-register the same HCAM
@@ -1454,8 +1469,9 @@
 		sizeof(struct pmcraid_config_table_entry));
 
 	if (pinstance->ccn.hcam->notification_type ==
-	    NOTIFICATION_TYPE_ENTRY_DELETED) {
+	    NOTIFICATION_TYPE_ENTRY_DELETED || hidden_entry) {
 		if (res->scsi_dev) {
+			res->cfg_entry.unique_flags1 &= 0x7F;
 			res->change_detected = RES_CHANGE_DEL;
 			res->cfg_entry.resource_handle =
 				PMCRAID_INVALID_RES_HANDLE;
diff --git a/drivers/scsi/pmcraid.h b/drivers/scsi/pmcraid.h
index 2752b56..92f89d5 100644
--- a/drivers/scsi/pmcraid.h
+++ b/drivers/scsi/pmcraid.h
@@ -1,6 +1,9 @@
 /*
  * pmcraid.h -- PMC Sierra MaxRAID controller driver header file
  *
+ * Written By: Anil Ravindranath<anil_ravindranath@pmc-sierra.com>
+ *             PMC-Sierra Inc
+ *
  * Copyright (C) 2008, 2009 PMC Sierra Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -106,7 +109,7 @@
 #define PMCRAID_VSET_LUN_ID                      0x0
 #define PMCRAID_PHYS_BUS_ID                      0x0
 #define PMCRAID_VIRTUAL_ENCL_BUS_ID              0x8
-#define PMCRAID_MAX_VSET_TARGETS                 240
+#define PMCRAID_MAX_VSET_TARGETS                 0x7F
 #define PMCRAID_MAX_VSET_LUNS_PER_TARGET         8
 
 #define PMCRAID_IOA_MAX_SECTORS                  32767
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 6b9bf23..384afda 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1570,9 +1570,6 @@
 	struct fc_rport *rport, *drport;
 	u32 supported_classes;
 
-	unsigned long last_queue_full;
-	unsigned long last_ramp_up;
-
 	uint16_t vp_idx;
 } fc_port_t;
 
@@ -2265,6 +2262,7 @@
 		uint32_t	port0			:1;
 		uint32_t	running_gold_fw		:1;
 		uint32_t	cpu_affinity_enabled	:1;
+		uint32_t	disable_msix_handshake	:1;
 	} flags;
 
 	/* This spinlock is used to protect "io transactions", you must
@@ -2387,6 +2385,7 @@
 #define IS_QLA81XX(ha)		(IS_QLA8001(ha))
 #define IS_QLA2XXX_MIDTYPE(ha)	(IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
 				IS_QLA25XX(ha) || IS_QLA81XX(ha))
+#define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha))
 #define IS_NOPOLLING_TYPE(ha)	((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
 				(ha)->flags.msix_enabled)
 #define IS_FAC_REQUIRED(ha)	(IS_QLA81XX(ha))
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e218513..0b6801f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -72,8 +72,6 @@
 extern int ql2xfdmienable;
 extern int ql2xallocfwdump;
 extern int ql2xextended_error_logging;
-extern int ql2xqfullrampup;
-extern int ql2xqfulltracking;
 extern int ql2xiidmaenable;
 extern int ql2xmaxqueues;
 extern int ql2xmultique_tag;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index b74924b..73a7935 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1442,7 +1442,17 @@
 			icb->firmware_options_2 |=
 				__constant_cpu_to_le32(BIT_18);
 
-		icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22);
+		/* Use Disable MSIX Handshake mode for capable adapters */
+		if (IS_MSIX_NACK_CAPABLE(ha)) {
+			icb->firmware_options_2 &=
+				__constant_cpu_to_le32(~BIT_22);
+			ha->flags.disable_msix_handshake = 1;
+			qla_printk(KERN_INFO, ha,
+				"MSIX Handshake Disable Mode turned on\n");
+		} else {
+			icb->firmware_options_2 |=
+				__constant_cpu_to_le32(BIT_22);
+		}
 		icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23);
 
 		WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 8049873..1692a88 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -811,78 +811,6 @@
 		qla2x00_alert_all_vps(rsp, mb);
 }
 
-static void
-qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data)
-{
-	fc_port_t *fcport = data;
-	struct scsi_qla_host *vha = fcport->vha;
-	struct qla_hw_data *ha = vha->hw;
-	struct req_que *req = NULL;
-
-	if (!ql2xqfulltracking)
-		return;
-
-	req = vha->req;
-	if (!req)
-		return;
-	if (req->max_q_depth <= sdev->queue_depth)
-		return;
-
-	if (sdev->ordered_tags)
-		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
-		    sdev->queue_depth + 1);
-	else
-		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG,
-		    sdev->queue_depth + 1);
-
-	fcport->last_ramp_up = jiffies;
-
-	DEBUG2(qla_printk(KERN_INFO, ha,
-	    "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
-	    fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-	    sdev->queue_depth));
-}
-
-static void
-qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data)
-{
-	fc_port_t *fcport = data;
-
-	if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1))
-		return;
-
-	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
-	    "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
-	    fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
-	    sdev->queue_depth));
-}
-
-static inline void
-qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req,
-								srb_t *sp)
-{
-	fc_port_t *fcport;
-	struct scsi_device *sdev;
-
-	if (!ql2xqfulltracking)
-		return;
-
-	sdev = sp->cmd->device;
-	if (sdev->queue_depth >= req->max_q_depth)
-		return;
-
-	fcport = sp->fcport;
-	if (time_before(jiffies,
-	    fcport->last_ramp_up + ql2xqfullrampup * HZ))
-		return;
-	if (time_before(jiffies,
-	    fcport->last_queue_full + ql2xqfullrampup * HZ))
-		return;
-
-	starget_for_each_device(sdev->sdev_target, fcport,
-	    qla2x00_adjust_sdev_qdepth_up);
-}
-
 /**
  * qla2x00_process_completed_request() - Process a Fast Post response.
  * @ha: SCSI driver HA context
@@ -913,8 +841,6 @@
 
 		/* Save ISP completion status */
 		sp->cmd->result = DID_OK << 16;
-
-		qla2x00_ramp_up_queue_depth(vha, req, sp);
 		qla2x00_sp_compl(ha, sp);
 	} else {
 		DEBUG2(printk("scsi(%ld) Req:%d: Invalid ISP SCSI completion"
@@ -1435,13 +1361,6 @@
 			    "scsi(%ld): QUEUE FULL status detected "
 			    "0x%x-0x%x.\n", vha->host_no, comp_status,
 			    scsi_status));
-
-			/* Adjust queue depth for all luns on the port. */
-			if (!ql2xqfulltracking)
-				break;
-			fcport->last_queue_full = jiffies;
-			starget_for_each_device(cp->device->sdev_target,
-			    fcport, qla2x00_adjust_sdev_qdepth_down);
 			break;
 		}
 		if (lscsi_status != SS_CHECK_CONDITION)
@@ -1516,17 +1435,6 @@
 				    "scsi(%ld): QUEUE FULL status detected "
 				    "0x%x-0x%x.\n", vha->host_no, comp_status,
 				    scsi_status));
-
-				/*
-				 * Adjust queue depth for all luns on the
-				 * port.
-				 */
-				if (!ql2xqfulltracking)
-					break;
-				fcport->last_queue_full = jiffies;
-				starget_for_each_device(
-				    cp->device->sdev_target, fcport,
-				    qla2x00_adjust_sdev_qdepth_down);
 				break;
 			}
 			if (lscsi_status != SS_CHECK_CONDITION)
@@ -2020,7 +1928,7 @@
 
 	vha = qla25xx_get_host(rsp);
 	qla24xx_process_response_queue(vha, rsp);
-	if (!ha->mqenable) {
+	if (!ha->flags.disable_msix_handshake) {
 		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
 		RD_REG_DWORD_RELAXED(&reg->hccr);
 	}
@@ -2034,6 +1942,7 @@
 {
 	struct qla_hw_data *ha;
 	struct rsp_que *rsp;
+	struct device_reg_24xx __iomem *reg;
 
 	rsp = (struct rsp_que *) dev_id;
 	if (!rsp) {
@@ -2043,6 +1952,14 @@
 	}
 	ha = rsp->hw;
 
+	/* Clear the interrupt, if enabled, for this response queue */
+	if (rsp->options & ~BIT_6) {
+		reg = &ha->iobase->isp24;
+		spin_lock_irq(&ha->hardware_lock);
+		WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+		RD_REG_DWORD_RELAXED(&reg->hccr);
+		spin_unlock_irq(&ha->hardware_lock);
+	}
 	queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work);
 
 	return IRQ_HANDLED;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index a47d343..2a4c7f4 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -696,6 +696,10 @@
 	/* Use alternate PCI devfn */
 	if (LSB(rsp->rid))
 		options |= BIT_5;
+	/* Enable MSIX handshake mode on for uncapable adapters */
+	if (!IS_MSIX_NACK_CAPABLE(ha))
+		options |= BIT_6;
+
 	rsp->options = options;
 	rsp->id = que_id;
 	reg = ISP_QUE_REG(ha, que_id);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4166935..2f873d2 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -78,21 +78,6 @@
 MODULE_PARM_DESC(ql2xmaxqdepth,
 		"Maximum queue depth to report for target devices.");
 
-int ql2xqfulltracking = 1;
-module_param(ql2xqfulltracking, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xqfulltracking,
-		"Controls whether the driver tracks queue full status "
-		"returns and dynamically adjusts a scsi device's queue "
-		"depth.  Default is 1, perform tracking.  Set to 0 to "
-		"disable dynamic tracking and adjustment of queue depth.");
-
-int ql2xqfullrampup = 120;
-module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xqfullrampup,
-		"Number of seconds to wait to begin to ramp-up the queue "
-		"depth for a device after a queue-full condition has been "
-		"detected.  Default is 120 seconds.");
-
 int ql2xiidmaenable=1;
 module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xiidmaenable,
@@ -1217,13 +1202,61 @@
 	sdev->hostdata = NULL;
 }
 
+static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth)
+{
+	fc_port_t *fcport = (struct fc_port *) sdev->hostdata;
+
+	if (!scsi_track_queue_full(sdev, qdepth))
+		return;
+
+	DEBUG2(qla_printk(KERN_INFO, fcport->vha->hw,
+		"scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n",
+		fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
+		sdev->queue_depth));
+}
+
+static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth)
+{
+	fc_port_t *fcport = sdev->hostdata;
+	struct scsi_qla_host *vha = fcport->vha;
+	struct qla_hw_data *ha = vha->hw;
+	struct req_que *req = NULL;
+
+	req = vha->req;
+	if (!req)
+		return;
+
+	if (req->max_q_depth <= sdev->queue_depth || req->max_q_depth < qdepth)
+		return;
+
+	if (sdev->ordered_tags)
+		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, qdepth);
+	else
+		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth);
+
+	DEBUG2(qla_printk(KERN_INFO, ha,
+	       "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n",
+	       fcport->vha->host_no, sdev->channel, sdev->id, sdev->lun,
+	       sdev->queue_depth));
+}
+
 static int
 qla2x00_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason)
 {
-	if (reason != SCSI_QDEPTH_DEFAULT)
-		return -EOPNOTSUPP;
+	switch (reason) {
+	case SCSI_QDEPTH_DEFAULT:
+		scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
+		break;
+	case SCSI_QDEPTH_QFULL:
+		qla2x00_handle_queue_full(sdev, qdepth);
+		break;
+	case SCSI_QDEPTH_RAMP_UP:
+		qla2x00_adjust_sdev_qdepth_up(sdev, qdepth);
+		break;
+	default:
+		return EOPNOTSUPP;
+	}
 
-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth);
 	return sdev->queue_depth;
 }
 
@@ -2003,13 +2036,13 @@
 	DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
 	    base_vha->host_no, ha));
 
-	base_vha->flags.init_done = 1;
-	base_vha->flags.online = 1;
-
 	ret = scsi_add_host(host, &pdev->dev);
 	if (ret)
 		goto probe_failed;
 
+	base_vha->flags.init_done = 1;
+	base_vha->flags.online = 1;
+
 	ha->isp_ops->enable_intrs(ha);
 
 	scsi_scan_host(host);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 807e0db..c482220 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.01-k7"
+#define QLA2XXX_VERSION      "8.03.01-k8"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	3
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e495d38..d892768 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -859,6 +859,7 @@
 				case 0x07: /* operation in progress */
 				case 0x08: /* Long write in progress */
 				case 0x09: /* self test in progress */
+				case 0x14: /* space allocation in progress */
 					action = ACTION_DELAYED_RETRY;
 					break;
 				default:
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 6531c91..ddfcecd 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -649,11 +649,22 @@
 		return error;
 	error = transport_class_register(&fc_vport_class);
 	if (error)
-		return error;
+		goto unreg_host_class;
 	error = transport_class_register(&fc_rport_class);
 	if (error)
-		return error;
-	return transport_class_register(&fc_transport_class);
+		goto unreg_vport_class;
+	error = transport_class_register(&fc_transport_class);
+	if (error)
+		goto unreg_rport_class;
+	return 0;
+
+unreg_rport_class:
+	transport_class_unregister(&fc_rport_class);
+unreg_vport_class:
+	transport_class_unregister(&fc_vport_class);
+unreg_host_class:
+	transport_class_unregister(&fc_host_class);
+	return error;
 }
 
 static void __exit fc_transport_exit(void)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 9093c72..255da53 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -264,6 +264,15 @@
 	return snprintf(buf, 20, "%u\n", sdkp->ATO);
 }
 
+static ssize_t
+sd_show_thin_provisioning(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+	return snprintf(buf, 20, "%u\n", sdkp->thin_provisioning);
+}
+
 static struct device_attribute sd_disk_attrs[] = {
 	__ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
 	       sd_store_cache_type),
@@ -274,6 +283,7 @@
 	       sd_store_manage_start_stop),
 	__ATTR(protection_type, S_IRUGO, sd_show_protection_type, NULL),
 	__ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
+	__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
 	__ATTR_NULL,
 };
 
@@ -399,6 +409,57 @@
 }
 
 /**
+ * sd_prepare_discard - unmap blocks on thinly provisioned device
+ * @rq: Request to prepare
+ *
+ * Will issue either UNMAP or WRITE SAME(16) depending on preference
+ * indicated by target device.
+ **/
+static int sd_prepare_discard(struct request *rq)
+{
+	struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+	struct bio *bio = rq->bio;
+	sector_t sector = bio->bi_sector;
+	unsigned int num = bio_sectors(bio);
+
+	if (sdkp->device->sector_size == 4096) {
+		sector >>= 3;
+		num >>= 3;
+	}
+
+	rq->cmd_type = REQ_TYPE_BLOCK_PC;
+	rq->timeout = SD_TIMEOUT;
+
+	memset(rq->cmd, 0, rq->cmd_len);
+
+	if (sdkp->unmap) {
+		char *buf = kmap_atomic(bio_page(bio), KM_USER0);
+
+		rq->cmd[0] = UNMAP;
+		rq->cmd[8] = 24;
+		rq->cmd_len = 10;
+
+		/* Ensure that data length matches payload */
+		rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24;
+
+		put_unaligned_be16(6 + 16, &buf[0]);
+		put_unaligned_be16(16, &buf[2]);
+		put_unaligned_be64(sector, &buf[8]);
+		put_unaligned_be32(num, &buf[16]);
+
+		kunmap_atomic(buf, KM_USER0);
+	} else {
+		rq->cmd[0] = WRITE_SAME_16;
+		rq->cmd[1] = 0x8; /* UNMAP */
+		put_unaligned_be64(sector, &rq->cmd[2]);
+		put_unaligned_be32(num, &rq->cmd[10]);
+		rq->cmd_len = 16;
+	}
+
+	return BLKPREP_OK;
+}
+
+/**
  *	sd_init_command - build a scsi (read or write) command from
  *	information in the request structure.
  *	@SCpnt: pointer to mid-level's per scsi command structure that
@@ -418,6 +479,13 @@
 	int ret, host_dif;
 	unsigned char protect;
 
+	/*
+	 * Discard request come in as REQ_TYPE_FS but we turn them into
+	 * block PC requests to make life easier.
+	 */
+	if (blk_discard_rq(rq))
+		ret = sd_prepare_discard(rq);
+
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
 		ret = scsi_setup_blk_pc_cmnd(sdp, rq);
 		goto out;
@@ -1432,6 +1500,19 @@
 		sd_printk(KERN_NOTICE, sdkp,
 			  "physical block alignment offset: %u\n", alignment);
 
+	if (buffer[14] & 0x80) { /* TPE */
+		struct request_queue *q = sdp->request_queue;
+
+		sdkp->thin_provisioning = 1;
+		q->limits.discard_granularity = sdkp->hw_sector_size;
+		q->limits.max_discard_sectors = 0xffffffff;
+
+		if (buffer[14] & 0x40) /* TPRZ */
+			q->limits.discard_zeroes_data = 1;
+
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+	}
+
 	sdkp->capacity = lba + 1;
 	return sector_size;
 }
@@ -1863,6 +1944,7 @@
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
+	struct request_queue *q = sdkp->disk->queue;
 	unsigned int sector_sz = sdkp->device->sector_size;
 	char *buffer;
 
@@ -1877,6 +1959,31 @@
 	blk_queue_io_opt(sdkp->disk->queue,
 			 get_unaligned_be32(&buffer[12]) * sector_sz);
 
+	/* Thin provisioning enabled and page length indicates TP support */
+	if (sdkp->thin_provisioning && buffer[3] == 0x3c) {
+		unsigned int lba_count, desc_count, granularity;
+
+		lba_count = get_unaligned_be32(&buffer[20]);
+		desc_count = get_unaligned_be32(&buffer[24]);
+
+		if (lba_count) {
+			q->limits.max_discard_sectors =
+				lba_count * sector_sz >> 9;
+
+			if (desc_count)
+				sdkp->unmap = 1;
+		}
+
+		granularity = get_unaligned_be32(&buffer[28]);
+
+		if (granularity)
+			q->limits.discard_granularity = granularity * sector_sz;
+
+		if (buffer[32] & 0x80)
+			q->limits.discard_alignment =
+				get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+	}
+
 	kfree(buffer);
 }
 
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index e374804..43d3caf 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -60,6 +60,8 @@
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
 	unsigned	first_scan : 1;
+	unsigned	thin_provisioning : 1;
+	unsigned	unmap : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index ad59abb..d04ea9a 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -552,13 +552,15 @@
 	SRpnt->waiting = waiting;
 
 	if (STp->buffer->do_dio) {
+		mdata->page_order = 0;
 		mdata->nr_entries = STp->buffer->sg_segs;
 		mdata->pages = STp->buffer->mapped_pages;
 	} else {
+		mdata->page_order = STp->buffer->reserved_page_order;
 		mdata->nr_entries =
 			DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order);
-		STp->buffer->map_data.pages = STp->buffer->reserved_pages;
-		STp->buffer->map_data.offset = 0;
+		mdata->pages = STp->buffer->reserved_pages;
+		mdata->offset = 0;
 	}
 
 	memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
@@ -3719,7 +3721,7 @@
 		priority |= __GFP_ZERO;
 
 	if (STbuffer->frp_segs) {
-		order = STbuffer->map_data.page_order;
+		order = STbuffer->reserved_page_order;
 		b_size = PAGE_SIZE << order;
 	} else {
 		for (b_size = PAGE_SIZE, order = 0;
@@ -3752,7 +3754,7 @@
 		segs++;
 	}
 	STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
-	STbuffer->map_data.page_order = order;
+	STbuffer->reserved_page_order = order;
 
 	return 1;
 }
@@ -3765,7 +3767,7 @@
 
 	for (i=0; i < st_bp->frp_segs; i++)
 		memset(page_address(st_bp->reserved_pages[i]), 0,
-		       PAGE_SIZE << st_bp->map_data.page_order);
+		       PAGE_SIZE << st_bp->reserved_page_order);
 	st_bp->cleared = 1;
 }
 
@@ -3773,7 +3775,7 @@
 /* Release the extra buffer */
 static void normalize_buffer(struct st_buffer * STbuffer)
 {
-	int i, order = STbuffer->map_data.page_order;
+	int i, order = STbuffer->reserved_page_order;
 
 	for (i = 0; i < STbuffer->frp_segs; i++) {
 		__free_pages(STbuffer->reserved_pages[i], order);
@@ -3781,7 +3783,7 @@
 	}
 	STbuffer->frp_segs = 0;
 	STbuffer->sg_segs = 0;
-	STbuffer->map_data.page_order = 0;
+	STbuffer->reserved_page_order = 0;
 	STbuffer->map_data.offset = 0;
 }
 
@@ -3791,7 +3793,7 @@
 static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
 {
 	int i, cnt, res, offset;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	for (i = 0, offset = st_bp->buffer_bytes;
 	     i < st_bp->frp_segs && offset >= length; i++)
@@ -3823,7 +3825,7 @@
 static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
 {
 	int i, cnt, res, offset;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	for (i = 0, offset = st_bp->read_pointer;
 	     i < st_bp->frp_segs && offset >= length; i++)
@@ -3856,7 +3858,7 @@
 {
 	int src_seg, dst_seg, src_offset = 0, dst_offset;
 	int count, total;
-	int length = PAGE_SIZE << st_bp->map_data.page_order;
+	int length = PAGE_SIZE << st_bp->reserved_page_order;
 
 	if (offset == 0)
 		return;
@@ -4578,7 +4580,6 @@
         }
 
 	mdata->offset = uaddr & ~PAGE_MASK;
-	mdata->page_order = 0;
 	STbp->mapped_pages = pages;
 
 	return nr_pages;
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 544dc6b..f91a67c 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -46,6 +46,7 @@
 	struct st_request *last_SRpnt;
 	struct st_cmdstatus cmdstat;
 	struct page **reserved_pages;
+	int reserved_page_order;
 	struct page **mapped_pages;
 	struct rq_map_data map_data;
 	unsigned char *b_data;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 7e3f4ff..68c7f6c 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -1043,10 +1043,14 @@
 	sci_port->port.iotype	= UPIO_MEM;
 	sci_port->port.line	= index;
 	sci_port->port.fifosize	= 1;
-	sci_port->iclk		= p->clk ? clk_get(&dev->dev, p->clk) : NULL;
-	sci_port->dclk		= clk_get(&dev->dev, "peripheral_clk");
-	sci_port->enable	= sci_clk_enable;
-	sci_port->disable	= sci_clk_disable;
+
+	if (dev) {
+		sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
+		sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
+		sci_port->enable = sci_clk_enable;
+		sci_port->disable = sci_clk_disable;
+		sci_port->port.dev = &dev->dev;
+	}
 
 	sci_port->break_timer.data = (unsigned long)sci_port;
 	sci_port->break_timer.function = sci_break_timer;
@@ -1057,7 +1061,6 @@
 
 	sci_port->port.irq	= p->irqs[SCIx_TXI_IRQ];
 	sci_port->port.flags	= p->flags;
-	sci_port->port.dev	= &dev->dev;
 	sci_port->type		= sci_port->port.type = p->type;
 
 	memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
@@ -1101,7 +1104,7 @@
 		sci_port->disable(port);
 }
 
-static int __init serial_console_setup(struct console *co, char *options)
+static int __devinit serial_console_setup(struct console *co, char *options)
 {
 	struct sci_port *sci_port;
 	struct uart_port *port;
@@ -1119,9 +1122,14 @@
 	if (co->index >= SCI_NPORTS)
 		co->index = 0;
 
-	sci_port = &sci_ports[co->index];
-	port = &sci_port->port;
-	co->data = port;
+	if (co->data) {
+		port = co->data;
+		sci_port = to_sci_port(port);
+	} else {
+		sci_port = &sci_ports[co->index];
+		port = &sci_port->port;
+		co->data = port;
+	}
 
 	/*
 	 * Also need to check port->type, we don't actually have any
@@ -1165,6 +1173,15 @@
 	return 0;
 }
 console_initcall(sci_console_init);
+
+static struct sci_port early_serial_port;
+static struct console early_serial_console = {
+	.name           = "early_ttySC",
+	.write          = serial_console_write,
+	.flags          = CON_PRINTBUFFER,
+};
+static char early_serial_buf[32];
+
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
 #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
@@ -1250,6 +1267,21 @@
 	struct sh_sci_priv *priv;
 	int i, ret = -EINVAL;
 
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+	if (is_early_platform_device(dev)) {
+		if (dev->id == -1)
+			return -ENOTSUPP;
+		early_serial_console.index = dev->id;
+		early_serial_console.data = &early_serial_port.port;
+		sci_init_single(NULL, &early_serial_port, dev->id, p);
+		serial_console_setup(&early_serial_console, early_serial_buf);
+		if (!strstr(early_serial_buf, "keep"))
+			early_serial_console.flags |= CON_BOOT;
+		register_console(&early_serial_console);
+		return 0;
+	}
+#endif
+
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
@@ -1349,6 +1381,10 @@
 	uart_unregister_driver(&sci_uart_driver);
 }
 
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+early_platform_init_buffer("earlyprintk", &sci_driver,
+			   early_serial_buf, ARRAY_SIZE(early_serial_buf));
+#endif
 module_init(sci_init);
 module_exit(sci_exit);
 
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index a7e5c2e..d5d7f23 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -806,6 +806,8 @@
 		if (d->state.event != PM_EVENT_FREEZE)
 			break;
 		for_each_irq_desc(irq, desc) {
+			if (desc->handle_irq == intc_redirect_irq)
+				continue;
 			if (desc->chip != &d->chip)
 				continue;
 			if (desc->status & IRQ_DISABLED)
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index 841ed50..082604e 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -71,7 +71,7 @@
 
 	pos = dr->reg_width - (in_pos + 1);
 
-	pr_debug("write_bit addr = %lx, value = %ld, pos = %ld, "
+	pr_debug("write_bit addr = %lx, value = %d, pos = %ld, "
 		 "r_width = %ld\n",
 		 dr->reg, !!value, pos, dr->reg_width);
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2d9d703..f55eb01 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -216,6 +216,17 @@
 	help
 	  SPI driver for Samsung S3C24XX series ARM SoCs
 
+config SPI_S3C24XX_FIQ
+	bool "S3C24XX driver with FIQ pseudo-DMA"
+	depends on SPI_S3C24XX
+	select FIQ
+	help
+	  Enable FIQ support for the S3C24XX SPI driver to provide pseudo
+	  DMA by using the fast-interrupt request framework, This allows
+	  the driver to get DMA-like performance when there are either
+	  no free DMA channels, or when doing transfers that required both
+	  TX and RX data paths.
+
 config SPI_S3C24XX_GPIO
 	tristate "Samsung S3C24XX series SPI by GPIO"
 	depends on ARCH_S3C2410 && EXPERIMENTAL
@@ -226,6 +237,13 @@
 	  the inbuilt hardware cannot provide the transfer mode, or
 	  where the board is using non hardware connected pins.
 
+config SPI_S3C64XX
+	tristate "Samsung S3C64XX series type SPI"
+	depends on ARCH_S3C64XX && EXPERIMENTAL
+	select S3C64XX_DMA
+	help
+	  SPI driver for Samsung S3C64XX and newer SoCs.
+
 config SPI_SH_MSIOF
 	tristate "SuperH MSIOF SPI controller"
 	depends on SUPERH && HAVE_CLK
@@ -289,6 +307,16 @@
 # Add new SPI master controllers in alphabetical order above this line
 #
 
+config SPI_DESIGNWARE
+	bool "DesignWare SPI controller core support"
+	depends on SPI_MASTER
+	help
+	  general driver for SPI controller core from DesignWare
+
+config SPI_DW_PCI
+	tristate "PCI interface driver for DW SPI core"
+	depends on SPI_DESIGNWARE && PCI
+
 #
 # There are lots of SPI device types, with sensors and memory
 # being probably the most widely used ones.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ed8c167..f3d2810 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,8 @@
 obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
 obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
 obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
+obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.o
+obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_pci.o
 obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
@@ -30,7 +32,8 @@
 obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
-obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
+obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
+obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
 obj-$(CONFIG_SPI_XILINX_OF)		+= xilinx_spi_of.o
@@ -39,6 +42,11 @@
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
 obj-$(CONFIG_SPI_NUC900)		+= spi_nuc900.o
+
+# special build for s3c24xx spi driver with fiq support
+spi_s3c24xx_hw-y			:= spi_s3c24xx.o
+spi_s3c24xx_hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi_s3c24xx_fiq.o
+
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index f5b3fdb..d21c24e 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -189,14 +189,14 @@
 
 	/* use scratch buffer only when rx or tx data is unspecified */
 	if (xfer->rx_buf)
-		*rx_dma = xfer->rx_dma + xfer->len - len;
+		*rx_dma = xfer->rx_dma + xfer->len - *plen;
 	else {
 		*rx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
 			len = BUFFER_SIZE;
 	}
 	if (xfer->tx_buf)
-		*tx_dma = xfer->tx_dma + xfer->len - len;
+		*tx_dma = xfer->tx_dma + xfer->len - *plen;
 	else {
 		*tx_dma = as->buffer_dma;
 		if (len > BUFFER_SIZE)
@@ -788,7 +788,7 @@
 	spin_lock_init(&as->lock);
 	INIT_LIST_HEAD(&as->queue);
 	as->pdev = pdev;
-	as->regs = ioremap(regs->start, (regs->end - regs->start) + 1);
+	as->regs = ioremap(regs->start, resource_size(regs));
 	if (!as->regs)
 		goto out_free_buffer;
 	as->irq = irq;
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
new file mode 100644
index 0000000..31620fa
--- /dev/null
+++ b/drivers/spi/dw_spi.c
@@ -0,0 +1,944 @@
+/*
+ * dw_spi.c - Designware SPI core controller driver (refer pxa2xx_spi.c)
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/highmem.h>
+#include <linux/delay.h>
+
+#include <linux/spi/dw_spi.h>
+#include <linux/spi/spi.h>
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#endif
+
+#define START_STATE	((void *)0)
+#define RUNNING_STATE	((void *)1)
+#define DONE_STATE	((void *)2)
+#define ERROR_STATE	((void *)-1)
+
+#define QUEUE_RUNNING	0
+#define QUEUE_STOPPED	1
+
+#define MRST_SPI_DEASSERT	0
+#define MRST_SPI_ASSERT		1
+
+/* Slave spi_dev related */
+struct chip_data {
+	u16 cr0;
+	u8 cs;			/* chip select pin */
+	u8 n_bytes;		/* current is a 1/2/4 byte op */
+	u8 tmode;		/* TR/TO/RO/EEPROM */
+	u8 type;		/* SPI/SSP/MicroWire */
+
+	u8 poll_mode;		/* 1 means use poll mode */
+
+	u32 dma_width;
+	u32 rx_threshold;
+	u32 tx_threshold;
+	u8 enable_dma;
+	u8 bits_per_word;
+	u16 clk_div;		/* baud rate divider */
+	u32 speed_hz;		/* baud rate */
+	int (*write)(struct dw_spi *dws);
+	int (*read)(struct dw_spi *dws);
+	void (*cs_control)(u32 command);
+};
+
+#ifdef CONFIG_DEBUG_FS
+static int spi_show_regs_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define SPI_REGS_BUFSIZE	1024
+static ssize_t  spi_show_regs(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct dw_spi *dws;
+	char *buf;
+	u32 len = 0;
+	ssize_t ret;
+
+	dws = file->private_data;
+
+	buf = kzalloc(SPI_REGS_BUFSIZE, GFP_KERNEL);
+	if (!buf)
+		return 0;
+
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"MRST SPI0 registers:\n");
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"=================================\n");
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"CTRL0: \t\t0x%08x\n", dw_readl(dws, ctrl0));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"CTRL1: \t\t0x%08x\n", dw_readl(dws, ctrl1));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SSIENR: \t0x%08x\n", dw_readl(dws, ssienr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SER: \t\t0x%08x\n", dw_readl(dws, ser));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"BAUDR: \t\t0x%08x\n", dw_readl(dws, baudr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"TXFTLR: \t0x%08x\n", dw_readl(dws, txfltr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"RXFTLR: \t0x%08x\n", dw_readl(dws, rxfltr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"TXFLR: \t\t0x%08x\n", dw_readl(dws, txflr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"RXFLR: \t\t0x%08x\n", dw_readl(dws, rxflr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"SR: \t\t0x%08x\n", dw_readl(dws, sr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"IMR: \t\t0x%08x\n", dw_readl(dws, imr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"ISR: \t\t0x%08x\n", dw_readl(dws, isr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMACR: \t\t0x%08x\n", dw_readl(dws, dmacr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMATDLR: \t0x%08x\n", dw_readl(dws, dmatdlr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"DMARDLR: \t0x%08x\n", dw_readl(dws, dmardlr));
+	len += snprintf(buf + len, SPI_REGS_BUFSIZE - len,
+			"=================================\n");
+
+	ret =  simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+	return ret;
+}
+
+static const struct file_operations mrst_spi_regs_ops = {
+	.owner		= THIS_MODULE,
+	.open		= spi_show_regs_open,
+	.read		= spi_show_regs,
+};
+
+static int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+	dws->debugfs = debugfs_create_dir("mrst_spi", NULL);
+	if (!dws->debugfs)
+		return -ENOMEM;
+
+	debugfs_create_file("registers", S_IFREG | S_IRUGO,
+		dws->debugfs, (void *)dws, &mrst_spi_regs_ops);
+	return 0;
+}
+
+static void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+	if (dws->debugfs)
+		debugfs_remove_recursive(dws->debugfs);
+}
+
+#else
+static inline int mrst_spi_debugfs_init(struct dw_spi *dws)
+{
+}
+
+static inline void mrst_spi_debugfs_remove(struct dw_spi *dws)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+static void wait_till_not_busy(struct dw_spi *dws)
+{
+	unsigned long end = jiffies + usecs_to_jiffies(1000);
+
+	while (time_before(jiffies, end)) {
+		if (!(dw_readw(dws, sr) & SR_BUSY))
+			return;
+	}
+	dev_err(&dws->master->dev,
+		"DW SPI: Stutus keeps busy for 1000us after a read/write!\n");
+}
+
+static void flush(struct dw_spi *dws)
+{
+	while (dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+		dw_readw(dws, dr);
+
+	wait_till_not_busy(dws);
+}
+
+static void null_cs_control(u32 command)
+{
+}
+
+static int null_writer(struct dw_spi *dws)
+{
+	u8 n_bytes = dws->n_bytes;
+
+	if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+		|| (dws->tx == dws->tx_end))
+		return 0;
+	dw_writew(dws, dr, 0);
+	dws->tx += n_bytes;
+
+	wait_till_not_busy(dws);
+	return 1;
+}
+
+static int null_reader(struct dw_spi *dws)
+{
+	u8 n_bytes = dws->n_bytes;
+
+	while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+		&& (dws->rx < dws->rx_end)) {
+		dw_readw(dws, dr);
+		dws->rx += n_bytes;
+	}
+	wait_till_not_busy(dws);
+	return dws->rx == dws->rx_end;
+}
+
+static int u8_writer(struct dw_spi *dws)
+{
+	if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+		|| (dws->tx == dws->tx_end))
+		return 0;
+
+	dw_writew(dws, dr, *(u8 *)(dws->tx));
+	++dws->tx;
+
+	wait_till_not_busy(dws);
+	return 1;
+}
+
+static int u8_reader(struct dw_spi *dws)
+{
+	while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+		&& (dws->rx < dws->rx_end)) {
+		*(u8 *)(dws->rx) = dw_readw(dws, dr);
+		++dws->rx;
+	}
+
+	wait_till_not_busy(dws);
+	return dws->rx == dws->rx_end;
+}
+
+static int u16_writer(struct dw_spi *dws)
+{
+	if (!(dw_readw(dws, sr) & SR_TF_NOT_FULL)
+		|| (dws->tx == dws->tx_end))
+		return 0;
+
+	dw_writew(dws, dr, *(u16 *)(dws->tx));
+	dws->tx += 2;
+
+	wait_till_not_busy(dws);
+	return 1;
+}
+
+static int u16_reader(struct dw_spi *dws)
+{
+	u16 temp;
+
+	while ((dw_readw(dws, sr) & SR_RF_NOT_EMPT)
+		&& (dws->rx < dws->rx_end)) {
+		temp = dw_readw(dws, dr);
+		*(u16 *)(dws->rx) = temp;
+		dws->rx += 2;
+	}
+
+	wait_till_not_busy(dws);
+	return dws->rx == dws->rx_end;
+}
+
+static void *next_transfer(struct dw_spi *dws)
+{
+	struct spi_message *msg = dws->cur_msg;
+	struct spi_transfer *trans = dws->cur_transfer;
+
+	/* Move to next transfer */
+	if (trans->transfer_list.next != &msg->transfers) {
+		dws->cur_transfer =
+			list_entry(trans->transfer_list.next,
+					struct spi_transfer,
+					transfer_list);
+		return RUNNING_STATE;
+	} else
+		return DONE_STATE;
+}
+
+/*
+ * Note: first step is the protocol driver prepares
+ * a dma-capable memory, and this func just need translate
+ * the virt addr to physical
+ */
+static int map_dma_buffers(struct dw_spi *dws)
+{
+	if (!dws->cur_msg->is_dma_mapped || !dws->dma_inited
+		|| !dws->cur_chip->enable_dma)
+		return 0;
+
+	if (dws->cur_transfer->tx_dma)
+		dws->tx_dma = dws->cur_transfer->tx_dma;
+
+	if (dws->cur_transfer->rx_dma)
+		dws->rx_dma = dws->cur_transfer->rx_dma;
+
+	return 1;
+}
+
+/* Caller already set message->status; dma and pio irqs are blocked */
+static void giveback(struct dw_spi *dws)
+{
+	struct spi_transfer *last_transfer;
+	unsigned long flags;
+	struct spi_message *msg;
+
+	spin_lock_irqsave(&dws->lock, flags);
+	msg = dws->cur_msg;
+	dws->cur_msg = NULL;
+	dws->cur_transfer = NULL;
+	dws->prev_chip = dws->cur_chip;
+	dws->cur_chip = NULL;
+	dws->dma_mapped = 0;
+	queue_work(dws->workqueue, &dws->pump_messages);
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	last_transfer = list_entry(msg->transfers.prev,
+					struct spi_transfer,
+					transfer_list);
+
+	if (!last_transfer->cs_change)
+		dws->cs_control(MRST_SPI_DEASSERT);
+
+	msg->state = NULL;
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+static void int_error_stop(struct dw_spi *dws, const char *msg)
+{
+	/* Stop and reset hw */
+	flush(dws);
+	spi_enable_chip(dws, 0);
+
+	dev_err(&dws->master->dev, "%s\n", msg);
+	dws->cur_msg->state = ERROR_STATE;
+	tasklet_schedule(&dws->pump_transfers);
+}
+
+static void transfer_complete(struct dw_spi *dws)
+{
+	/* Update total byte transfered return count actual bytes read */
+	dws->cur_msg->actual_length += dws->len;
+
+	/* Move to next transfer */
+	dws->cur_msg->state = next_transfer(dws);
+
+	/* Handle end of message */
+	if (dws->cur_msg->state == DONE_STATE) {
+		dws->cur_msg->status = 0;
+		giveback(dws);
+	} else
+		tasklet_schedule(&dws->pump_transfers);
+}
+
+static irqreturn_t interrupt_transfer(struct dw_spi *dws)
+{
+	u16 irq_status, irq_mask = 0x3f;
+
+	irq_status = dw_readw(dws, isr) & irq_mask;
+	/* Error handling */
+	if (irq_status & (SPI_INT_TXOI | SPI_INT_RXOI | SPI_INT_RXUI)) {
+		dw_readw(dws, txoicr);
+		dw_readw(dws, rxoicr);
+		dw_readw(dws, rxuicr);
+		int_error_stop(dws, "interrupt_transfer: fifo overrun");
+		return IRQ_HANDLED;
+	}
+
+	/* INT comes from tx */
+	if (dws->tx && (irq_status & SPI_INT_TXEI)) {
+		while (dws->tx < dws->tx_end)
+			dws->write(dws);
+
+		if (dws->tx == dws->tx_end) {
+			spi_mask_intr(dws, SPI_INT_TXEI);
+			transfer_complete(dws);
+		}
+	}
+
+	/* INT comes from rx */
+	if (dws->rx && (irq_status & SPI_INT_RXFI)) {
+		if (dws->read(dws))
+			transfer_complete(dws);
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dw_spi_irq(int irq, void *dev_id)
+{
+	struct dw_spi *dws = dev_id;
+
+	if (!dws->cur_msg) {
+		spi_mask_intr(dws, SPI_INT_TXEI);
+		/* Never fail */
+		return IRQ_HANDLED;
+	}
+
+	return dws->transfer_handler(dws);
+}
+
+/* Must be called inside pump_transfers() */
+static void poll_transfer(struct dw_spi *dws)
+{
+	if (dws->tx) {
+		while (dws->write(dws))
+			dws->read(dws);
+	}
+
+	dws->read(dws);
+	transfer_complete(dws);
+}
+
+static void dma_transfer(struct dw_spi *dws, int cs_change)
+{
+}
+
+static void pump_transfers(unsigned long data)
+{
+	struct dw_spi *dws = (struct dw_spi *)data;
+	struct spi_message *message = NULL;
+	struct spi_transfer *transfer = NULL;
+	struct spi_transfer *previous = NULL;
+	struct spi_device *spi = NULL;
+	struct chip_data *chip = NULL;
+	u8 bits = 0;
+	u8 imask = 0;
+	u8 cs_change = 0;
+	u16 clk_div = 0;
+	u32 speed = 0;
+	u32 cr0 = 0;
+
+	/* Get current state information */
+	message = dws->cur_msg;
+	transfer = dws->cur_transfer;
+	chip = dws->cur_chip;
+	spi = message->spi;
+
+	if (message->state == ERROR_STATE) {
+		message->status = -EIO;
+		goto early_exit;
+	}
+
+	/* Handle end of message */
+	if (message->state == DONE_STATE) {
+		message->status = 0;
+		goto early_exit;
+	}
+
+	/* Delay if requested at end of transfer*/
+	if (message->state == RUNNING_STATE) {
+		previous = list_entry(transfer->transfer_list.prev,
+					struct spi_transfer,
+					transfer_list);
+		if (previous->delay_usecs)
+			udelay(previous->delay_usecs);
+	}
+
+	dws->n_bytes = chip->n_bytes;
+	dws->dma_width = chip->dma_width;
+	dws->cs_control = chip->cs_control;
+
+	dws->rx_dma = transfer->rx_dma;
+	dws->tx_dma = transfer->tx_dma;
+	dws->tx = (void *)transfer->tx_buf;
+	dws->tx_end = dws->tx + transfer->len;
+	dws->rx = transfer->rx_buf;
+	dws->rx_end = dws->rx + transfer->len;
+	dws->write = dws->tx ? chip->write : null_writer;
+	dws->read = dws->rx ? chip->read : null_reader;
+	dws->cs_change = transfer->cs_change;
+	dws->len = dws->cur_transfer->len;
+	if (chip != dws->prev_chip)
+		cs_change = 1;
+
+	cr0 = chip->cr0;
+
+	/* Handle per transfer options for bpw and speed */
+	if (transfer->speed_hz) {
+		speed = chip->speed_hz;
+
+		if (transfer->speed_hz != speed) {
+			speed = transfer->speed_hz;
+			if (speed > dws->max_freq) {
+				printk(KERN_ERR "MRST SPI0: unsupported"
+					"freq: %dHz\n", speed);
+				message->status = -EIO;
+				goto early_exit;
+			}
+
+			/* clk_div doesn't support odd number */
+			clk_div = dws->max_freq / speed;
+			clk_div = (clk_div >> 1) << 1;
+
+			chip->speed_hz = speed;
+			chip->clk_div = clk_div;
+		}
+	}
+	if (transfer->bits_per_word) {
+		bits = transfer->bits_per_word;
+
+		switch (bits) {
+		case 8:
+			dws->n_bytes = 1;
+			dws->dma_width = 1;
+			dws->read = (dws->read != null_reader) ?
+					u8_reader : null_reader;
+			dws->write = (dws->write != null_writer) ?
+					u8_writer : null_writer;
+			break;
+		case 16:
+			dws->n_bytes = 2;
+			dws->dma_width = 2;
+			dws->read = (dws->read != null_reader) ?
+					u16_reader : null_reader;
+			dws->write = (dws->write != null_writer) ?
+					u16_writer : null_writer;
+			break;
+		default:
+			printk(KERN_ERR "MRST SPI0: unsupported bits:"
+				"%db\n", bits);
+			message->status = -EIO;
+			goto early_exit;
+		}
+
+		cr0 = (bits - 1)
+			| (chip->type << SPI_FRF_OFFSET)
+			| (spi->mode << SPI_MODE_OFFSET)
+			| (chip->tmode << SPI_TMOD_OFFSET);
+	}
+	message->state = RUNNING_STATE;
+
+	/* Check if current transfer is a DMA transaction */
+	dws->dma_mapped = map_dma_buffers(dws);
+
+	if (!dws->dma_mapped && !chip->poll_mode) {
+		if (dws->rx)
+			imask |= SPI_INT_RXFI;
+		if (dws->tx)
+			imask |= SPI_INT_TXEI;
+		dws->transfer_handler = interrupt_transfer;
+	}
+
+	/*
+	 * Reprogram registers only if
+	 *	1. chip select changes
+	 *	2. clk_div is changed
+	 *	3. control value changes
+	 */
+	if (dw_readw(dws, ctrl0) != cr0 || cs_change || clk_div) {
+		spi_enable_chip(dws, 0);
+
+		if (dw_readw(dws, ctrl0) != cr0)
+			dw_writew(dws, ctrl0, cr0);
+
+		/* Set the interrupt mask, for poll mode just diable all int */
+		spi_mask_intr(dws, 0xff);
+		if (!chip->poll_mode)
+			spi_umask_intr(dws, imask);
+
+		spi_set_clk(dws, clk_div ? clk_div : chip->clk_div);
+		spi_chip_sel(dws, spi->chip_select);
+		spi_enable_chip(dws, 1);
+
+		if (cs_change)
+			dws->prev_chip = chip;
+	}
+
+	if (dws->dma_mapped)
+		dma_transfer(dws, cs_change);
+
+	if (chip->poll_mode)
+		poll_transfer(dws);
+
+	return;
+
+early_exit:
+	giveback(dws);
+	return;
+}
+
+static void pump_messages(struct work_struct *work)
+{
+	struct dw_spi *dws =
+		container_of(work, struct dw_spi, pump_messages);
+	unsigned long flags;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&dws->lock, flags);
+	if (list_empty(&dws->queue) || dws->run == QUEUE_STOPPED) {
+		dws->busy = 0;
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (dws->cur_msg) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return;
+	}
+
+	/* Extract head of queue */
+	dws->cur_msg = list_entry(dws->queue.next, struct spi_message, queue);
+	list_del_init(&dws->cur_msg->queue);
+
+	/* Initial message state*/
+	dws->cur_msg->state = START_STATE;
+	dws->cur_transfer = list_entry(dws->cur_msg->transfers.next,
+						struct spi_transfer,
+						transfer_list);
+	dws->cur_chip = spi_get_ctldata(dws->cur_msg->spi);
+
+	/* Mark as busy and launch transfers */
+	tasklet_schedule(&dws->pump_transfers);
+
+	dws->busy = 1;
+	spin_unlock_irqrestore(&dws->lock, flags);
+}
+
+/* spi_device use this to queue in their spi_msg */
+static int dw_spi_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct dw_spi *dws = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dws->lock, flags);
+
+	if (dws->run == QUEUE_STOPPED) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+	msg->state = START_STATE;
+
+	list_add_tail(&msg->queue, &dws->queue);
+
+	if (dws->run == QUEUE_RUNNING && !dws->busy) {
+
+		if (dws->cur_transfer || dws->cur_msg)
+			queue_work(dws->workqueue,
+					&dws->pump_messages);
+		else {
+			/* If no other data transaction in air, just go */
+			spin_unlock_irqrestore(&dws->lock, flags);
+			pump_messages(&dws->pump_messages);
+			return 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&dws->lock, flags);
+	return 0;
+}
+
+/* This may be called twice for each spi dev */
+static int dw_spi_setup(struct spi_device *spi)
+{
+	struct dw_spi_chip *chip_info = NULL;
+	struct chip_data *chip;
+
+	if (spi->bits_per_word != 8 && spi->bits_per_word != 16)
+		return -EINVAL;
+
+	/* Only alloc on first setup */
+	chip = spi_get_ctldata(spi);
+	if (!chip) {
+		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+
+		chip->cs_control = null_cs_control;
+		chip->enable_dma = 0;
+	}
+
+	/*
+	 * Protocol drivers may change the chip settings, so...
+	 * if chip_info exists, use it
+	 */
+	chip_info = spi->controller_data;
+
+	/* chip_info doesn't always exist */
+	if (chip_info) {
+		if (chip_info->cs_control)
+			chip->cs_control = chip_info->cs_control;
+
+		chip->poll_mode = chip_info->poll_mode;
+		chip->type = chip_info->type;
+
+		chip->rx_threshold = 0;
+		chip->tx_threshold = 0;
+
+		chip->enable_dma = chip_info->enable_dma;
+	}
+
+	if (spi->bits_per_word <= 8) {
+		chip->n_bytes = 1;
+		chip->dma_width = 1;
+		chip->read = u8_reader;
+		chip->write = u8_writer;
+	} else if (spi->bits_per_word <= 16) {
+		chip->n_bytes = 2;
+		chip->dma_width = 2;
+		chip->read = u16_reader;
+		chip->write = u16_writer;
+	} else {
+		/* Never take >16b case for MRST SPIC */
+		dev_err(&spi->dev, "invalid wordsize\n");
+		return -EINVAL;
+	}
+	chip->bits_per_word = spi->bits_per_word;
+
+	chip->speed_hz = spi->max_speed_hz;
+	if (chip->speed_hz)
+		chip->clk_div = 25000000 / chip->speed_hz;
+	else
+		chip->clk_div = 8;	/* default value */
+
+	chip->tmode = 0; /* Tx & Rx */
+	/* Default SPI mode is SCPOL = 0, SCPH = 0 */
+	chip->cr0 = (chip->bits_per_word - 1)
+			| (chip->type << SPI_FRF_OFFSET)
+			| (spi->mode  << SPI_MODE_OFFSET)
+			| (chip->tmode << SPI_TMOD_OFFSET);
+
+	spi_set_ctldata(spi, chip);
+	return 0;
+}
+
+static void dw_spi_cleanup(struct spi_device *spi)
+{
+	struct chip_data *chip = spi_get_ctldata(spi);
+	kfree(chip);
+}
+
+static int __init init_queue(struct dw_spi *dws)
+{
+	INIT_LIST_HEAD(&dws->queue);
+	spin_lock_init(&dws->lock);
+
+	dws->run = QUEUE_STOPPED;
+	dws->busy = 0;
+
+	tasklet_init(&dws->pump_transfers,
+			pump_transfers,	(unsigned long)dws);
+
+	INIT_WORK(&dws->pump_messages, pump_messages);
+	dws->workqueue = create_singlethread_workqueue(
+					dev_name(dws->master->dev.parent));
+	if (dws->workqueue == NULL)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int start_queue(struct dw_spi *dws)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dws->lock, flags);
+
+	if (dws->run == QUEUE_RUNNING || dws->busy) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		return -EBUSY;
+	}
+
+	dws->run = QUEUE_RUNNING;
+	dws->cur_msg = NULL;
+	dws->cur_transfer = NULL;
+	dws->cur_chip = NULL;
+	dws->prev_chip = NULL;
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	queue_work(dws->workqueue, &dws->pump_messages);
+
+	return 0;
+}
+
+static int stop_queue(struct dw_spi *dws)
+{
+	unsigned long flags;
+	unsigned limit = 50;
+	int status = 0;
+
+	spin_lock_irqsave(&dws->lock, flags);
+	dws->run = QUEUE_STOPPED;
+	while (!list_empty(&dws->queue) && dws->busy && limit--) {
+		spin_unlock_irqrestore(&dws->lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&dws->lock, flags);
+	}
+
+	if (!list_empty(&dws->queue) || dws->busy)
+		status = -EBUSY;
+	spin_unlock_irqrestore(&dws->lock, flags);
+
+	return status;
+}
+
+static int destroy_queue(struct dw_spi *dws)
+{
+	int status;
+
+	status = stop_queue(dws);
+	if (status != 0)
+		return status;
+	destroy_workqueue(dws->workqueue);
+	return 0;
+}
+
+/* Restart the controller, disable all interrupts, clean rx fifo */
+static void spi_hw_init(struct dw_spi *dws)
+{
+	spi_enable_chip(dws, 0);
+	spi_mask_intr(dws, 0xff);
+	spi_enable_chip(dws, 1);
+	flush(dws);
+}
+
+int __devinit dw_spi_add_host(struct dw_spi *dws)
+{
+	struct spi_master *master;
+	int ret;
+
+	BUG_ON(dws == NULL);
+
+	master = spi_alloc_master(dws->parent_dev, 0);
+	if (!master) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	dws->master = master;
+	dws->type = SSI_MOTO_SPI;
+	dws->prev_chip = NULL;
+	dws->dma_inited = 0;
+	dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+
+	ret = request_irq(dws->irq, dw_spi_irq, 0,
+			"dw_spi", dws);
+	if (ret < 0) {
+		dev_err(&master->dev, "can not get IRQ\n");
+		goto err_free_master;
+	}
+
+	master->mode_bits = SPI_CPOL | SPI_CPHA;
+	master->bus_num = dws->bus_num;
+	master->num_chipselect = dws->num_cs;
+	master->cleanup = dw_spi_cleanup;
+	master->setup = dw_spi_setup;
+	master->transfer = dw_spi_transfer;
+
+	dws->dma_inited = 0;
+
+	/* Basic HW init */
+	spi_hw_init(dws);
+
+	/* Initial and start queue */
+	ret = init_queue(dws);
+	if (ret) {
+		dev_err(&master->dev, "problem initializing queue\n");
+		goto err_diable_hw;
+	}
+	ret = start_queue(dws);
+	if (ret) {
+		dev_err(&master->dev, "problem starting queue\n");
+		goto err_diable_hw;
+	}
+
+	spi_master_set_devdata(master, dws);
+	ret = spi_register_master(master);
+	if (ret) {
+		dev_err(&master->dev, "problem registering spi master\n");
+		goto err_queue_alloc;
+	}
+
+	mrst_spi_debugfs_init(dws);
+	return 0;
+
+err_queue_alloc:
+	destroy_queue(dws);
+err_diable_hw:
+	spi_enable_chip(dws, 0);
+	free_irq(dws->irq, dws);
+err_free_master:
+	spi_master_put(master);
+exit:
+	return ret;
+}
+EXPORT_SYMBOL(dw_spi_add_host);
+
+void __devexit dw_spi_remove_host(struct dw_spi *dws)
+{
+	int status = 0;
+
+	if (!dws)
+		return;
+	mrst_spi_debugfs_remove(dws);
+
+	/* Remove the queue */
+	status = destroy_queue(dws);
+	if (status != 0)
+		dev_err(&dws->master->dev, "dw_spi_remove: workqueue will not "
+			"complete, message memory not freed\n");
+
+	spi_enable_chip(dws, 0);
+	/* Disable clk */
+	spi_set_clk(dws, 0);
+	free_irq(dws->irq, dws);
+
+	/* Disconnect from the SPI framework */
+	spi_unregister_master(dws->master);
+}
+
+int dw_spi_suspend_host(struct dw_spi *dws)
+{
+	int ret = 0;
+
+	ret = stop_queue(dws);
+	if (ret)
+		return ret;
+	spi_enable_chip(dws, 0);
+	spi_set_clk(dws, 0);
+	return ret;
+}
+EXPORT_SYMBOL(dw_spi_suspend_host);
+
+int dw_spi_resume_host(struct dw_spi *dws)
+{
+	int ret;
+
+	spi_hw_init(dws);
+	ret = start_queue(dws);
+	if (ret)
+		dev_err(&dws->master->dev, "fail to start queue (%d)\n", ret);
+	return ret;
+}
+EXPORT_SYMBOL(dw_spi_resume_host);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
new file mode 100644
index 0000000..34ba691
--- /dev/null
+++ b/drivers/spi/dw_spi_pci.c
@@ -0,0 +1,169 @@
+/*
+ * mrst_spi_pci.c - PCI interface driver for DW SPI Core
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/spi/dw_spi.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME "dw_spi_pci"
+
+struct dw_spi_pci {
+	struct pci_dev		*pdev;
+	struct dw_spi		dws;
+};
+
+static int __devinit spi_pci_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	struct dw_spi_pci *dwpci;
+	struct dw_spi *dws;
+	int pci_bar = 0;
+	int ret;
+
+	printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n",
+		pdev->vendor, pdev->device);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL);
+	if (!dwpci) {
+		ret = -ENOMEM;
+		goto err_disable;
+	}
+
+	dwpci->pdev = pdev;
+	dws = &dwpci->dws;
+
+	/* Get basic io resource and map it */
+	dws->paddr = pci_resource_start(pdev, pci_bar);
+	dws->iolen = pci_resource_len(pdev, pci_bar);
+
+	ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev));
+	if (ret)
+		goto err_kfree;
+
+	dws->regs = ioremap_nocache((unsigned long)dws->paddr,
+				pci_resource_len(pdev, pci_bar));
+	if (!dws->regs) {
+		ret = -ENOMEM;
+		goto err_release_reg;
+	}
+
+	dws->parent_dev = &pdev->dev;
+	dws->bus_num = 0;
+	dws->num_cs = 4;
+	dws->max_freq = 25000000;	/* for Moorestwon */
+	dws->irq = pdev->irq;
+
+	ret = dw_spi_add_host(dws);
+	if (ret)
+		goto err_unmap;
+
+	/* PCI hook and SPI hook use the same drv data */
+	pci_set_drvdata(pdev, dwpci);
+	return 0;
+
+err_unmap:
+	iounmap(dws->regs);
+err_release_reg:
+	pci_release_region(pdev, pci_bar);
+err_kfree:
+	kfree(dwpci);
+err_disable:
+	pci_disable_device(pdev);
+	return ret;
+}
+
+static void __devexit spi_pci_remove(struct pci_dev *pdev)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+
+	pci_set_drvdata(pdev, NULL);
+	iounmap(dwpci->dws.regs);
+	pci_release_region(pdev, 0);
+	kfree(dwpci);
+	pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM
+static int spi_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+	int ret;
+
+	ret = dw_spi_suspend_host(&dwpci->dws);
+	if (ret)
+		return ret;
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return ret;
+}
+
+static int spi_resume(struct pci_dev *pdev)
+{
+	struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+	return dw_spi_resume_host(&dwpci->dws);
+}
+#else
+#define spi_suspend	NULL
+#define spi_resume	NULL
+#endif
+
+static const struct pci_device_id pci_ids[] __devinitdata = {
+	/* Intel Moorestown platform SPI controller 0 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) },
+	{},
+};
+
+static struct pci_driver dw_spi_driver = {
+	.name =		DRIVER_NAME,
+	.id_table =	pci_ids,
+	.probe =	spi_pci_probe,
+	.remove =	__devexit_p(spi_pci_remove),
+	.suspend =	spi_suspend,
+	.resume	=	spi_resume,
+};
+
+static int __init mrst_spi_init(void)
+{
+	return pci_register_driver(&dw_spi_driver);
+}
+
+static void __exit mrst_spi_exit(void)
+{
+	pci_unregister_driver(&dw_spi_driver);
+}
+
+module_init(mrst_spi_init);
+module_exit(mrst_spi_exit);
+
+MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
+MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 73e24ef..1d41058 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1294,7 +1294,7 @@
 		goto out_error_get_res;
 	}
 
-	drv_data->regs_base = ioremap(res->start, (res->end - res->start + 1));
+	drv_data->regs_base = ioremap(res->start, resource_size(res));
 	if (drv_data->regs_base == NULL) {
 		dev_err(dev, "Cannot map IO\n");
 		status = -ENXIO;
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
index e9390d7..1fb2a6e 100644
--- a/drivers/spi/spi_mpc8xxx.c
+++ b/drivers/spi/spi_mpc8xxx.c
@@ -1013,7 +1013,7 @@
 
 	init_completion(&mpc8xxx_spi->done);
 
-	mpc8xxx_spi->base = ioremap(mem->start, mem->end - mem->start + 1);
+	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
 	if (mpc8xxx_spi->base == NULL) {
 		ret = -ENOMEM;
 		goto err_ioremap;
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 2765915..c010733 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -1,7 +1,7 @@
 /* linux/drivers/spi/spi_s3c24xx.c
  *
  * Copyright (c) 2006 Ben Dooks
- * Copyright (c) 2006 Simtec Electronics
+ * Copyright 2006-2009 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -28,6 +28,11 @@
 #include <plat/regs-spi.h>
 #include <mach/spi.h>
 
+#include <plat/fiq.h>
+#include <asm/fiq.h>
+
+#include "spi_s3c24xx_fiq.h"
+
 /**
  * s3c24xx_spi_devstate - per device data
  * @hz: Last frequency calculated for @sppre field.
@@ -42,6 +47,13 @@
 	u8		sppre;
 };
 
+enum spi_fiq_mode {
+	FIQ_MODE_NONE	= 0,
+	FIQ_MODE_TX	= 1,
+	FIQ_MODE_RX	= 2,
+	FIQ_MODE_TXRX	= 3,
+};
+
 struct s3c24xx_spi {
 	/* bitbang has to be first */
 	struct spi_bitbang	 bitbang;
@@ -52,6 +64,11 @@
 	int			 len;
 	int			 count;
 
+	struct fiq_handler	 fiq_handler;
+	enum spi_fiq_mode	 fiq_mode;
+	unsigned char		 fiq_inuse;
+	unsigned char		 fiq_claimed;
+
 	void			(*set_cs)(struct s3c2410_spi_info *spi,
 					  int cs, int pol);
 
@@ -67,6 +84,7 @@
 	struct s3c2410_spi_info *pdata;
 };
 
+
 #define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
 #define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
 
@@ -127,7 +145,7 @@
 	}
 
 	if (spi->mode != cs->mode) {
-		u8 spcon = SPCON_DEFAULT;
+		u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
 
 		if (spi->mode & SPI_CPHA)
 			spcon |= S3C2410_SPCON_CPHA_FMTB;
@@ -214,13 +232,196 @@
 	return hw->tx ? hw->tx[count] : 0;
 }
 
+#ifdef CONFIG_SPI_S3C24XX_FIQ
+/* Support for FIQ based pseudo-DMA to improve the transfer speed.
+ *
+ * This code uses the assembly helper in spi_s3c24xx_spi.S which is
+ * used by the FIQ core to move data between main memory and the peripheral
+ * block. Since this is code running on the processor, there is no problem
+ * with cache coherency of the buffers, so we can use any buffer we like.
+ */
+
+/**
+ * struct spi_fiq_code - FIQ code and header
+ * @length: The length of the code fragment, excluding this header.
+ * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
+ * @data: The code itself to install as a FIQ handler.
+ */
+struct spi_fiq_code {
+	u32	length;
+	u32	ack_offset;
+	u8	data[0];
+};
+
+extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
+extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
+
+/**
+ * ack_bit - turn IRQ into IRQ acknowledgement bit
+ * @irq: The interrupt number
+ *
+ * Returns the bit to write to the interrupt acknowledge register.
+ */
+static inline u32 ack_bit(unsigned int irq)
+{
+	return 1 << (irq - IRQ_EINT0);
+}
+
+/**
+ * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
+ * @hw: The hardware state.
+ *
+ * Claim the FIQ handler (only one can be active at any one time) and
+ * then setup the correct transfer code for this transfer.
+ *
+ * This call updates all the necessary state information if sucessful,
+ * so the caller does not need to do anything more than start the transfer
+ * as normal, since the IRQ will have been re-routed to the FIQ handler.
+*/
+void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
+{
+	struct pt_regs regs;
+	enum spi_fiq_mode mode;
+	struct spi_fiq_code *code;
+	int ret;
+
+	if (!hw->fiq_claimed) {
+		/* try and claim fiq if we haven't got it, and if not
+		 * then return and simply use another transfer method */
+
+		ret = claim_fiq(&hw->fiq_handler);
+		if (ret)
+			return;
+	}
+
+	if (hw->tx && !hw->rx)
+		mode = FIQ_MODE_TX;
+	else if (hw->rx && !hw->tx)
+		mode = FIQ_MODE_RX;
+	else
+		mode = FIQ_MODE_TXRX;
+
+	regs.uregs[fiq_rspi] = (long)hw->regs;
+	regs.uregs[fiq_rrx]  = (long)hw->rx;
+	regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
+	regs.uregs[fiq_rcount] = hw->len - 1;
+	regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
+
+	set_fiq_regs(&regs);
+
+	if (hw->fiq_mode != mode) {
+		u32 *ack_ptr;
+
+		hw->fiq_mode = mode;
+
+		switch (mode) {
+		case FIQ_MODE_TX:
+			code = &s3c24xx_spi_fiq_tx;
+			break;
+		case FIQ_MODE_RX:
+			code = &s3c24xx_spi_fiq_rx;
+			break;
+		case FIQ_MODE_TXRX:
+			code = &s3c24xx_spi_fiq_txrx;
+			break;
+		default:
+			code = NULL;
+		}
+
+		BUG_ON(!code);
+
+		ack_ptr = (u32 *)&code->data[code->ack_offset];
+		*ack_ptr = ack_bit(hw->irq);
+
+		set_fiq_handler(&code->data, code->length);
+	}
+
+	s3c24xx_set_fiq(hw->irq, true);
+
+	hw->fiq_mode = mode;
+	hw->fiq_inuse = 1;
+}
+
+/**
+ * s3c24xx_spi_fiqop - FIQ core code callback
+ * @pw: Data registered with the handler
+ * @release: Whether this is a release or a return.
+ *
+ * Called by the FIQ code when another module wants to use the FIQ, so
+ * return whether we are currently using this or not and then update our
+ * internal state.
+ */
+static int s3c24xx_spi_fiqop(void *pw, int release)
+{
+	struct s3c24xx_spi *hw = pw;
+	int ret = 0;
+
+	if (release) {
+		if (hw->fiq_inuse)
+			ret = -EBUSY;
+
+		/* note, we do not need to unroute the FIQ, as the FIQ
+		 * vector code de-routes it to signal the end of transfer */
+
+		hw->fiq_mode = FIQ_MODE_NONE;
+		hw->fiq_claimed = 0;
+	} else {
+		hw->fiq_claimed = 1;
+	}
+
+	return ret;
+}
+
+/**
+ * s3c24xx_spi_initfiq - setup the information for the FIQ core
+ * @hw: The hardware state.
+ *
+ * Setup the fiq_handler block to pass to the FIQ core.
+ */
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *hw)
+{
+	hw->fiq_handler.dev_id = hw;
+	hw->fiq_handler.name = dev_name(hw->dev);
+	hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop;
+}
+
+/**
+ * s3c24xx_spi_usefiq - return if we should be using FIQ.
+ * @hw: The hardware state.
+ *
+ * Return true if the platform data specifies whether this channel is
+ * allowed to use the FIQ.
+ */
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *hw)
+{
+	return hw->pdata->use_fiq;
+}
+
+/**
+ * s3c24xx_spi_usingfiq - return if channel is using FIQ
+ * @spi: The hardware state.
+ *
+ * Return whether the channel is currently using the FIQ (separate from
+ * whether the FIQ is claimed).
+ */
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *spi)
+{
+	return spi->fiq_inuse;
+}
+#else
+
+static inline void s3c24xx_spi_initfiq(struct s3c24xx_spi *s) { }
+static inline void s3c24xx_spi_tryfiq(struct s3c24xx_spi *s) { }
+static inline bool s3c24xx_spi_usefiq(struct s3c24xx_spi *s) { return false; }
+static inline bool s3c24xx_spi_usingfiq(struct s3c24xx_spi *s) { return false; }
+
+#endif /* CONFIG_SPI_S3C24XX_FIQ */
+
 static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 {
 	struct s3c24xx_spi *hw = to_hw(spi);
 
-	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
-		t->tx_buf, t->rx_buf, t->len);
-
 	hw->tx = t->tx_buf;
 	hw->rx = t->rx_buf;
 	hw->len = t->len;
@@ -228,11 +429,14 @@
 
 	init_completion(&hw->done);
 
+	hw->fiq_inuse = 0;
+	if (s3c24xx_spi_usefiq(hw) && t->len >= 3)
+		s3c24xx_spi_tryfiq(hw);
+
 	/* send the first byte */
 	writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT);
 
 	wait_for_completion(&hw->done);
-
 	return hw->count;
 }
 
@@ -254,17 +458,27 @@
 		goto irq_done;
 	}
 
-	hw->count++;
+	if (!s3c24xx_spi_usingfiq(hw)) {
+		hw->count++;
 
-	if (hw->rx)
-		hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
+		if (hw->rx)
+			hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT);
 
-	count++;
+		count++;
 
-	if (count < hw->len)
-		writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
-	else
+		if (count < hw->len)
+			writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT);
+		else
+			complete(&hw->done);
+	} else {
+		hw->count = hw->len;
+		hw->fiq_inuse = 0;
+
+		if (hw->rx)
+			hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT);
+
 		complete(&hw->done);
+	}
 
  irq_done:
 	return IRQ_HANDLED;
@@ -322,6 +536,10 @@
 	platform_set_drvdata(pdev, hw);
 	init_completion(&hw->done);
 
+	/* initialise fiq handler */
+
+	s3c24xx_spi_initfiq(hw);
+
 	/* setup the master state. */
 
 	/* the spi->mode bits understood by this driver: */
diff --git a/drivers/spi/spi_s3c24xx_fiq.S b/drivers/spi/spi_s3c24xx_fiq.S
new file mode 100644
index 0000000..3793cae
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx_fiq.S
@@ -0,0 +1,116 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.S
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer code
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#include <mach/map.h>
+#include <mach/regs-irq.h>
+#include <plat/regs-spi.h>
+
+#include "spi_s3c24xx_fiq.h"
+
+	.text
+
+	@ entry to these routines is as follows, with the register names
+	@ defined in fiq.h so that they can be shared with the C files which
+	@ setup the calling registers.
+	@
+	@ fiq_rirq	The base of the IRQ registers to find S3C2410_SRCPND
+	@ fiq_rtmp	Temporary register to hold tx/rx data
+	@ fiq_rspi	The base of the SPI register block
+	@ fiq_rtx	The tx buffer pointer
+	@ fiq_rrx	The rx buffer pointer
+	@ fiq_rcount	The number of bytes to move
+
+	@ each entry starts with a word entry of how long it is
+	@ and an offset to the irq acknowledgment word
+
+ENTRY(s3c24xx_spi_fiq_rx)
+s3c24xx_spi_fix_rx:
+	.word	fiq_rx_end - fiq_rx_start
+	.word	fiq_rx_irq_ack - fiq_rx_start
+fiq_rx_start:
+	ldr	fiq_rtmp, fiq_rx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+	strb	fiq_rtmp, [ fiq_rrx ], #1
+
+	mov	fiq_rtmp, #0xff
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	@@ set IRQ controller so that next op will trigger IRQ
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_rx_irq_ack:
+	.word	0
+fiq_rx_end:
+
+ENTRY(s3c24xx_spi_fiq_txrx)
+s3c24xx_spi_fiq_txrx:
+	.word	fiq_txrx_end - fiq_txrx_start
+	.word	fiq_txrx_irq_ack - fiq_txrx_start
+fiq_txrx_start:
+
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+	strb	fiq_rtmp, [ fiq_rrx ], #1
+
+	ldr	fiq_rtmp, fiq_txrx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rtx ], #1
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_txrx_irq_ack:
+	.word	0
+
+fiq_txrx_end:
+
+ENTRY(s3c24xx_spi_fiq_tx)
+s3c24xx_spi_fix_tx:
+	.word	fiq_tx_end - fiq_tx_start
+	.word	fiq_tx_irq_ack - fiq_tx_start
+fiq_tx_start:
+	ldrb	fiq_rtmp, [ fiq_rspi, #  S3C2410_SPRDAT ]
+
+	ldr	fiq_rtmp, fiq_tx_irq_ack
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_SRCPND - S3C24XX_VA_IRQ ]
+
+	ldrb	fiq_rtmp, [ fiq_rtx ], #1
+	strb	fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ]
+
+	subs	fiq_rcount, fiq_rcount, #1
+	subnes	pc, lr, #4		@@ return, still have work to do
+
+	mov	fiq_rtmp, #0
+	str	fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD  - S3C24XX_VA_IRQ ]
+	subs	pc, lr, #4
+
+fiq_tx_irq_ack:
+	.word	0
+
+fiq_tx_end:
+
+	.end
diff --git a/drivers/spi/spi_s3c24xx_fiq.h b/drivers/spi/spi_s3c24xx_fiq.h
new file mode 100644
index 0000000..a5950bb
--- /dev/null
+++ b/drivers/spi/spi_s3c24xx_fiq.h
@@ -0,0 +1,26 @@
+/* linux/drivers/spi/spi_s3c24xx_fiq.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX SPI - FIQ pseudo-DMA transfer support
+ *
+ * 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.
+*/
+
+/* We have R8 through R13 to play with */
+
+#ifdef __ASSEMBLY__
+#define __REG_NR(x)     r##x
+#else
+#define __REG_NR(x)     (x)
+#endif
+
+#define fiq_rspi	__REG_NR(8)
+#define fiq_rtmp	__REG_NR(9)
+#define fiq_rrx		__REG_NR(10)
+#define fiq_rtx		__REG_NR(11)
+#define fiq_rcount	__REG_NR(12)
+#define fiq_rirq	__REG_NR(13)
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
new file mode 100644
index 0000000..88a456d
--- /dev/null
+++ b/drivers/spi/spi_s3c64xx.c
@@ -0,0 +1,1196 @@
+/* linux/drivers/spi/spi_s3c64xx.c
+ *
+ * Copyright (C) 2009 Samsung Electronics Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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/workqueue.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+#include <plat/spi.h>
+
+/* Registers and bit-fields */
+
+#define S3C64XX_SPI_CH_CFG		0x00
+#define S3C64XX_SPI_CLK_CFG		0x04
+#define S3C64XX_SPI_MODE_CFG	0x08
+#define S3C64XX_SPI_SLAVE_SEL	0x0C
+#define S3C64XX_SPI_INT_EN		0x10
+#define S3C64XX_SPI_STATUS		0x14
+#define S3C64XX_SPI_TX_DATA		0x18
+#define S3C64XX_SPI_RX_DATA		0x1C
+#define S3C64XX_SPI_PACKET_CNT	0x20
+#define S3C64XX_SPI_PENDING_CLR	0x24
+#define S3C64XX_SPI_SWAP_CFG	0x28
+#define S3C64XX_SPI_FB_CLK		0x2C
+
+#define S3C64XX_SPI_CH_HS_EN		(1<<6)	/* High Speed Enable */
+#define S3C64XX_SPI_CH_SW_RST		(1<<5)
+#define S3C64XX_SPI_CH_SLAVE		(1<<4)
+#define S3C64XX_SPI_CPOL_L		(1<<3)
+#define S3C64XX_SPI_CPHA_B		(1<<2)
+#define S3C64XX_SPI_CH_RXCH_ON		(1<<1)
+#define S3C64XX_SPI_CH_TXCH_ON		(1<<0)
+
+#define S3C64XX_SPI_CLKSEL_SRCMSK	(3<<9)
+#define S3C64XX_SPI_CLKSEL_SRCSHFT	9
+#define S3C64XX_SPI_ENCLK_ENABLE	(1<<8)
+#define S3C64XX_SPI_PSR_MASK 		0xff
+
+#define S3C64XX_SPI_MODE_CH_TSZ_BYTE		(0<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD	(1<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_WORD		(2<<29)
+#define S3C64XX_SPI_MODE_CH_TSZ_MASK		(3<<29)
+#define S3C64XX_SPI_MODE_BUS_TSZ_BYTE		(0<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD	(1<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_WORD		(2<<17)
+#define S3C64XX_SPI_MODE_BUS_TSZ_MASK		(3<<17)
+#define S3C64XX_SPI_MODE_RXDMA_ON		(1<<2)
+#define S3C64XX_SPI_MODE_TXDMA_ON		(1<<1)
+#define S3C64XX_SPI_MODE_4BURST			(1<<0)
+
+#define S3C64XX_SPI_SLAVE_AUTO			(1<<1)
+#define S3C64XX_SPI_SLAVE_SIG_INACT		(1<<0)
+
+#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
+					(c)->regs + S3C64XX_SPI_SLAVE_SEL)
+
+#define S3C64XX_SPI_INT_TRAILING_EN		(1<<6)
+#define S3C64XX_SPI_INT_RX_OVERRUN_EN		(1<<5)
+#define S3C64XX_SPI_INT_RX_UNDERRUN_EN		(1<<4)
+#define S3C64XX_SPI_INT_TX_OVERRUN_EN		(1<<3)
+#define S3C64XX_SPI_INT_TX_UNDERRUN_EN		(1<<2)
+#define S3C64XX_SPI_INT_RX_FIFORDY_EN		(1<<1)
+#define S3C64XX_SPI_INT_TX_FIFORDY_EN		(1<<0)
+
+#define S3C64XX_SPI_ST_RX_OVERRUN_ERR		(1<<5)
+#define S3C64XX_SPI_ST_RX_UNDERRUN_ERR	(1<<4)
+#define S3C64XX_SPI_ST_TX_OVERRUN_ERR		(1<<3)
+#define S3C64XX_SPI_ST_TX_UNDERRUN_ERR	(1<<2)
+#define S3C64XX_SPI_ST_RX_FIFORDY		(1<<1)
+#define S3C64XX_SPI_ST_TX_FIFORDY		(1<<0)
+
+#define S3C64XX_SPI_PACKET_CNT_EN		(1<<16)
+
+#define S3C64XX_SPI_PND_TX_UNDERRUN_CLR		(1<<4)
+#define S3C64XX_SPI_PND_TX_OVERRUN_CLR		(1<<3)
+#define S3C64XX_SPI_PND_RX_UNDERRUN_CLR		(1<<2)
+#define S3C64XX_SPI_PND_RX_OVERRUN_CLR		(1<<1)
+#define S3C64XX_SPI_PND_TRAILING_CLR		(1<<0)
+
+#define S3C64XX_SPI_SWAP_RX_HALF_WORD		(1<<7)
+#define S3C64XX_SPI_SWAP_RX_BYTE		(1<<6)
+#define S3C64XX_SPI_SWAP_RX_BIT			(1<<5)
+#define S3C64XX_SPI_SWAP_RX_EN			(1<<4)
+#define S3C64XX_SPI_SWAP_TX_HALF_WORD		(1<<3)
+#define S3C64XX_SPI_SWAP_TX_BYTE		(1<<2)
+#define S3C64XX_SPI_SWAP_TX_BIT			(1<<1)
+#define S3C64XX_SPI_SWAP_TX_EN			(1<<0)
+
+#define S3C64XX_SPI_FBCLK_MSK		(3<<0)
+
+#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
+					(((i)->fifo_lvl_mask + 1))) \
+					? 1 : 0)
+
+#define S3C64XX_SPI_ST_TX_DONE(v, i) ((((v) >> (i)->rx_lvl_offset) & \
+					(((i)->fifo_lvl_mask + 1) << 1)) \
+					? 1 : 0)
+#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
+#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
+
+#define S3C64XX_SPI_MAX_TRAILCNT	0x3ff
+#define S3C64XX_SPI_TRAILCNT_OFF	19
+
+#define S3C64XX_SPI_TRAILCNT		S3C64XX_SPI_MAX_TRAILCNT
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+#define SUSPND    (1<<0)
+#define SPIBUSY   (1<<1)
+#define RXBUSY    (1<<2)
+#define TXBUSY    (1<<3)
+
+/**
+ * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
+ * @clk: Pointer to the spi clock.
+ * @master: Pointer to the SPI Protocol master.
+ * @workqueue: Work queue for the SPI xfer requests.
+ * @cntrlr_info: Platform specific data for the controller this driver manages.
+ * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint.
+ * @work: Work
+ * @queue: To log SPI xfer requests.
+ * @lock: Controller specific lock.
+ * @state: Set of FLAGS to indicate status.
+ * @rx_dmach: Controller's DMA channel for Rx.
+ * @tx_dmach: Controller's DMA channel for Tx.
+ * @sfr_start: BUS address of SPI controller regs.
+ * @regs: Pointer to ioremap'ed controller registers.
+ * @xfer_completion: To indicate completion of xfer task.
+ * @cur_mode: Stores the active configuration of the controller.
+ * @cur_bpw: Stores the active bits per word settings.
+ * @cur_speed: Stores the active xfer clock speed.
+ */
+struct s3c64xx_spi_driver_data {
+	void __iomem                    *regs;
+	struct clk                      *clk;
+	struct platform_device          *pdev;
+	struct spi_master               *master;
+	struct workqueue_struct	        *workqueue;
+	struct s3c64xx_spi_cntrlr_info  *cntrlr_info;
+	struct spi_device               *tgl_spi;
+	struct work_struct              work;
+	struct list_head                queue;
+	spinlock_t                      lock;
+	enum dma_ch                     rx_dmach;
+	enum dma_ch                     tx_dmach;
+	unsigned long                   sfr_start;
+	struct completion               xfer_completion;
+	unsigned                        state;
+	unsigned                        cur_mode, cur_bpw;
+	unsigned                        cur_speed;
+};
+
+static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
+	.name = "samsung-spi-dma",
+};
+
+static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned long loops;
+	u32 val;
+
+	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val |= S3C64XX_SPI_CH_SW_RST;
+	val &= ~S3C64XX_SPI_CH_HS_EN;
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	/* Flush TxFIFO*/
+	loops = msecs_to_loops(1);
+	do {
+		val = readl(regs + S3C64XX_SPI_STATUS);
+	} while (TX_FIFO_LVL(val, sci) && loops--);
+
+	/* Flush RxFIFO*/
+	loops = msecs_to_loops(1);
+	do {
+		val = readl(regs + S3C64XX_SPI_STATUS);
+		if (RX_FIFO_LVL(val, sci))
+			readl(regs + S3C64XX_SPI_RX_DATA);
+		else
+			break;
+	} while (loops--);
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~S3C64XX_SPI_CH_SW_RST;
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
+				struct spi_device *spi,
+				struct spi_transfer *xfer, int dma_mode)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	u32 modecfg, chcfg;
+
+	modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
+	modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
+
+	chcfg = readl(regs + S3C64XX_SPI_CH_CFG);
+	chcfg &= ~S3C64XX_SPI_CH_TXCH_ON;
+
+	if (dma_mode) {
+		chcfg &= ~S3C64XX_SPI_CH_RXCH_ON;
+	} else {
+		/* Always shift in data in FIFO, even if xfer is Tx only,
+		 * this helps setting PCKT_CNT value for generating clocks
+		 * as exactly needed.
+		 */
+		chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+		writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+					| S3C64XX_SPI_PACKET_CNT_EN,
+					regs + S3C64XX_SPI_PACKET_CNT);
+	}
+
+	if (xfer->tx_buf != NULL) {
+		sdd->state |= TXBUSY;
+		chcfg |= S3C64XX_SPI_CH_TXCH_ON;
+		if (dma_mode) {
+			modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
+			s3c2410_dma_config(sdd->tx_dmach, 1);
+			s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
+						xfer->tx_dma, xfer->len);
+			s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
+		} else {
+			unsigned char *buf = (unsigned char *) xfer->tx_buf;
+			int i = 0;
+			while (i < xfer->len)
+				writeb(buf[i++], regs + S3C64XX_SPI_TX_DATA);
+		}
+	}
+
+	if (xfer->rx_buf != NULL) {
+		sdd->state |= RXBUSY;
+
+		if (sci->high_speed && sdd->cur_speed >= 30000000UL
+					&& !(sdd->cur_mode & SPI_CPHA))
+			chcfg |= S3C64XX_SPI_CH_HS_EN;
+
+		if (dma_mode) {
+			modecfg |= S3C64XX_SPI_MODE_RXDMA_ON;
+			chcfg |= S3C64XX_SPI_CH_RXCH_ON;
+			writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
+					| S3C64XX_SPI_PACKET_CNT_EN,
+					regs + S3C64XX_SPI_PACKET_CNT);
+			s3c2410_dma_config(sdd->rx_dmach, 1);
+			s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
+						xfer->rx_dma, xfer->len);
+			s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
+		}
+	}
+
+	writel(modecfg, regs + S3C64XX_SPI_MODE_CFG);
+	writel(chcfg, regs + S3C64XX_SPI_CH_CFG);
+}
+
+static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs;
+
+	if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */
+		if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
+			/* Deselect the last toggled device */
+			cs = sdd->tgl_spi->controller_data;
+			cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1);
+		}
+		sdd->tgl_spi = NULL;
+	}
+
+	cs = spi->controller_data;
+	cs->set_level(spi->mode & SPI_CS_HIGH ? 1 : 0);
+}
+
+static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
+				struct spi_transfer *xfer, int dma_mode)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned long val;
+	int ms;
+
+	/* millisecs to xfer 'len' bytes @ 'cur_speed' */
+	ms = xfer->len * 8 * 1000 / sdd->cur_speed;
+	ms += 5; /* some tolerance */
+
+	if (dma_mode) {
+		val = msecs_to_jiffies(ms) + 10;
+		val = wait_for_completion_timeout(&sdd->xfer_completion, val);
+	} else {
+		val = msecs_to_loops(ms);
+		do {
+			val = readl(regs + S3C64XX_SPI_STATUS);
+		} while (RX_FIFO_LVL(val, sci) < xfer->len && --val);
+	}
+
+	if (!val)
+		return -EIO;
+
+	if (dma_mode) {
+		u32 status;
+
+		/*
+		 * DmaTx returns after simply writing data in the FIFO,
+		 * w/o waiting for real transmission on the bus to finish.
+		 * DmaRx returns only after Dma read data from FIFO which
+		 * needs bus transmission to finish, so we don't worry if
+		 * Xfer involved Rx(with or without Tx).
+		 */
+		if (xfer->rx_buf == NULL) {
+			val = msecs_to_loops(10);
+			status = readl(regs + S3C64XX_SPI_STATUS);
+			while ((TX_FIFO_LVL(status, sci)
+				|| !S3C64XX_SPI_ST_TX_DONE(status, sci))
+					&& --val) {
+				cpu_relax();
+				status = readl(regs + S3C64XX_SPI_STATUS);
+			}
+
+			if (!val)
+				return -EIO;
+		}
+	} else {
+		unsigned char *buf;
+		int i;
+
+		/* If it was only Tx */
+		if (xfer->rx_buf == NULL) {
+			sdd->state &= ~TXBUSY;
+			return 0;
+		}
+
+		i = 0;
+		buf = xfer->rx_buf;
+		while (i < xfer->len)
+			buf[i++] = readb(regs + S3C64XX_SPI_RX_DATA);
+
+		sdd->state &= ~RXBUSY;
+	}
+
+	return 0;
+}
+
+static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+
+	if (sdd->tgl_spi == spi)
+		sdd->tgl_spi = NULL;
+
+	cs->set_level(spi->mode & SPI_CS_HIGH ? 0 : 1);
+}
+
+static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	u32 val;
+
+	/* Disable Clock */
+	val = readl(regs + S3C64XX_SPI_CLK_CFG);
+	val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+	/* Set Polarity and Phase */
+	val = readl(regs + S3C64XX_SPI_CH_CFG);
+	val &= ~(S3C64XX_SPI_CH_SLAVE |
+			S3C64XX_SPI_CPOL_L |
+			S3C64XX_SPI_CPHA_B);
+
+	if (sdd->cur_mode & SPI_CPOL)
+		val |= S3C64XX_SPI_CPOL_L;
+
+	if (sdd->cur_mode & SPI_CPHA)
+		val |= S3C64XX_SPI_CPHA_B;
+
+	writel(val, regs + S3C64XX_SPI_CH_CFG);
+
+	/* Set Channel & DMA Mode */
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~(S3C64XX_SPI_MODE_BUS_TSZ_MASK
+			| S3C64XX_SPI_MODE_CH_TSZ_MASK);
+
+	switch (sdd->cur_bpw) {
+	case 32:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_WORD;
+		break;
+	case 16:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_HALFWORD;
+		break;
+	default:
+		val |= S3C64XX_SPI_MODE_BUS_TSZ_BYTE;
+		break;
+	}
+	val |= S3C64XX_SPI_MODE_CH_TSZ_BYTE; /* Always 8bits wide */
+
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	/* Configure Clock */
+	val = readl(regs + S3C64XX_SPI_CLK_CFG);
+	val &= ~S3C64XX_SPI_PSR_MASK;
+	val |= ((clk_get_rate(sci->src_clk) / sdd->cur_speed / 2 - 1)
+			& S3C64XX_SPI_PSR_MASK);
+	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+	/* Enable Clock */
+	val = readl(regs + S3C64XX_SPI_CLK_CFG);
+	val |= S3C64XX_SPI_ENCLK_ENABLE;
+	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+}
+
+void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
+				int size, enum s3c2410_dma_buffresult res)
+{
+	struct s3c64xx_spi_driver_data *sdd = buf_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (res == S3C2410_RES_OK)
+		sdd->state &= ~RXBUSY;
+	else
+		dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
+
+	/* If the other done */
+	if (!(sdd->state & TXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
+				int size, enum s3c2410_dma_buffresult res)
+{
+	struct s3c64xx_spi_driver_data *sdd = buf_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (res == S3C2410_RES_OK)
+		sdd->state &= ~TXBUSY;
+	else
+		dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
+
+	/* If the other done */
+	if (!(sdd->state & RXBUSY))
+		complete(&sdd->xfer_completion);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+}
+
+#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
+
+static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_message *msg)
+{
+	struct device *dev = &sdd->pdev->dev;
+	struct spi_transfer *xfer;
+
+	if (msg->is_dma_mapped)
+		return 0;
+
+	/* First mark all xfer unmapped */
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+		xfer->rx_dma = XFER_DMAADDR_INVALID;
+		xfer->tx_dma = XFER_DMAADDR_INVALID;
+	}
+
+	/* Map until end or first fail */
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		if (xfer->tx_buf != NULL) {
+			xfer->tx_dma = dma_map_single(dev, xfer->tx_buf,
+						xfer->len, DMA_TO_DEVICE);
+			if (dma_mapping_error(dev, xfer->tx_dma)) {
+				dev_err(dev, "dma_map_single Tx failed\n");
+				xfer->tx_dma = XFER_DMAADDR_INVALID;
+				return -ENOMEM;
+			}
+		}
+
+		if (xfer->rx_buf != NULL) {
+			xfer->rx_dma = dma_map_single(dev, xfer->rx_buf,
+						xfer->len, DMA_FROM_DEVICE);
+			if (dma_mapping_error(dev, xfer->rx_dma)) {
+				dev_err(dev, "dma_map_single Rx failed\n");
+				dma_unmap_single(dev, xfer->tx_dma,
+						xfer->len, DMA_TO_DEVICE);
+				xfer->tx_dma = XFER_DMAADDR_INVALID;
+				xfer->rx_dma = XFER_DMAADDR_INVALID;
+				return -ENOMEM;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
+						struct spi_message *msg)
+{
+	struct device *dev = &sdd->pdev->dev;
+	struct spi_transfer *xfer;
+
+	if (msg->is_dma_mapped)
+		return;
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		if (xfer->rx_buf != NULL
+				&& xfer->rx_dma != XFER_DMAADDR_INVALID)
+			dma_unmap_single(dev, xfer->rx_dma,
+						xfer->len, DMA_FROM_DEVICE);
+
+		if (xfer->tx_buf != NULL
+				&& xfer->tx_dma != XFER_DMAADDR_INVALID)
+			dma_unmap_single(dev, xfer->tx_dma,
+						xfer->len, DMA_TO_DEVICE);
+	}
+}
+
+static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
+					struct spi_message *msg)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	struct spi_device *spi = msg->spi;
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+	struct spi_transfer *xfer;
+	int status = 0, cs_toggle = 0;
+	u32 speed;
+	u8 bpw;
+
+	/* If Master's(controller) state differs from that needed by Slave */
+	if (sdd->cur_speed != spi->max_speed_hz
+			|| sdd->cur_mode != spi->mode
+			|| sdd->cur_bpw != spi->bits_per_word) {
+		sdd->cur_bpw = spi->bits_per_word;
+		sdd->cur_speed = spi->max_speed_hz;
+		sdd->cur_mode = spi->mode;
+		s3c64xx_spi_config(sdd);
+	}
+
+	/* Map all the transfers if needed */
+	if (s3c64xx_spi_map_mssg(sdd, msg)) {
+		dev_err(&spi->dev,
+			"Xfer: Unable to map message buffers!\n");
+		status = -ENOMEM;
+		goto out;
+	}
+
+	/* Configure feedback delay */
+	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);
+
+	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+
+		unsigned long flags;
+		int use_dma;
+
+		INIT_COMPLETION(sdd->xfer_completion);
+
+		/* Only BPW and Speed may change across transfers */
+		bpw = xfer->bits_per_word ? : spi->bits_per_word;
+		speed = xfer->speed_hz ? : spi->max_speed_hz;
+
+		if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) {
+			sdd->cur_bpw = bpw;
+			sdd->cur_speed = speed;
+			s3c64xx_spi_config(sdd);
+		}
+
+		/* Polling method for xfers not bigger than FIFO capacity */
+		if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+			use_dma = 0;
+		else
+			use_dma = 1;
+
+		spin_lock_irqsave(&sdd->lock, flags);
+
+		/* Pending only which is to be done */
+		sdd->state &= ~RXBUSY;
+		sdd->state &= ~TXBUSY;
+
+		enable_datapath(sdd, spi, xfer, use_dma);
+
+		/* Slave Select */
+		enable_cs(sdd, spi);
+
+		/* Start the signals */
+		S3C64XX_SPI_ACT(sdd);
+
+		spin_unlock_irqrestore(&sdd->lock, flags);
+
+		status = wait_for_xfer(sdd, xfer, use_dma);
+
+		/* Quiese the signals */
+		S3C64XX_SPI_DEACT(sdd);
+
+		if (status) {
+			dev_err(&spi->dev, "I/O Error: \
+				rx-%d tx-%d res:rx-%c tx-%c len-%d\n",
+				xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0,
+				(sdd->state & RXBUSY) ? 'f' : 'p',
+				(sdd->state & TXBUSY) ? 'f' : 'p',
+				xfer->len);
+
+			if (use_dma) {
+				if (xfer->tx_buf != NULL
+						&& (sdd->state & TXBUSY))
+					s3c2410_dma_ctrl(sdd->tx_dmach,
+							S3C2410_DMAOP_FLUSH);
+				if (xfer->rx_buf != NULL
+						&& (sdd->state & RXBUSY))
+					s3c2410_dma_ctrl(sdd->rx_dmach,
+							S3C2410_DMAOP_FLUSH);
+			}
+
+			goto out;
+		}
+
+		if (xfer->delay_usecs)
+			udelay(xfer->delay_usecs);
+
+		if (xfer->cs_change) {
+			/* Hint that the next mssg is gonna be
+			   for the same device */
+			if (list_is_last(&xfer->transfer_list,
+						&msg->transfers))
+				cs_toggle = 1;
+			else
+				disable_cs(sdd, spi);
+		}
+
+		msg->actual_length += xfer->len;
+
+		flush_fifo(sdd);
+	}
+
+out:
+	if (!cs_toggle || status)
+		disable_cs(sdd, spi);
+	else
+		sdd->tgl_spi = spi;
+
+	s3c64xx_spi_unmap_mssg(sdd, msg);
+
+	msg->status = status;
+
+	if (msg->complete)
+		msg->complete(msg->context);
+}
+
+static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
+{
+	if (s3c2410_dma_request(sdd->rx_dmach,
+					&s3c64xx_spi_dma_client, NULL) < 0) {
+		dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
+		return 0;
+	}
+	s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
+	s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
+					sdd->sfr_start + S3C64XX_SPI_RX_DATA);
+
+	if (s3c2410_dma_request(sdd->tx_dmach,
+					&s3c64xx_spi_dma_client, NULL) < 0) {
+		dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
+		s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+		return 0;
+	}
+	s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
+	s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
+					sdd->sfr_start + S3C64XX_SPI_TX_DATA);
+
+	return 1;
+}
+
+static void s3c64xx_spi_work(struct work_struct *work)
+{
+	struct s3c64xx_spi_driver_data *sdd = container_of(work,
+					struct s3c64xx_spi_driver_data, work);
+	unsigned long flags;
+
+	/* Acquire DMA channels */
+	while (!acquire_dma(sdd))
+		msleep(10);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	while (!list_empty(&sdd->queue)
+				&& !(sdd->state & SUSPND)) {
+
+		struct spi_message *msg;
+
+		msg = container_of(sdd->queue.next, struct spi_message, queue);
+
+		list_del_init(&msg->queue);
+
+		/* Set Xfer busy flag */
+		sdd->state |= SPIBUSY;
+
+		spin_unlock_irqrestore(&sdd->lock, flags);
+
+		handle_msg(sdd, msg);
+
+		spin_lock_irqsave(&sdd->lock, flags);
+
+		sdd->state &= ~SPIBUSY;
+	}
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	/* Free DMA channels */
+	s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
+	s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+}
+
+static int s3c64xx_spi_transfer(struct spi_device *spi,
+						struct spi_message *msg)
+{
+	struct s3c64xx_spi_driver_data *sdd;
+	unsigned long flags;
+
+	sdd = spi_master_get_devdata(spi->master);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	if (sdd->state & SUSPND) {
+		spin_unlock_irqrestore(&sdd->lock, flags);
+		return -ESHUTDOWN;
+	}
+
+	msg->status = -EINPROGRESS;
+	msg->actual_length = 0;
+
+	list_add_tail(&msg->queue, &sdd->queue);
+
+	queue_work(sdd->workqueue, &sdd->work);
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Here we only check the validity of requested configuration
+ * and save the configuration in a local data-structure.
+ * The controller is actually configured only just before we
+ * get a message to transfer.
+ */
+static int s3c64xx_spi_setup(struct spi_device *spi)
+{
+	struct s3c64xx_spi_csinfo *cs = spi->controller_data;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_cntrlr_info *sci;
+	struct spi_message *msg;
+	u32 psr, speed;
+	unsigned long flags;
+	int err = 0;
+
+	if (cs == NULL || cs->set_level == NULL) {
+		dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
+		return -ENODEV;
+	}
+
+	sdd = spi_master_get_devdata(spi->master);
+	sci = sdd->cntrlr_info;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+
+	list_for_each_entry(msg, &sdd->queue, queue) {
+		/* Is some mssg is already queued for this device */
+		if (msg->spi == spi) {
+			dev_err(&spi->dev,
+				"setup: attempt while mssg in queue!\n");
+			spin_unlock_irqrestore(&sdd->lock, flags);
+			return -EBUSY;
+		}
+	}
+
+	if (sdd->state & SUSPND) {
+		spin_unlock_irqrestore(&sdd->lock, flags);
+		dev_err(&spi->dev,
+			"setup: SPI-%d not active!\n", spi->master->bus_num);
+		return -ESHUTDOWN;
+	}
+
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	if (spi->bits_per_word != 8
+			&& spi->bits_per_word != 16
+			&& spi->bits_per_word != 32) {
+		dev_err(&spi->dev, "setup: %dbits/wrd not supported!\n",
+							spi->bits_per_word);
+		err = -EINVAL;
+		goto setup_exit;
+	}
+
+	/* Check if we can provide the requested rate */
+	speed = clk_get_rate(sci->src_clk) / 2 / (0 + 1); /* Max possible */
+
+	if (spi->max_speed_hz > speed)
+		spi->max_speed_hz = speed;
+
+	psr = clk_get_rate(sci->src_clk) / 2 / spi->max_speed_hz - 1;
+	psr &= S3C64XX_SPI_PSR_MASK;
+	if (psr == S3C64XX_SPI_PSR_MASK)
+		psr--;
+
+	speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1);
+	if (spi->max_speed_hz < speed) {
+		if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+			psr++;
+		} else {
+			err = -EINVAL;
+			goto setup_exit;
+		}
+	}
+
+	speed = clk_get_rate(sci->src_clk) / 2 / (psr + 1);
+	if (spi->max_speed_hz >= speed)
+		spi->max_speed_hz = speed;
+	else
+		err = -EINVAL;
+
+setup_exit:
+
+	/* setup() returns with device de-selected */
+	disable_cs(sdd, spi);
+
+	return err;
+}
+
+static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
+{
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	void __iomem *regs = sdd->regs;
+	unsigned int val;
+
+	sdd->cur_speed = 0;
+
+	S3C64XX_SPI_DEACT(sdd);
+
+	/* Disable Interrupts - we use Polling if not DMA mode */
+	writel(0, regs + S3C64XX_SPI_INT_EN);
+
+	writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+				regs + S3C64XX_SPI_CLK_CFG);
+	writel(0, regs + S3C64XX_SPI_MODE_CFG);
+	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
+
+	/* Clear any irq pending bits */
+	writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
+				regs + S3C64XX_SPI_PENDING_CLR);
+
+	writel(0, regs + S3C64XX_SPI_SWAP_CFG);
+
+	val = readl(regs + S3C64XX_SPI_MODE_CFG);
+	val &= ~S3C64XX_SPI_MODE_4BURST;
+	val &= ~(S3C64XX_SPI_MAX_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+	val |= (S3C64XX_SPI_TRAILCNT << S3C64XX_SPI_TRAILCNT_OFF);
+	writel(val, regs + S3C64XX_SPI_MODE_CFG);
+
+	flush_fifo(sdd);
+}
+
+static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+{
+	struct resource	*mem_res, *dmatx_res, *dmarx_res;
+	struct s3c64xx_spi_driver_data *sdd;
+	struct s3c64xx_spi_cntrlr_info *sci;
+	struct spi_master *master;
+	int ret;
+
+	if (pdev->id < 0) {
+		dev_err(&pdev->dev,
+				"Invalid platform device id-%d\n", pdev->id);
+		return -ENODEV;
+	}
+
+	if (pdev->dev.platform_data == NULL) {
+		dev_err(&pdev->dev, "platform_data missing!\n");
+		return -ENODEV;
+	}
+
+	/* Check for availability of necessary resource */
+
+	dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (dmatx_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
+		return -ENXIO;
+	}
+
+	dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+	if (dmarx_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
+		return -ENXIO;
+	}
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem_res == NULL) {
+		dev_err(&pdev->dev, "Unable to get SPI MEM resource\n");
+		return -ENXIO;
+	}
+
+	master = spi_alloc_master(&pdev->dev,
+				sizeof(struct s3c64xx_spi_driver_data));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "Unable to allocate SPI Master\n");
+		return -ENOMEM;
+	}
+
+	sci = pdev->dev.platform_data;
+
+	platform_set_drvdata(pdev, master);
+
+	sdd = spi_master_get_devdata(master);
+	sdd->master = master;
+	sdd->cntrlr_info = sci;
+	sdd->pdev = pdev;
+	sdd->sfr_start = mem_res->start;
+	sdd->tx_dmach = dmatx_res->start;
+	sdd->rx_dmach = dmarx_res->start;
+
+	sdd->cur_bpw = 8;
+
+	master->bus_num = pdev->id;
+	master->setup = s3c64xx_spi_setup;
+	master->transfer = s3c64xx_spi_transfer;
+	master->num_chipselect = sci->num_cs;
+	master->dma_alignment = 8;
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+	if (request_mem_region(mem_res->start,
+			resource_size(mem_res), pdev->name) == NULL) {
+		dev_err(&pdev->dev, "Req mem region failed\n");
+		ret = -ENXIO;
+		goto err0;
+	}
+
+	sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
+	if (sdd->regs == NULL) {
+		dev_err(&pdev->dev, "Unable to remap IO\n");
+		ret = -ENXIO;
+		goto err1;
+	}
+
+	if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
+		dev_err(&pdev->dev, "Unable to config gpio\n");
+		ret = -EBUSY;
+		goto err2;
+	}
+
+	/* Setup clocks */
+	sdd->clk = clk_get(&pdev->dev, "spi");
+	if (IS_ERR(sdd->clk)) {
+		dev_err(&pdev->dev, "Unable to acquire clock 'spi'\n");
+		ret = PTR_ERR(sdd->clk);
+		goto err3;
+	}
+
+	if (clk_enable(sdd->clk)) {
+		dev_err(&pdev->dev, "Couldn't enable clock 'spi'\n");
+		ret = -EBUSY;
+		goto err4;
+	}
+
+	if (sci->src_clk_nr == S3C64XX_SPI_SRCCLK_PCLK)
+		sci->src_clk = sdd->clk;
+	else
+		sci->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
+	if (IS_ERR(sci->src_clk)) {
+		dev_err(&pdev->dev,
+			"Unable to acquire clock '%s'\n", sci->src_clk_name);
+		ret = PTR_ERR(sci->src_clk);
+		goto err5;
+	}
+
+	if (sci->src_clk != sdd->clk && clk_enable(sci->src_clk)) {
+		dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
+							sci->src_clk_name);
+		ret = -EBUSY;
+		goto err6;
+	}
+
+	sdd->workqueue = create_singlethread_workqueue(
+						dev_name(master->dev.parent));
+	if (sdd->workqueue == NULL) {
+		dev_err(&pdev->dev, "Unable to create workqueue\n");
+		ret = -ENOMEM;
+		goto err7;
+	}
+
+	/* Setup Deufult Mode */
+	s3c64xx_spi_hwinit(sdd, pdev->id);
+
+	spin_lock_init(&sdd->lock);
+	init_completion(&sdd->xfer_completion);
+	INIT_WORK(&sdd->work, s3c64xx_spi_work);
+	INIT_LIST_HEAD(&sdd->queue);
+
+	if (spi_register_master(master)) {
+		dev_err(&pdev->dev, "cannot register SPI master\n");
+		ret = -EBUSY;
+		goto err8;
+	}
+
+	dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d \
+					with %d Slaves attached\n",
+					pdev->id, master->num_chipselect);
+	dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\
+					\tDMA=[Rx-%d, Tx-%d]\n",
+					mem_res->end, mem_res->start,
+					sdd->rx_dmach, sdd->tx_dmach);
+
+	return 0;
+
+err8:
+	destroy_workqueue(sdd->workqueue);
+err7:
+	if (sci->src_clk != sdd->clk)
+		clk_disable(sci->src_clk);
+err6:
+	if (sci->src_clk != sdd->clk)
+		clk_put(sci->src_clk);
+err5:
+	clk_disable(sdd->clk);
+err4:
+	clk_put(sdd->clk);
+err3:
+err2:
+	iounmap((void *) sdd->regs);
+err1:
+	release_mem_region(mem_res->start, resource_size(mem_res));
+err0:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int s3c64xx_spi_remove(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	struct resource	*mem_res;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state |= SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	while (sdd->state & SPIBUSY)
+		msleep(10);
+
+	spi_unregister_master(master);
+
+	destroy_workqueue(sdd->workqueue);
+
+	if (sci->src_clk != sdd->clk)
+		clk_disable(sci->src_clk);
+
+	if (sci->src_clk != sdd->clk)
+		clk_put(sci->src_clk);
+
+	clk_disable(sdd->clk);
+	clk_put(sdd->clk);
+
+	iounmap((void *) sdd->regs);
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem_res->start, resource_size(mem_res));
+
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c64xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	struct s3c64xx_spi_csinfo *cs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state |= SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	while (sdd->state & SPIBUSY)
+		msleep(10);
+
+	/* Disable the clock */
+	if (sci->src_clk != sdd->clk)
+		clk_disable(sci->src_clk);
+
+	clk_disable(sdd->clk);
+
+	sdd->cur_speed = 0; /* Output Clock is stopped */
+
+	return 0;
+}
+
+static int s3c64xx_spi_resume(struct platform_device *pdev)
+{
+	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
+	struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
+	struct s3c64xx_spi_cntrlr_info *sci = sdd->cntrlr_info;
+	unsigned long flags;
+
+	sci->cfg_gpio(pdev);
+
+	/* Enable the clock */
+	if (sci->src_clk != sdd->clk)
+		clk_enable(sci->src_clk);
+
+	clk_enable(sdd->clk);
+
+	s3c64xx_spi_hwinit(sdd, pdev->id);
+
+	spin_lock_irqsave(&sdd->lock, flags);
+	sdd->state &= ~SUSPND;
+	spin_unlock_irqrestore(&sdd->lock, flags);
+
+	return 0;
+}
+#else
+#define s3c64xx_spi_suspend	NULL
+#define s3c64xx_spi_resume	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver s3c64xx_spi_driver = {
+	.driver = {
+		.name	= "s3c64xx-spi",
+		.owner = THIS_MODULE,
+	},
+	.remove = s3c64xx_spi_remove,
+	.suspend = s3c64xx_spi_suspend,
+	.resume = s3c64xx_spi_resume,
+};
+MODULE_ALIAS("platform:s3c64xx-spi");
+
+static int __init s3c64xx_spi_init(void)
+{
+	return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
+}
+module_init(s3c64xx_spi_init);
+
+static void __exit s3c64xx_spi_exit(void)
+{
+	platform_driver_unregister(&s3c64xx_spi_driver);
+}
+module_exit(s3c64xx_spi_exit);
+
+MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>");
+MODULE_DESCRIPTION("S3C64XX SPI Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c
index 7d36720..a65c12f 100644
--- a/drivers/spi/spi_sh_sci.c
+++ b/drivers/spi/spi_sh_sci.c
@@ -148,7 +148,7 @@
 		ret = -ENOENT;
 		goto err1;
 	}
-	sp->membase = ioremap(r->start, r->end - r->start + 1);
+	sp->membase = ioremap(r->start, resource_size(r));
 	if (!sp->membase) {
 		ret = -ENXIO;
 		goto err1;
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
index 19f7562..dfa024b 100644
--- a/drivers/spi/spi_txx9.c
+++ b/drivers/spi/spi_txx9.c
@@ -375,12 +375,10 @@
 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
 	if (!res)
 		goto exit_busy;
-	if (!devm_request_mem_region(&dev->dev,
-				     res->start, res->end - res->start + 1,
+	if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res),
 				     "spi_txx9"))
 		goto exit_busy;
-	c->membase = devm_ioremap(&dev->dev,
-				  res->start, res->end - res->start + 1);
+	c->membase = devm_ioremap(&dev->dev, res->start, resource_size(res));
 	if (!c->membase)
 		goto exit_busy;
 
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 9c446e6..ea1bec3 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -53,7 +53,7 @@
 #define SPIDEV_MAJOR			153	/* assigned */
 #define N_SPI_MINORS			32	/* ... up to 256 */
 
-static unsigned long	minors[N_SPI_MINORS / BITS_PER_LONG];
+static DECLARE_BITMAP(minors, N_SPI_MINORS);
 
 
 /* Bit masks for spi_device.mode management.  Note that incorrect
@@ -558,7 +558,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int spidev_probe(struct spi_device *spi)
+static int __devinit spidev_probe(struct spi_device *spi)
 {
 	struct spidev_data	*spidev;
 	int			status;
@@ -607,7 +607,7 @@
 	return status;
 }
 
-static int spidev_remove(struct spi_device *spi)
+static int __devexit spidev_remove(struct spi_device *spi)
 {
 	struct spidev_data	*spidev = spi_get_drvdata(spi);
 
@@ -629,7 +629,7 @@
 	return 0;
 }
 
-static struct spi_driver spidev_spi = {
+static struct spi_driver spidev_spi_driver = {
 	.driver = {
 		.name =		"spidev",
 		.owner =	THIS_MODULE,
@@ -661,14 +661,14 @@
 
 	spidev_class = class_create(THIS_MODULE, "spidev");
 	if (IS_ERR(spidev_class)) {
-		unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+		unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 		return PTR_ERR(spidev_class);
 	}
 
-	status = spi_register_driver(&spidev_spi);
+	status = spi_register_driver(&spidev_spi_driver);
 	if (status < 0) {
 		class_destroy(spidev_class);
-		unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+		unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 	}
 	return status;
 }
@@ -676,9 +676,9 @@
 
 static void __exit spidev_exit(void)
 {
-	spi_unregister_driver(&spidev_spi);
+	spi_unregister_driver(&spidev_spi_driver);
 	class_destroy(spidev_class);
-	unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
+	unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name);
 }
 module_exit(spidev_exit);
 
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 54e174d2..093f57a 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -99,6 +99,8 @@
 
 source "drivers/staging/line6/Kconfig"
 
+source "drivers/gpu/drm/vmwgfx/Kconfig"
+
 source "drivers/gpu/drm/radeon/Kconfig"
 
 source "drivers/gpu/drm/nouveau/Kconfig"
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c
index f78b891..89c8fe2 100644
--- a/drivers/staging/cx25821/cx25821-audups11.c
+++ b/drivers/staging/cx25821/cx25821-audups11.c
@@ -94,36 +94,20 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH11]
-		    && h->video_dev[SRAM_CH11]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -427,7 +411,6 @@
 struct video_device cx25821_video_template11 = {
 	.name = "cx25821-audioupstream",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
index 8834bc8..c7c14c7 100644
--- a/drivers/staging/cx25821/cx25821-video.c
+++ b/drivers/staging/cx25821/cx25821-video.c
@@ -184,11 +184,11 @@
 	if (NULL == vfd)
 		return NULL;
 	*vfd = *template;
-	vfd->minor = -1;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->release = video_device_release;
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
 		 cx25821_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
 	return vfd;
 }
 
@@ -424,7 +424,7 @@
 void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
 {
 	if (dev->ioctl_dev) {
-		if (dev->ioctl_dev->minor != -1)
+		if (video_is_registered(dev->ioctl_dev))
 			video_unregister_device(dev->ioctl_dev);
 		else
 			video_device_release(dev->ioctl_dev);
@@ -438,7 +438,7 @@
 	cx_clear(PCI_INT_MSK, 1);
 
 	if (dev->video_dev[chan_num]) {
-		if (-1 != dev->video_dev[chan_num]->minor)
+		if (video_is_registered(dev->video_dev[chan_num]))
 			video_unregister_device(dev->video_dev[chan_num]);
 		else
 			video_device_release(dev->video_dev[chan_num]);
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c
index 950fac1..ad7a691 100644
--- a/drivers/staging/cx25821/cx25821-video0.c
+++ b/drivers/staging/cx25821/cx25821-video0.c
@@ -94,37 +94,21 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH00]
-		    && h->video_dev[SRAM_CH00]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -444,7 +428,6 @@
 struct video_device cx25821_video_template0 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c
index a4dddc68..e3f3c4a 100644
--- a/drivers/staging/cx25821/cx25821-video1.c
+++ b/drivers/staging/cx25821/cx25821-video1.c
@@ -94,37 +94,21 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH01]
-		    && h->video_dev[SRAM_CH01]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -444,7 +428,6 @@
 struct video_device cx25821_video_template1 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c
index 8e04e25..36fb855 100644
--- a/drivers/staging/cx25821/cx25821-video2.c
+++ b/drivers/staging/cx25821/cx25821-video2.c
@@ -94,37 +94,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH02]
-		    && h->video_dev[SRAM_CH02]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -445,7 +430,6 @@
 struct video_device cx25821_video_template2 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c
index 8801a8e..1e0f10a 100644
--- a/drivers/staging/cx25821/cx25821-video3.c
+++ b/drivers/staging/cx25821/cx25821-video3.c
@@ -94,37 +94,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH03]
-		    && h->video_dev[SRAM_CH03]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -444,7 +429,6 @@
 struct video_device cx25821_video_template3 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c
index ab0d747..0cbe7a7 100644
--- a/drivers/staging/cx25821/cx25821-video4.c
+++ b/drivers/staging/cx25821/cx25821-video4.c
@@ -94,37 +94,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH04]
-		    && h->video_dev[SRAM_CH04]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -443,7 +428,6 @@
 struct video_device cx25821_video_template4 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c
index 7ef0b97..5dc08ad 100644
--- a/drivers/staging/cx25821/cx25821-video5.c
+++ b/drivers/staging/cx25821/cx25821-video5.c
@@ -94,37 +94,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH05]
-		    && h->video_dev[SRAM_CH05]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -443,7 +428,6 @@
 struct video_device cx25821_video_template5 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c
index 3c41b49..2938ad3 100644
--- a/drivers/staging/cx25821/cx25821-video6.c
+++ b/drivers/staging/cx25821/cx25821-video6.c
@@ -94,37 +94,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH06]
-		    && h->video_dev[SRAM_CH06]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -443,7 +428,6 @@
 struct video_device cx25821_video_template6 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c
index 625c9b7..458e525 100644
--- a/drivers/staging/cx25821/cx25821-video7.c
+++ b/drivers/staging/cx25821/cx25821-video7.c
@@ -93,37 +93,22 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH07]
-		    && h->video_dev[SRAM_CH07]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
+
 	file->private_data = fh;
 	fh->dev = dev;
 	fh->type = type;
@@ -442,7 +427,6 @@
 struct video_device cx25821_video_template7 = {
 	.name = "cx25821-video",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c
index 2a312ce..1da52b5 100644
--- a/drivers/staging/cx25821/cx25821-videoioctl.c
+++ b/drivers/staging/cx25821/cx25821-videoioctl.c
@@ -94,36 +94,21 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	u32 pix_format;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->ioctl_dev && h->ioctl_dev->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -489,7 +474,6 @@
 struct video_device cx25821_videoioctl_template = {
 	.name = "cx25821-videoioctl",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c
index 77b63b0..b76d9f6 100644
--- a/drivers/staging/cx25821/cx25821-vidups10.c
+++ b/drivers/staging/cx25821/cx25821-vidups10.c
@@ -94,36 +94,20 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH10]
-		    && h->video_dev[SRAM_CH10]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -428,7 +412,6 @@
 struct video_device cx25821_video_template10 = {
 	.name = "cx25821-upstream10",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c
index 75c8c1e..1580da3 100644
--- a/drivers/staging/cx25821/cx25821-vidups9.c
+++ b/drivers/staging/cx25821/cx25821-vidups9.c
@@ -94,36 +94,20 @@
 
 static int video_open(struct file *file)
 {
-	int minor = video_devdata(file)->minor;
-	struct cx25821_dev *h, *dev = NULL;
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *dev = video_drvdata(file);
 	struct cx25821_fh *fh;
-	struct list_head *list;
-	enum v4l2_buf_type type = 0;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	lock_kernel();
-	list_for_each(list, &cx25821_devlist) {
-		h = list_entry(list, struct cx25821_dev, devlist);
-
-		if (h->video_dev[SRAM_CH09]
-		    && h->video_dev[SRAM_CH09]->minor == minor) {
-			dev = h;
-			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-		}
-	}
-
-	if (NULL == dev) {
-		unlock_kernel();
-		return -ENODEV;
-	}
-
-	printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+	printk("open dev=%s type=%s\n", video_device_node_name(vdev),
+		v4l2_type_names[type]);
 
 	/* allocate + initialize per filehandle data */
 	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-	if (NULL == fh) {
-		unlock_kernel();
+	if (NULL == fh)
 		return -ENOMEM;
-	}
+
+	lock_kernel();
 
 	file->private_data = fh;
 	fh->dev = dev;
@@ -426,7 +410,6 @@
 struct video_device cx25821_video_template9 = {
 	.name = "cx25821-upstream9",
 	.fops = &video_fops,
-	.minor = -1,
 	.ioctl_ops = &video_ioctl_ops,
 	.tvnorms = CX25821_NORMS,
 	.current_norm = V4L2_STD_NTSC_M,
diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c
index fd5bd0e..c83ca7e 100644
--- a/drivers/staging/dst/dcore.c
+++ b/drivers/staging/dst/dcore.c
@@ -403,7 +403,7 @@
 
 	if (n->bdev) {
 		sync_blockdev(n->bdev);
-		blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
+		close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
 	}
 
 	dst_state_lock(st);
@@ -464,37 +464,6 @@
 }
 
 /*
- * This function finds devices major/minor numbers for given pathname.
- */
-static int dst_lookup_device(const char *path, dev_t *dev)
-{
-	int err;
-	struct nameidata nd;
-	struct inode *inode;
-
-	err = path_lookup(path, LOOKUP_FOLLOW, &nd);
-	if (err)
-		return err;
-
-	inode = nd.path.dentry->d_inode;
-	if (!inode) {
-		err = -ENOENT;
-		goto out;
-	}
-
-	if (!S_ISBLK(inode->i_mode)) {
-		err = -ENOTBLK;
-		goto out;
-	}
-
-	*dev = inode->i_rdev;
-
-out:
-	path_put(&nd.path);
-	return err;
-}
-
-/*
  * Setting up export device: lookup by the name, get its size
  * and setup listening socket, which will accept clients, which
  * will submit IO for given storage.
@@ -503,17 +472,12 @@
 		struct dst_export_ctl *le)
 {
 	int err;
-	dev_t dev = 0; /* gcc likes to scream here */
 
 	snprintf(n->info->local, sizeof(n->info->local), "%s", le->device);
 
-	err = dst_lookup_device(le->device, &dev);
-	if (err)
-		return err;
-
-	n->bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
-	if (!n->bdev)
-		return -ENODEV;
+	n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL);
+	if (IS_ERR(n->bdev))
+		return PTR_ERR(n->bdev);
 
 	if (n->size != 0)
 		n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size);
@@ -528,7 +492,7 @@
 	return 0;
 
 err_out_cleanup:
-	blkdev_put(n->bdev, FMODE_READ|FMODE_WRITE);
+	close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE);
 	n->bdev = NULL;
 
 	return err;
diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c
index b18d8e2..3af7924 100644
--- a/drivers/staging/go7007/go7007-v4l2.c
+++ b/drivers/staging/go7007/go7007-v4l2.c
@@ -1787,7 +1787,6 @@
 static struct video_device go7007_template = {
 	.name		= "go7007",
 	.fops		= &go7007_fops,
-	.minor		= -1,
 	.release	= go7007_vfl_release,
 	.ioctl_ops	= &video_ioctl_ops,
 	.tvnorms	= V4L2_STD_ALL,
@@ -1817,8 +1816,8 @@
 	}
 	video_set_drvdata(go->video_dev, go);
 	++go->ref_count;
-	printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
-	       go->video_dev->name, go->video_dev->num);
+	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+	       go->video_dev->name, video_device_node_name(go->video_dev));
 
 	return 0;
 }
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index f0b86f0..fd677f0 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -29,7 +29,6 @@
  * driver requests - some may support multiple options */
 
 
-#include <linux/autoconf.h>
 #include "iio.h"
 #include "ring_generic.h"
 
diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig
index 536e238..638ad6b 100644
--- a/drivers/staging/octeon/Kconfig
+++ b/drivers/staging/octeon/Kconfig
@@ -1,7 +1,8 @@
 config OCTEON_ETHERNET
 	tristate "Cavium Networks Octeon Ethernet support"
 	depends on CPU_CAVIUM_OCTEON
-	select MII
+	select PHYLIB
+	select MDIO_OCTEON
 	help
 	  This driver supports the builtin ethernet ports on Cavium
 	  Networks' products in the Octeon family. This driver supports the
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c
index 31a58e5..05a5cc0 100644
--- a/drivers/staging/octeon/ethernet-mdio.c
+++ b/drivers/staging/octeon/ethernet-mdio.c
@@ -26,7 +26,8 @@
 **********************************************************************/
 #include <linux/kernel.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
+
 #include <net/dst.h>
 
 #include <asm/octeon/octeon.h>
@@ -34,86 +35,12 @@
 #include "ethernet-defines.h"
 #include "octeon-ethernet.h"
 #include "ethernet-mdio.h"
+#include "ethernet-util.h"
 
 #include "cvmx-helper-board.h"
 
 #include "cvmx-smix-defs.h"
 
-DECLARE_MUTEX(mdio_sem);
-
-/**
- * Perform an MII read. Called by the generic MII routines
- *
- * @dev:      Device to perform read for
- * @phy_id:   The MII phy id
- * @location: Register location to read
- * Returns Result from the read or zero on failure
- */
-static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location)
-{
-	union cvmx_smix_cmd smi_cmd;
-	union cvmx_smix_rd_dat smi_rd;
-
-	smi_cmd.u64 = 0;
-	smi_cmd.s.phy_op = 1;
-	smi_cmd.s.phy_adr = phy_id;
-	smi_cmd.s.reg_adr = location;
-	cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
-
-	do {
-		if (!in_interrupt())
-			yield();
-		smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0));
-	} while (smi_rd.s.pending);
-
-	if (smi_rd.s.val)
-		return smi_rd.s.dat;
-	else
-		return 0;
-}
-
-static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id,
-				   int location)
-{
-	return 0xffff;
-}
-
-/**
- * Perform an MII write. Called by the generic MII routines
- *
- * @dev:      Device to perform write for
- * @phy_id:   The MII phy id
- * @location: Register location to write
- * @val:      Value to write
- */
-static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location,
-			       int val)
-{
-	union cvmx_smix_cmd smi_cmd;
-	union cvmx_smix_wr_dat smi_wr;
-
-	smi_wr.u64 = 0;
-	smi_wr.s.dat = val;
-	cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64);
-
-	smi_cmd.u64 = 0;
-	smi_cmd.s.phy_op = 0;
-	smi_cmd.s.phy_adr = phy_id;
-	smi_cmd.s.reg_adr = location;
-	cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64);
-
-	do {
-		if (!in_interrupt())
-			yield();
-		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0));
-	} while (smi_wr.s.pending);
-}
-
-static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id,
-				     int location, int val)
-{
-}
-
 static void cvm_oct_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
@@ -125,49 +52,37 @@
 static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
-	int ret;
 
-	down(&mdio_sem);
-	ret = mii_ethtool_gset(&priv->mii_info, cmd);
-	up(&mdio_sem);
+	if (priv->phydev)
+		return phy_ethtool_gset(priv->phydev, cmd);
 
-	return ret;
+	return -EINVAL;
 }
 
 static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
-	int ret;
 
-	down(&mdio_sem);
-	ret = mii_ethtool_sset(&priv->mii_info, cmd);
-	up(&mdio_sem);
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
 
-	return ret;
+	if (priv->phydev)
+		return phy_ethtool_sset(priv->phydev, cmd);
+
+	return -EINVAL;
 }
 
 static int cvm_oct_nway_reset(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
-	int ret;
 
-	down(&mdio_sem);
-	ret = mii_nway_restart(&priv->mii_info);
-	up(&mdio_sem);
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
 
-	return ret;
-}
+	if (priv->phydev)
+		return phy_start_aneg(priv->phydev);
 
-static u32 cvm_oct_get_link(struct net_device *dev)
-{
-	struct octeon_ethernet *priv = netdev_priv(dev);
-	u32 ret;
-
-	down(&mdio_sem);
-	ret = mii_link_ok(&priv->mii_info);
-	up(&mdio_sem);
-
-	return ret;
+	return -EINVAL;
 }
 
 const struct ethtool_ops cvm_oct_ethtool_ops = {
@@ -175,7 +90,7 @@
 	.get_settings = cvm_oct_get_settings,
 	.set_settings = cvm_oct_set_settings,
 	.nway_reset = cvm_oct_nway_reset,
-	.get_link = cvm_oct_get_link,
+	.get_link = ethtool_op_get_link,
 	.get_sg = ethtool_op_get_sg,
 	.get_tx_csum = ethtool_op_get_tx_csum,
 };
@@ -191,41 +106,78 @@
 int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
-	struct mii_ioctl_data *data = if_mii(rq);
-	unsigned int duplex_chg;
-	int ret;
 
-	down(&mdio_sem);
-	ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg);
-	up(&mdio_sem);
+	if (!netif_running(dev))
+		return -EINVAL;
 
-	return ret;
+	if (!priv->phydev)
+		return -EINVAL;
+
+	return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
 }
 
+static void cvm_oct_adjust_link(struct net_device *dev)
+{
+	struct octeon_ethernet *priv = netdev_priv(dev);
+	cvmx_helper_link_info_t link_info;
+
+	if (priv->last_link != priv->phydev->link) {
+		priv->last_link = priv->phydev->link;
+		link_info.u64 = 0;
+		link_info.s.link_up = priv->last_link ? 1 : 0;
+		link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0;
+		link_info.s.speed = priv->phydev->speed;
+		cvmx_helper_link_set( priv->port, link_info);
+		if (priv->last_link) {
+			netif_carrier_on(dev);
+			if (priv->queue != -1)
+				DEBUGPRINT("%s: %u Mbps %s duplex, "
+					   "port %2d, queue %2d\n",
+					   dev->name, priv->phydev->speed,
+					   priv->phydev->duplex ?
+						"Full" : "Half",
+					   priv->port, priv->queue);
+			else
+				DEBUGPRINT("%s: %u Mbps %s duplex, "
+					   "port %2d, POW\n",
+					   dev->name, priv->phydev->speed,
+					   priv->phydev->duplex ?
+						"Full" : "Half",
+					   priv->port);
+		} else {
+			netif_carrier_off(dev);
+			DEBUGPRINT("%s: Link down\n", dev->name);
+		}
+	}
+}
+
+
 /**
- * Setup the MDIO device structures
+ * Setup the PHY
  *
  * @dev:    Device to setup
  *
  * Returns Zero on success, negative on failure
  */
-int cvm_oct_mdio_setup_device(struct net_device *dev)
+int cvm_oct_phy_setup_device(struct net_device *dev)
 {
 	struct octeon_ethernet *priv = netdev_priv(dev);
-	int phy_id = cvmx_helper_board_get_mii_address(priv->port);
-	if (phy_id != -1) {
-		priv->mii_info.dev = dev;
-		priv->mii_info.phy_id = phy_id;
-		priv->mii_info.phy_id_mask = 0xff;
-		priv->mii_info.supports_gmii = 1;
-		priv->mii_info.reg_num_mask = 0x1f;
-		priv->mii_info.mdio_read = cvm_oct_mdio_read;
-		priv->mii_info.mdio_write = cvm_oct_mdio_write;
-	} else {
-		/* Supply dummy MDIO routines so the kernel won't crash
-		   if the user tries to read them */
-		priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read;
-		priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write;
+
+	int phy_addr = cvmx_helper_board_get_mii_address(priv->port);
+	if (phy_addr != -1) {
+		char phy_id[20];
+
+		snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr);
+
+		priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0,
+					PHY_INTERFACE_MODE_GMII);
+
+		if (IS_ERR(priv->phydev)) {
+			priv->phydev = NULL;
+			return -1;
+		}
+		priv->last_link = 0;
+		phy_start_aneg(priv->phydev);
 	}
 	return 0;
 }
diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h
index b3328ae..55d0614a 100644
--- a/drivers/staging/octeon/ethernet-mdio.h
+++ b/drivers/staging/octeon/ethernet-mdio.h
@@ -43,4 +43,4 @@
 
 extern const struct ethtool_ops cvm_oct_ethtool_ops;
 int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-int cvm_oct_mdio_setup_device(struct net_device *dev);
+int cvm_oct_phy_setup_device(struct net_device *dev);
diff --git a/drivers/staging/octeon/ethernet-proc.c b/drivers/staging/octeon/ethernet-proc.c
index 8fa88fc..16308d4 100644
--- a/drivers/staging/octeon/ethernet-proc.c
+++ b/drivers/staging/octeon/ethernet-proc.c
@@ -25,7 +25,6 @@
  * Contact Cavium Networks for more information
 **********************************************************************/
 #include <linux/kernel.h>
-#include <linux/mii.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <net/dst.h>
@@ -38,112 +37,6 @@
 #include "cvmx-helper.h"
 #include "cvmx-pip.h"
 
-static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev,
-						    int phy_id, int offset)
-{
-	struct octeon_ethernet *priv = netdev_priv(dev);
-
-	priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset);
-	return ((uint64_t) priv->mii_info.
-		mdio_read(dev, phy_id,
-			  0x1e) << 16) | (uint64_t) priv->mii_info.
-	    mdio_read(dev, phy_id, 0x1f);
-}
-
-static int cvm_oct_stats_switch_show(struct seq_file *m, void *v)
-{
-	static const int ports[] = { 0, 1, 2, 3, 9, -1 };
-	struct net_device *dev = cvm_oct_device[0];
-	int index = 0;
-
-	while (ports[index] != -1) {
-
-		/* Latch port */
-		struct octeon_ethernet *priv = netdev_priv(dev);
-
-		priv->mii_info.mdio_write(dev, 0x1b, 0x1d,
-					  0xdc00 | ports[index]);
-		seq_printf(m, "\nSwitch Port %d\n", ports[index]);
-		seq_printf(m, "InGoodOctets:   %12llu\t"
-			   "OutOctets:      %12llu\t"
-			   "64 Octets:      %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b,
-						     0x00) |
-			   (cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32),
-			   cvm_oct_stats_read_switch(dev, 0x1b,
-						     0x0E) |
-			   (cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x08));
-
-		seq_printf(m, "InBadOctets:    %12llu\t"
-			   "OutUnicast:     %12llu\t"
-			   "65-127 Octets:  %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x02),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x10),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x09));
-
-		seq_printf(m, "InUnicast:      %12llu\t"
-			   "OutBroadcasts:  %12llu\t"
-			   "128-255 Octets: %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x04),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x13),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x0A));
-
-		seq_printf(m, "InBroadcasts:   %12llu\t"
-			   "OutMulticasts:  %12llu\t"
-			   "256-511 Octets: %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x06),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x12),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x0B));
-
-		seq_printf(m, "InMulticasts:   %12llu\t"
-			   "OutPause:       %12llu\t"
-			   "512-1023 Octets:%12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x07),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x15),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x0C));
-
-		seq_printf(m, "InPause:        %12llu\t"
-			   "Excessive:      %12llu\t"
-			   "1024-Max Octets:%12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x16),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x11),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x0D));
-
-		seq_printf(m, "InUndersize:    %12llu\t"
-			   "Collisions:     %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x18),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1E));
-
-		seq_printf(m, "InFragments:    %12llu\t"
-			   "Deferred:       %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x19),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x05));
-
-		seq_printf(m, "InOversize:     %12llu\t"
-			   "Single:         %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1A),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x14));
-
-		seq_printf(m, "InJabber:       %12llu\t"
-			   "Multiple:       %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1B),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x17));
-
-		seq_printf(m, "In RxErr:       %12llu\t"
-			   "OutFCSErr:      %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1C),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x03));
-
-		seq_printf(m, "InFCSErr:       %12llu\t"
-			   "Late:           %12llu\n",
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1D),
-			   cvm_oct_stats_read_switch(dev, 0x1b, 0x1F));
-		index++;
-	}
-	return 0;
-}
-
 /**
  * User is reading /proc/octeon_ethernet_stats
  *
@@ -215,11 +108,6 @@
 		}
 	}
 
-	if (cvm_oct_device[0]) {
-		priv = netdev_priv(cvm_oct_device[0]);
-		if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
-			cvm_oct_stats_switch_show(m, v);
-	}
 	return 0;
 }
 
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index fbaa465..3820f1e 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -147,32 +147,36 @@
 		cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
 			       gmxx_rxx_int_reg.u64);
 	}
-
-	link_info = cvmx_helper_link_autoconf(priv->port);
-	priv->link_info = link_info.u64;
+	if (priv->phydev == NULL) {
+		link_info = cvmx_helper_link_autoconf(priv->port);
+		priv->link_info = link_info.u64;
+	}
 	spin_unlock_irqrestore(&global_register_lock, flags);
 
-	/* Tell Linux */
-	if (link_info.s.link_up) {
-
-		if (!netif_carrier_ok(dev))
-			netif_carrier_on(dev);
-		if (priv->queue != -1)
-			DEBUGPRINT
-			    ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
-			     dev->name, link_info.s.speed,
-			     (link_info.s.full_duplex) ? "Full" : "Half",
-			     priv->port, priv->queue);
-		else
-			DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
-				   dev->name, link_info.s.speed,
-				   (link_info.s.full_duplex) ? "Full" : "Half",
-				   priv->port);
-	} else {
-
-		if (netif_carrier_ok(dev))
-			netif_carrier_off(dev);
-		DEBUGPRINT("%s: Link down\n", dev->name);
+	if (priv->phydev == NULL) {
+		/* Tell core. */
+		if (link_info.s.link_up) {
+			if (!netif_carrier_ok(dev))
+				netif_carrier_on(dev);
+			if (priv->queue != -1)
+				DEBUGPRINT("%s: %u Mbps %s duplex, "
+					   "port %2d, queue %2d\n",
+					   dev->name, link_info.s.speed,
+					   (link_info.s.full_duplex) ?
+						"Full" : "Half",
+					   priv->port, priv->queue);
+			else
+				DEBUGPRINT("%s: %u Mbps %s duplex, "
+					   "port %2d, POW\n",
+					   dev->name, link_info.s.speed,
+					   (link_info.s.full_duplex) ?
+						"Full" : "Half",
+					   priv->port);
+		} else {
+			if (netif_carrier_ok(dev))
+				netif_carrier_off(dev);
+			DEBUGPRINT("%s: Link down\n", dev->name);
+		}
 	}
 }
 
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c
index 2b54996..6061d01 100644
--- a/drivers/staging/octeon/ethernet-sgmii.c
+++ b/drivers/staging/octeon/ethernet-sgmii.c
@@ -113,7 +113,7 @@
 	struct octeon_ethernet *priv = netdev_priv(dev);
 	cvm_oct_common_init(dev);
 	dev->netdev_ops->ndo_stop(dev);
-	if (!octeon_is_simulation())
+	if (!octeon_is_simulation() && priv->phydev == NULL)
 		priv->poll = cvm_oct_sgmii_poll;
 
 	/* FIXME: Need autoneg logic */
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c
index 0c2e7cc..ee3dc41 100644
--- a/drivers/staging/octeon/ethernet-xaui.c
+++ b/drivers/staging/octeon/ethernet-xaui.c
@@ -112,7 +112,7 @@
 	struct octeon_ethernet *priv = netdev_priv(dev);
 	cvm_oct_common_init(dev);
 	dev->netdev_ops->ndo_stop(dev);
-	if (!octeon_is_simulation())
+	if (!octeon_is_simulation() && priv->phydev == NULL)
 		priv->poll = cvm_oct_xaui_poll;
 
 	return 0;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 492c502..4cfd4b1 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -30,7 +30,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
 
 #include <net/dst.h>
 
@@ -132,8 +132,6 @@
  */
 struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS];
 
-extern struct semaphore mdio_sem;
-
 /**
  * Periodic timer tick for slow management operations
  *
@@ -160,13 +158,8 @@
 		goto out;
 
 	priv = netdev_priv(cvm_oct_device[port]);
-	if (priv->poll) {
-		/* skip polling if we don't get the lock */
-		if (!down_trylock(&mdio_sem)) {
-			priv->poll(cvm_oct_device[port]);
-			up(&mdio_sem);
-		}
-	}
+	if (priv->poll)
+		priv->poll(cvm_oct_device[port]);
 
 	queues_per_port = cvmx_pko_get_num_queues(port);
 	/* Drain any pending packets in the free list */
@@ -524,7 +517,7 @@
 	dev->features |= NETIF_F_LLTX;
 	SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
 
-	cvm_oct_mdio_setup_device(dev);
+	cvm_oct_phy_setup_device(dev);
 	dev->netdev_ops->ndo_set_mac_address(dev, &sa);
 	dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
 
@@ -540,7 +533,10 @@
 
 void cvm_oct_common_uninit(struct net_device *dev)
 {
-	/* Currently nothing to do */
+	struct octeon_ethernet *priv = netdev_priv(dev);
+
+	if (priv->phydev)
+		phy_disconnect(priv->phydev);
 }
 
 static const struct net_device_ops cvm_oct_npi_netdev_ops = {
@@ -627,6 +623,8 @@
 #endif
 };
 
+extern void octeon_mdiobus_force_mod_depencency(void);
+
 /**
  * Module/ driver initialization. Creates the linux network
  * devices.
@@ -640,6 +638,7 @@
 	int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
 	int qos;
 
+	octeon_mdiobus_force_mod_depencency();
 	pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
 
 	if (OCTEON_IS_MODEL(OCTEON_CN52XX))
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index 3aef987..402a15b 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -50,9 +50,9 @@
 	/* List of outstanding tx buffers per queue */
 	struct sk_buff_head tx_free_list[16];
 	/* Device statistics */
-	struct net_device_stats stats
-;	/* Generic MII info structure */
-	struct mii_if_info mii_info;
+	struct net_device_stats stats;
+	struct phy_device *phydev;
+	unsigned int last_link;
 	/* Last negotiated link state */
 	uint64_t link_info;
 	/* Called periodically to check link status */
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 4ce399b..f98a524 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -55,7 +55,7 @@
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 
 #include <linux/io.h>
 #include <asm/uaccess.h>
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 6f8d8f97..5066de5 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -225,6 +225,12 @@
 	if (!sscanf(buf, "%d\n", &state))
 		return -EINVAL;
 
+	/* sanity check: values below 1000 millicelcius don't make sense
+	 * and can cause the system to go into a thermal heart attack
+	 */
+	if (state && state < 1000)
+		return -EINVAL;
+
 	if (state && !tz->forced_passive) {
 		mutex_lock(&thermal_list_lock);
 		list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -235,6 +241,8 @@
 								 cdev);
 		}
 		mutex_unlock(&thermal_list_lock);
+		if (!tz->passive_delay)
+			tz->passive_delay = 1000;
 	} else if (!state && tz->forced_passive) {
 		mutex_lock(&thermal_list_lock);
 		list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -245,17 +253,12 @@
 								   cdev);
 		}
 		mutex_unlock(&thermal_list_lock);
+		tz->passive_delay = 0;
 	}
 
 	tz->tc1 = 1;
 	tz->tc2 = 1;
 
-	if (!tz->passive_delay)
-		tz->passive_delay = 1000;
-
-	if (!tz->polling_delay)
-		tz->polling_delay = 10000;
-
 	tz->forced_passive = state;
 
 	thermal_zone_device_update(tz);
@@ -374,7 +377,7 @@
 	if (!sscanf(buf, "%ld\n", &state))
 		return -EINVAL;
 
-	if (state < 0)
+	if ((long)state < 0)
 		return -EINVAL;
 
 	result = cdev->ops->set_cur_state(cdev, state);
@@ -1016,6 +1019,8 @@
 		thermal_zone_device_set_polling(tz, tz->passive_delay);
 	else if (tz->polling_delay)
 		thermal_zone_device_set_polling(tz, tz->polling_delay);
+	else
+		thermal_zone_device_set_polling(tz, 0);
 	mutex_unlock(&tz->lock);
 }
 EXPORT_SYMBOL(thermal_zone_device_update);
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 5c774ab..73352f3 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -80,7 +80,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/io.h>
-#include <linux/bitops.h>
+#include <linux/bitmap.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -190,10 +190,8 @@
 			     struct isp1362_ep *ep, u16 len)
 {
 	int ptd_offset = -EINVAL;
-	int index;
 	int num_ptds = ((len + PTD_HEADER_SIZE - 1) / epq->blk_size) + 1;
-	int found = -1;
-	int last = -1;
+	int found;
 
 	BUG_ON(len > epq->buf_size);
 
@@ -205,20 +203,9 @@
 		    epq->name, len, epq->blk_size, num_ptds, epq->buf_map, epq->skip_map);
 	BUG_ON(ep->num_ptds != 0);
 
-	for (index = 0; index <= epq->buf_count - num_ptds; index++) {
-		if (test_bit(index, &epq->buf_map))
-			continue;
-		found = index;
-		for (last = index + 1; last < index + num_ptds; last++) {
-			if (test_bit(last, &epq->buf_map)) {
-				found = -1;
-				break;
-			}
-		}
-		if (found >= 0)
-			break;
-	}
-	if (found < 0)
+	found = bitmap_find_next_zero_area(&epq->buf_map, epq->buf_count, 0,
+						num_ptds, 0);
+	if (found >= epq->buf_count)
 		return -EOVERFLOW;
 
 	DBG(1, "%s: Found %d PTDs[%d] for %d/%d byte\n", __func__,
@@ -230,8 +217,7 @@
 	epq->buf_avail -= num_ptds;
 	BUG_ON(epq->buf_avail > epq->buf_count);
 	ep->ptd_index = found;
-	for (index = found; index < last; index++)
-		__set_bit(index, &epq->buf_map);
+	bitmap_set(&epq->buf_map, found, num_ptds);
 	DBG(1, "%s: Done %s PTD[%d] $%04x, avail %d count %d claimed %d %08lx:%08lx\n",
 	    __func__, epq->name, ep->ptd_index, ep->ptd_offset,
 	    epq->buf_avail, epq->buf_count, num_ptds, epq->buf_map, epq->skip_map);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 99c0df1..5a5c303 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -614,6 +614,21 @@
 	 This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
 	 It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
 
+config FB_BFIN_LQ035Q1
+	tristate "SHARP LQ035Q1DH02 TFT LCD"
+	depends on FB && BLACKFIN && SPI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select BFIN_GPTIMERS
+	help
+	  This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on
+	  the Blackfin Landscape LCD EZ-Extender Card.
+	  This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI
+	  It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin-lq035q1-fb.
 
 config FB_STI
 	tristate "HP STI frame buffer device support"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 0f8da33..4ecb30c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -137,6 +137,7 @@
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
 obj-$(CONFIG_FB_BF54X_LQ043)	  += bf54x-lq043fb.o
+obj-$(CONFIG_FB_BFIN_LQ035Q1)     += bfin-lq035q1-fb.o
 obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 4c10edecf..86d95c22 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -85,7 +85,7 @@
 	return error ? data->current_brightness : reg_val;
 }
 
-static struct backlight_ops adp5520_bl_ops = {
+static const struct backlight_ops adp5520_bl_ops = {
 	.update_status	= adp5520_bl_update_status,
 	.get_brightness	= adp5520_bl_get_brightness,
 };
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index 2c3bdfc..d769b0b 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -61,7 +61,7 @@
 	return 1;
 }
 
-static struct backlight_ops adx_backlight_ops = {
+static const struct backlight_ops adx_backlight_ops = {
 	.options = 0,
 	.update_status = adx_backlight_update_status,
 	.get_brightness = adx_backlight_get_brightness,
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index 2cf7ba5..f625ffc 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -113,7 +113,7 @@
 	return pwm_channel_enable(&pwmbl->pwmc);
 }
 
-static struct backlight_ops atmel_pwm_bl_ops = {
+static const struct backlight_ops atmel_pwm_bl_ops = {
 	.get_brightness = atmel_pwm_bl_get_intensity,
 	.update_status  = atmel_pwm_bl_set_intensity,
 };
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 6615ac7..18829cf 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -269,7 +269,7 @@
  * ERR_PTR() or a pointer to the newly allocated device.
  */
 struct backlight_device *backlight_device_register(const char *name,
-		struct device *parent, void *devdata, struct backlight_ops *ops)
+		struct device *parent, void *devdata, const struct backlight_ops *ops)
 {
 	struct backlight_device *new_bd;
 	int rc;
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 9677494..b4bcf80 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -451,7 +451,7 @@
 }
 EXPORT_SYMBOL(corgi_lcd_limit_intensity);
 
-static struct backlight_ops corgi_bl_ops = {
+static const struct backlight_ops corgi_bl_ops = {
 	.get_brightness	= corgi_bl_get_intensity,
 	.update_status  = corgi_bl_update_status,
 };
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index b9fe62b..da86db4 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -108,7 +108,7 @@
 	return intensity;
 }
 
-static struct backlight_ops cr_backlight_ops = {
+static const struct backlight_ops cr_backlight_ops = {
 	.get_brightness = cr_backlight_get_intensity,
 	.update_status = cr_backlight_set_intensity,
 };
@@ -201,7 +201,7 @@
 	if (IS_ERR(ldp)) {
 		backlight_device_unregister(bdp);
 		pci_dev_put(lpc_dev);
-		return PTR_ERR(bdp);
+		return PTR_ERR(ldp);
 	}
 
 	pci_read_config_dword(lpc_dev, CRVML_REG_GPIOBAR,
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index f2d76da..74cdc64 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -95,7 +95,7 @@
 	return data->current_brightness;
 }
 
-static struct backlight_ops da903x_backlight_ops = {
+static const struct backlight_ops da903x_backlight_ops = {
 	.update_status	= da903x_backlight_update_status,
 	.get_brightness	= da903x_backlight_get_brightness,
 };
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 6d27f62..e6d348e 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -70,7 +70,7 @@
 }
 EXPORT_SYMBOL(corgibl_limit_intensity);
 
-static struct backlight_ops genericbl_ops = {
+static const struct backlight_ops genericbl_ops = {
 	.options = BL_CORE_SUSPENDRESUME,
 	.get_brightness = genericbl_get_intensity,
 	.update_status  = genericbl_send_intensity,
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 7fb4eef..f7cc528 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -98,7 +98,7 @@
 	return current_intensity;
 }
 
-static struct backlight_ops hp680bl_ops = {
+static const struct backlight_ops hp680bl_ops = {
 	.get_brightness = hp680bl_get_intensity,
 	.update_status  = hp680bl_set_intensity,
 };
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 7aed256..db9071f 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -93,7 +93,7 @@
 	return ret;
 }
 
-static struct backlight_ops jornada_bl_ops = {
+static const struct backlight_ops jornada_bl_ops = {
 	.get_brightness = jornada_bl_get_brightness,
 	.update_status = jornada_bl_update_status,
 	.options = BL_CORE_SUSPENDRESUME,
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index a38fda1..939e7b8 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -134,7 +134,7 @@
 	return kb3886bl_intensity;
 }
 
-static struct backlight_ops kb3886bl_ops = {
+static const struct backlight_ops kb3886bl_ops = {
 	.get_brightness = kb3886bl_get_intensity,
 	.update_status  = kb3886bl_send_intensity,
 };
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 6b488b8..00a9591 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -141,7 +141,7 @@
 	return current_intensity;
 }
 
-static struct backlight_ops locomobl_data = {
+static const struct backlight_ops locomobl_data = {
 	.get_brightness = locomolcd_get_intensity,
 	.update_status  = locomolcd_set_intensity,
 };
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
index 9edb8d7..2e78b07 100644
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ b/drivers/video/backlight/mbp_nvidia_bl.c
@@ -33,7 +33,7 @@
 	unsigned long iostart;
 	unsigned long iolen;
 	/* Backlight operations structure. */
-	struct backlight_ops backlight_ops;
+	const struct backlight_ops backlight_ops;
 };
 
 /* Module parameters. */
@@ -220,6 +220,24 @@
 	},
 	{
 		.callback	= mbp_dmi_match,
+		.ident		= "MacBookPro 5,3",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
+		},
+		.driver_data	= (void *)&nvidia_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
+		.ident		= "MacBookPro 5,4",
+		.matches	= {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
+		},
+		.driver_data	= (void *)&nvidia_chipset_data,
+	},
+	{
+		.callback	= mbp_dmi_match,
 		.ident		= "MacBookPro 5,5",
 		.matches	= {
 			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index 8693e5f..409ca96 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -125,7 +125,7 @@
 	return bl->current_intensity;
 }
 
-static struct backlight_ops omapbl_ops = {
+static const struct backlight_ops omapbl_ops = {
 	.get_brightness = omapbl_get_intensity,
 	.update_status  = omapbl_update_status,
 };
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 9edaf24f..075786e 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -54,7 +54,7 @@
 	return intensity - HW_LEVEL_MIN;
 }
 
-static struct backlight_ops progearbl_ops = {
+static const struct backlight_ops progearbl_ops = {
 	.get_brightness = progearbl_get_intensity,
 	.update_status = progearbl_set_intensity,
 };
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 8871662..9d2ec2a 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -22,8 +22,10 @@
 
 struct pwm_bl_data {
 	struct pwm_device	*pwm;
+	struct device		*dev;
 	unsigned int		period;
-	int			(*notify)(int brightness);
+	int			(*notify)(struct device *,
+					  int brightness);
 };
 
 static int pwm_backlight_update_status(struct backlight_device *bl)
@@ -39,7 +41,7 @@
 		brightness = 0;
 
 	if (pb->notify)
-		brightness = pb->notify(brightness);
+		brightness = pb->notify(pb->dev, brightness);
 
 	if (brightness == 0) {
 		pwm_config(pb->pwm, 0, pb->period);
@@ -56,7 +58,7 @@
 	return bl->props.brightness;
 }
 
-static struct backlight_ops pwm_backlight_ops = {
+static const struct backlight_ops pwm_backlight_ops = {
 	.update_status	= pwm_backlight_update_status,
 	.get_brightness	= pwm_backlight_get_brightness,
 };
@@ -88,6 +90,7 @@
 
 	pb->period = data->pwm_period_ns;
 	pb->notify = data->notify;
+	pb->dev = &pdev->dev;
 
 	pb->pwm = pwm_request(data->pwm_id, "backlight");
 	if (IS_ERR(pb->pwm)) {
@@ -146,7 +149,7 @@
 	struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
 
 	if (pb->notify)
-		pb->notify(0);
+		pb->notify(pb->dev, 0);
 	pwm_config(pb->pwm, 0, pb->period);
 	pwm_disable(pb->pwm);
 	return 0;
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 43edbad..e14ce4d 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -72,7 +72,7 @@
 	return props->brightness;
 }
 
-static struct backlight_ops bl_ops = {
+static const struct backlight_ops bl_ops = {
 	.get_brightness		= tosa_bl_get_brightness,
 	.update_status		= tosa_bl_update_status,
 };
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 467bdb7..e32add3 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -112,7 +112,7 @@
 	return data->current_brightness;
 }
 
-static struct backlight_ops wm831x_backlight_ops = {
+static const struct backlight_ops wm831x_backlight_ops = {
 	.options = BL_CORE_SUSPENDRESUME,
 	.update_status	= wm831x_backlight_update_status,
 	.get_brightness	= wm831x_backlight_get_brightness,
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
new file mode 100644
index 0000000..b690c26
--- /dev/null
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -0,0 +1,826 @@
+/*
+ * Blackfin LCD Framebuffer driver SHARP LQ035Q1DH02
+ *
+ * Copyright 2008-2009 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#define DRIVER_NAME "bfin-lq035q1"
+#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/blackfin.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+#include <asm/gptimers.h>
+
+#include <asm/bfin-lq035q1.h>
+
+#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
+#define TIMER_HSYNC_id			TIMER1_id
+#define TIMER_HSYNCbit			TIMER1bit
+#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
+#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
+#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
+
+#define TIMER_VSYNC_id			TIMER2_id
+#define TIMER_VSYNCbit			TIMER2bit
+#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN2
+#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL2
+#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF2
+#else
+#define TIMER_HSYNC_id			TIMER0_id
+#define TIMER_HSYNCbit			TIMER0bit
+#define TIMER_HSYNC_STATUS_TRUN		TIMER_STATUS_TRUN0
+#define TIMER_HSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL0
+#define TIMER_HSYNC_STATUS_TOVF		TIMER_STATUS_TOVF0
+
+#define TIMER_VSYNC_id			TIMER1_id
+#define TIMER_VSYNCbit			TIMER1bit
+#define TIMER_VSYNC_STATUS_TRUN		TIMER_STATUS_TRUN1
+#define TIMER_VSYNC_STATUS_TIMIL	TIMER_STATUS_TIMIL1
+#define TIMER_VSYNC_STATUS_TOVF		TIMER_STATUS_TOVF1
+#endif
+
+#define LCD_X_RES		320	/* Horizontal Resolution */
+#define LCD_Y_RES		240	/* Vertical Resolution */
+#define	DMA_BUS_SIZE		16
+
+#define USE_RGB565_16_BIT_PPI
+
+#ifdef USE_RGB565_16_BIT_PPI
+#define LCD_BPP		16	/* Bit Per Pixel */
+#define CLOCKS_PER_PIX	1
+#define CPLD_PIPELINE_DELAY_COR 0	/* NO CPLB */
+#endif
+
+/* Interface 16/18-bit TFT over an 8-bit wide PPI using a small Programmable Logic Device (CPLD)
+ * http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=165
+ */
+
+#ifdef USE_RGB565_8_BIT_PPI
+#define LCD_BPP		16	/* Bit Per Pixel */
+#define CLOCKS_PER_PIX	2
+#define CPLD_PIPELINE_DELAY_COR 3	/* RGB565 */
+#endif
+
+#ifdef USE_RGB888_8_BIT_PPI
+#define LCD_BPP		24	/* Bit Per Pixel */
+#define CLOCKS_PER_PIX	3
+#define CPLD_PIPELINE_DELAY_COR 5	/* RGB888 */
+#endif
+
+	/*
+	 * HS and VS timing parameters (all in number of PPI clk ticks)
+	 */
+
+#define U_LINE		4				/* Blanking Lines */
+
+#define H_ACTPIX	(LCD_X_RES * CLOCKS_PER_PIX)	/* active horizontal pixel */
+#define H_PERIOD	(336 * CLOCKS_PER_PIX)		/* HS period */
+#define H_PULSE		(2 * CLOCKS_PER_PIX)				/* HS pulse width */
+#define H_START		(7 * CLOCKS_PER_PIX + CPLD_PIPELINE_DELAY_COR)	/* first valid pixel */
+
+#define	V_LINES		(LCD_Y_RES + U_LINE)		/* total vertical lines */
+#define V_PULSE		(2 * CLOCKS_PER_PIX)		/* VS pulse width (1-5 H_PERIODs) */
+#define V_PERIOD	(H_PERIOD * V_LINES)		/* VS period */
+
+#define ACTIVE_VIDEO_MEM_OFFSET		((U_LINE / 2) * LCD_X_RES * (LCD_BPP / 8))
+
+#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
+
+#define PPI_TX_MODE			0x2
+#define PPI_XFER_TYPE_11		0xC
+#define PPI_PORT_CFG_01			0x10
+#define PPI_POLS_1			0x8000
+
+#if (CLOCKS_PER_PIX > 1)
+#define PPI_PMODE (DLEN_8 | PACK_EN)
+#else
+#define PPI_PMODE (DLEN_16)
+#endif
+
+#define LQ035_INDEX			0x74
+#define LQ035_DATA			0x76
+
+#define LQ035_DRIVER_OUTPUT_CTL		0x1
+#define LQ035_SHUT_CTL			0x11
+
+#define LQ035_DRIVER_OUTPUT_MASK	(LQ035_LR | LQ035_TB | LQ035_BGR | LQ035_REV)
+#define LQ035_DRIVER_OUTPUT_DEFAULT	(0x2AEF & ~LQ035_DRIVER_OUTPUT_MASK)
+
+#define LQ035_SHUT			(1 << 0)	/* Shutdown */
+#define LQ035_ON			(0 << 0)	/* Shutdown */
+
+struct bfin_lq035q1fb_info {
+	struct fb_info *fb;
+	struct device *dev;
+	struct spi_driver spidrv;
+	struct bfin_lq035q1fb_disp_info *disp_info;
+	unsigned char *fb_buffer;	/* RGB Buffer */
+	dma_addr_t dma_handle;
+	int lq035_open_cnt;
+	int irq;
+	spinlock_t lock;	/* lock */
+	u32 pseudo_pal[16];
+};
+
+static int nocursor;
+module_param(nocursor, int, 0644);
+MODULE_PARM_DESC(nocursor, "cursor enable/disable");
+
+struct spi_control {
+	unsigned short mode;
+};
+
+static int lq035q1_control(struct spi_device *spi, unsigned char reg, unsigned short value)
+{
+	int ret;
+	u8 regs[3] = { LQ035_INDEX, 0, 0 };
+	u8 dat[3] = { LQ035_DATA, 0, 0 };
+
+	if (!spi)
+		return -ENODEV;
+
+	regs[2] = reg;
+	dat[1] = value >> 8;
+	dat[2] = value & 0xFF;
+
+	ret = spi_write(spi, regs, ARRAY_SIZE(regs));
+	ret |= spi_write(spi, dat, ARRAY_SIZE(dat));
+	return ret;
+}
+
+static int __devinit lq035q1_spidev_probe(struct spi_device *spi)
+{
+	int ret;
+	struct spi_control *ctl;
+	struct bfin_lq035q1fb_info *info = container_of(spi->dev.driver,
+						struct bfin_lq035q1fb_info,
+						spidrv.driver);
+
+	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
+
+	if (!ctl)
+		return -ENOMEM;
+
+	ctl->mode = (info->disp_info->mode &
+		LQ035_DRIVER_OUTPUT_MASK) | LQ035_DRIVER_OUTPUT_DEFAULT;
+
+	ret = lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
+	ret |= lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
+	if (ret)
+		return ret;
+
+	spi_set_drvdata(spi, ctl);
+
+	return 0;
+}
+
+static int lq035q1_spidev_remove(struct spi_device *spi)
+{
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+#ifdef CONFIG_PM
+static int lq035q1_spidev_suspend(struct spi_device *spi, pm_message_t state)
+{
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+static int lq035q1_spidev_resume(struct spi_device *spi)
+{
+	int ret;
+	struct spi_control *ctl = spi_get_drvdata(spi);
+
+	ret = lq035q1_control(spi, LQ035_DRIVER_OUTPUT_CTL, ctl->mode);
+	if (ret)
+		return ret;
+
+	return lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_ON);
+}
+#else
+# define lq035q1_spidev_suspend NULL
+# define lq035q1_spidev_resume  NULL
+#endif
+
+/* Power down all displays on reboot, poweroff or halt */
+static void lq035q1_spidev_shutdown(struct spi_device *spi)
+{
+	lq035q1_control(spi, LQ035_SHUT_CTL, LQ035_SHUT);
+}
+
+static int lq035q1_backlight(struct bfin_lq035q1fb_info *info, unsigned arg)
+{
+	if (info->disp_info->use_bl)
+		gpio_set_value(info->disp_info->gpio_bl, arg);
+
+	return 0;
+}
+
+static void bfin_lq035q1_config_ppi(struct bfin_lq035q1fb_info *fbi)
+{
+	bfin_write_PPI_DELAY(H_START);
+	bfin_write_PPI_COUNT(H_ACTPIX - 1);
+	bfin_write_PPI_FRAME(V_LINES);
+
+	bfin_write_PPI_CONTROL(PPI_TX_MODE |	   /* output mode , PORT_DIR */
+				PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
+				PPI_PORT_CFG_01 |  /* two frame sync PORT_CFG */
+				PPI_PMODE |	   /* 8/16 bit data length / PACK_EN? */
+				PPI_POLS_1);	   /* faling edge syncs POLS */
+}
+
+static inline void bfin_lq035q1_disable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
+}
+
+static inline void bfin_lq035q1_enable_ppi(void)
+{
+	bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
+}
+
+static void bfin_lq035q1_start_timers(void)
+{
+	enable_gptimers(TIMER_VSYNCbit | TIMER_HSYNCbit);
+}
+
+static void bfin_lq035q1_stop_timers(void)
+{
+	disable_gptimers(TIMER_HSYNCbit | TIMER_VSYNCbit);
+
+	set_gptimer_status(0, TIMER_HSYNC_STATUS_TRUN | TIMER_VSYNC_STATUS_TRUN |
+				TIMER_HSYNC_STATUS_TIMIL | TIMER_VSYNC_STATUS_TIMIL |
+				 TIMER_HSYNC_STATUS_TOVF | TIMER_VSYNC_STATUS_TOVF);
+
+}
+
+static void bfin_lq035q1_init_timers(void)
+{
+
+	bfin_lq035q1_stop_timers();
+
+	set_gptimer_period(TIMER_HSYNC_id, H_PERIOD);
+	set_gptimer_pwidth(TIMER_HSYNC_id, H_PULSE);
+	set_gptimer_config(TIMER_HSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL|
+				      TIMER_EMU_RUN);
+
+	set_gptimer_period(TIMER_VSYNC_id, V_PERIOD);
+	set_gptimer_pwidth(TIMER_VSYNC_id, V_PULSE);
+	set_gptimer_config(TIMER_VSYNC_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
+				      TIMER_TIN_SEL | TIMER_CLK_SEL |
+				      TIMER_EMU_RUN);
+
+}
+
+static void bfin_lq035q1_config_dma(struct bfin_lq035q1fb_info *fbi)
+{
+
+	set_dma_config(CH_PPI,
+		       set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
+					   INTR_DISABLE, DIMENSION_2D,
+					   DATA_SIZE_16,
+					   DMA_NOSYNC_KEEP_DMA_BUF));
+	set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
+	set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_y_count(CH_PPI, V_LINES);
+
+	set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
+	set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
+
+}
+
+#if (CLOCKS_PER_PIX == 1)
+static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, P_PPI0_D8,
+			    P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+			    P_PPI0_D12, P_PPI0_D13, P_PPI0_D14,
+			    P_PPI0_D15, 0};
+#else
+static const u16 ppi0_req_16[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+			    P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
+			    P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
+			    P_PPI0_D6, P_PPI0_D7, 0};
+#endif
+
+static inline void bfin_lq035q1_free_ports(void)
+{
+	peripheral_free_list(ppi0_req_16);
+	if (ANOMALY_05000400)
+		gpio_free(P_IDENT(P_PPI0_FS3));
+}
+
+static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev)
+{
+	/* ANOMALY_05000400 - PPI Does Not Start Properly In Specific Mode:
+	 * Drive PPI_FS3 Low
+	 */
+	if (ANOMALY_05000400) {
+		int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3");
+		if (ret)
+			return ret;
+		gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
+	}
+
+	if (peripheral_request_list(ppi0_req_16, DRIVER_NAME)) {
+		dev_err(&pdev->dev, "requesting peripherals failed\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_open(struct fb_info *info, int user)
+{
+	struct bfin_lq035q1fb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+	fbi->lq035_open_cnt++;
+
+	if (fbi->lq035_open_cnt <= 1) {
+
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+
+		bfin_lq035q1_config_dma(fbi);
+		bfin_lq035q1_config_ppi(fbi);
+		bfin_lq035q1_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_lq035q1_start_timers();
+		lq035q1_backlight(fbi, 1);
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_release(struct fb_info *info, int user)
+{
+	struct bfin_lq035q1fb_info *fbi = info->par;
+
+	spin_lock(&fbi->lock);
+
+	fbi->lq035_open_cnt--;
+
+	if (fbi->lq035_open_cnt <= 0) {
+		lq035q1_backlight(fbi, 0);
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_lq035q1_stop_timers();
+	}
+
+	spin_unlock(&fbi->lock);
+
+	return 0;
+}
+
+static int bfin_lq035q1_fb_check_var(struct fb_var_screeninfo *var,
+				     struct fb_info *info)
+{
+	switch (var->bits_per_pixel) {
+#if (LCD_BPP == 24)
+	case 24:/* TRUECOLOUR, 16m */
+#else
+	case 16:/* DIRECTCOLOUR, 64k */
+#endif
+		var->red.offset = info->var.red.offset;
+		var->green.offset = info->var.green.offset;
+		var->blue.offset = info->var.blue.offset;
+		var->red.length = info->var.red.length;
+		var->green.length = info->var.green.length;
+		var->blue.length = info->var.blue.length;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		var->transp.msb_right = 0;
+		var->red.msb_right = 0;
+		var->green.msb_right = 0;
+		var->blue.msb_right = 0;
+		break;
+	default:
+		pr_debug("%s: depth not supported: %u BPP\n", __func__,
+			 var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (info->var.xres != var->xres || info->var.yres != var->yres ||
+	    info->var.xres_virtual != var->xres_virtual ||
+	    info->var.yres_virtual != var->yres_virtual) {
+		pr_debug("%s: Resolution not supported: X%u x Y%u \n",
+			 __func__, var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/*
+	 *  Memory limit
+	 */
+
+	if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
+		pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
+			 __func__, var->yres_virtual);
+		return -ENOMEM;
+	}
+
+
+	return 0;
+}
+
+int bfin_lq035q1_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	if (nocursor)
+		return 0;
+	else
+		return -EINVAL;	/* just to force soft_cursor() call */
+}
+
+static int bfin_lq035q1_fb_setcolreg(u_int regno, u_int red, u_int green,
+				   u_int blue, u_int transp,
+				   struct fb_info *info)
+{
+	if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+
+		u32 value;
+		/* Place color in the pseudopalette */
+		if (regno > 16)
+			return -EINVAL;
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		value = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+		value &= 0xFFFFFF;
+
+		((u32 *) (info->pseudo_palette))[regno] = value;
+
+	}
+
+	return 0;
+}
+
+static struct fb_ops bfin_lq035q1_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_open = bfin_lq035q1_fb_open,
+	.fb_release = bfin_lq035q1_fb_release,
+	.fb_check_var = bfin_lq035q1_fb_check_var,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_cursor = bfin_lq035q1_fb_cursor,
+	.fb_setcolreg = bfin_lq035q1_fb_setcolreg,
+};
+
+static irqreturn_t bfin_lq035q1_irq_error(int irq, void *dev_id)
+{
+	/*struct bfin_lq035q1fb_info *info = (struct bfin_lq035q1fb_info *)dev_id;*/
+
+	u16 status = bfin_read_PPI_STATUS();
+	bfin_write_PPI_STATUS(-1);
+
+	if (status) {
+		bfin_lq035q1_disable_ppi();
+		disable_dma(CH_PPI);
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_write_PPI_STATUS(-1);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
+{
+	struct bfin_lq035q1fb_info *info;
+	struct fb_info *fbinfo;
+	int ret;
+
+	ret = request_dma(CH_PPI, DRIVER_NAME"_CH_PPI");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "PPI DMA unavailable\n");
+		goto out1;
+	}
+
+	fbinfo = framebuffer_alloc(sizeof(*info), &pdev->dev);
+	if (!fbinfo) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	info = fbinfo->par;
+	info->fb = fbinfo;
+	info->dev = &pdev->dev;
+
+	info->disp_info = pdev->dev.platform_data;
+
+	platform_set_drvdata(pdev, fbinfo);
+
+	strcpy(fbinfo->fix.id, DRIVER_NAME);
+
+	fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
+	fbinfo->fix.type_aux = 0;
+	fbinfo->fix.xpanstep = 0;
+	fbinfo->fix.ypanstep = 0;
+	fbinfo->fix.ywrapstep = 0;
+	fbinfo->fix.accel = FB_ACCEL_NONE;
+	fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	fbinfo->var.nonstd = 0;
+	fbinfo->var.activate = FB_ACTIVATE_NOW;
+	fbinfo->var.height = -1;
+	fbinfo->var.width = -1;
+	fbinfo->var.accel_flags = 0;
+	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
+
+	fbinfo->var.xres = LCD_X_RES;
+	fbinfo->var.xres_virtual = LCD_X_RES;
+	fbinfo->var.yres = LCD_Y_RES;
+	fbinfo->var.yres_virtual = LCD_Y_RES;
+	fbinfo->var.bits_per_pixel = LCD_BPP;
+
+	if (info->disp_info->mode & LQ035_BGR) {
+#if (LCD_BPP == 24)
+		fbinfo->var.red.offset = 0;
+		fbinfo->var.green.offset = 8;
+		fbinfo->var.blue.offset = 16;
+#else
+		fbinfo->var.red.offset = 0;
+		fbinfo->var.green.offset = 5;
+		fbinfo->var.blue.offset = 11;
+#endif
+	} else {
+#if (LCD_BPP == 24)
+		fbinfo->var.red.offset = 16;
+		fbinfo->var.green.offset = 8;
+		fbinfo->var.blue.offset = 0;
+#else
+		fbinfo->var.red.offset = 11;
+		fbinfo->var.green.offset = 5;
+		fbinfo->var.blue.offset = 0;
+#endif
+	}
+
+	fbinfo->var.transp.offset = 0;
+
+#if (LCD_BPP == 24)
+	fbinfo->var.red.length = 8;
+	fbinfo->var.green.length = 8;
+	fbinfo->var.blue.length = 8;
+#else
+	fbinfo->var.red.length = 5;
+	fbinfo->var.green.length = 6;
+	fbinfo->var.blue.length = 5;
+#endif
+
+	fbinfo->var.transp.length = 0;
+
+	fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8
+				+ ACTIVE_VIDEO_MEM_OFFSET;
+
+	fbinfo->fix.line_length = fbinfo->var.xres_virtual *
+	    fbinfo->var.bits_per_pixel / 8;
+
+
+	fbinfo->fbops = &bfin_lq035q1_fb_ops;
+	fbinfo->flags = FBINFO_FLAG_DEFAULT;
+
+	info->fb_buffer =
+	    dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
+			       GFP_KERNEL);
+
+	if (NULL == info->fb_buffer) {
+		dev_err(&pdev->dev, "couldn't allocate dma buffer\n");
+		ret = -ENOMEM;
+		goto out3;
+	}
+
+	fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+	fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
+
+	fbinfo->fbops = &bfin_lq035q1_fb_ops;
+
+	fbinfo->pseudo_palette = &info->pseudo_pal;
+
+	ret = fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to allocate colormap (%d entries)\n",
+		       BFIN_LCD_NBR_PALETTE_ENTRIES);
+		goto out4;
+	}
+
+	ret = bfin_lq035q1_request_ports(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request gpio port\n");
+		goto out6;
+	}
+
+	info->irq = platform_get_irq(pdev, 0);
+	if (info->irq < 0) {
+		ret = -EINVAL;
+		goto out7;
+	}
+
+	ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED,
+			DRIVER_NAME" PPI ERROR", info);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n");
+		goto out7;
+	}
+
+	info->spidrv.driver.name = DRIVER_NAME"-spi";
+	info->spidrv.probe    = lq035q1_spidev_probe;
+	info->spidrv.remove   = __devexit_p(lq035q1_spidev_remove);
+	info->spidrv.shutdown = lq035q1_spidev_shutdown;
+	info->spidrv.suspend  = lq035q1_spidev_suspend;
+	info->spidrv.resume   = lq035q1_spidev_resume;
+
+	ret = spi_register_driver(&info->spidrv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "couldn't register SPI Interface\n");
+		goto out8;
+	}
+
+	if (info->disp_info->use_bl) {
+		ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight");
+
+		if (ret) {
+			dev_err(&pdev->dev, "failed to request GPIO %d\n",
+				info->disp_info->gpio_bl);
+			goto out9;
+		}
+		gpio_direction_output(info->disp_info->gpio_bl, 0);
+	}
+
+	ret = register_framebuffer(fbinfo);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to register framebuffer\n");
+		goto out10;
+	}
+
+	dev_info(&pdev->dev, "%dx%d %d-bit RGB FrameBuffer initialized\n",
+		LCD_X_RES, LCD_Y_RES, LCD_BPP);
+
+	return 0;
+
+ out10:
+	if (info->disp_info->use_bl)
+		gpio_free(info->disp_info->gpio_bl);
+ out9:
+	spi_unregister_driver(&info->spidrv);
+ out8:
+	free_irq(info->irq, info);
+ out7:
+	bfin_lq035q1_free_ports();
+ out6:
+	fb_dealloc_cmap(&fbinfo->cmap);
+ out4:
+	dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+			  info->dma_handle);
+ out3:
+	framebuffer_release(fbinfo);
+ out2:
+	free_dma(CH_PPI);
+ out1:
+	platform_set_drvdata(pdev, NULL);
+
+	return ret;
+}
+
+static int __devexit bfin_lq035q1_remove(struct platform_device *pdev)
+{
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->disp_info->use_bl)
+		gpio_free(info->disp_info->gpio_bl);
+
+	spi_unregister_driver(&info->spidrv);
+
+	unregister_framebuffer(fbinfo);
+
+	free_dma(CH_PPI);
+	free_irq(info->irq, info);
+
+	if (info->fb_buffer != NULL)
+		dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
+				  info->dma_handle);
+
+	fb_dealloc_cmap(&fbinfo->cmap);
+
+	bfin_lq035q1_free_ports();
+
+	platform_set_drvdata(pdev, NULL);
+	framebuffer_release(fbinfo);
+
+	dev_info(&pdev->dev, "unregistered LCD driver\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bfin_lq035q1_suspend(struct device *dev)
+{
+	struct fb_info *fbinfo = dev_get_drvdata(dev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->lq035_open_cnt) {
+		lq035q1_backlight(info, 0);
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+		disable_dma(CH_PPI);
+		bfin_lq035q1_stop_timers();
+		bfin_write_PPI_STATUS(-1);
+	}
+
+	return 0;
+}
+
+static int bfin_lq035q1_resume(struct device *dev)
+{
+	struct fb_info *fbinfo = dev_get_drvdata(dev);
+	struct bfin_lq035q1fb_info *info = fbinfo->par;
+
+	if (info->lq035_open_cnt) {
+		bfin_lq035q1_disable_ppi();
+		SSYNC();
+
+		bfin_lq035q1_config_dma(info);
+		bfin_lq035q1_config_ppi(info);
+		bfin_lq035q1_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_lq035q1_enable_ppi();
+		bfin_lq035q1_start_timers();
+		lq035q1_backlight(info, 1);
+	}
+
+	return 0;
+}
+
+static struct dev_pm_ops bfin_lq035q1_dev_pm_ops = {
+	.suspend = bfin_lq035q1_suspend,
+	.resume  = bfin_lq035q1_resume,
+};
+#endif
+
+static struct platform_driver bfin_lq035q1_driver = {
+	.probe   = bfin_lq035q1_probe,
+	.remove  = __devexit_p(bfin_lq035q1_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm   = &bfin_lq035q1_dev_pm_ops,
+#endif
+	},
+};
+
+static int __init bfin_lq035q1_driver_init(void)
+{
+	return platform_driver_register(&bfin_lq035q1_driver);
+}
+module_init(bfin_lq035q1_driver_init);
+
+static void __exit bfin_lq035q1_driver_cleanup(void)
+{
+	platform_driver_unregister(&bfin_lq035q1_driver);
+}
+module_exit(bfin_lq035q1_driver_cleanup);
+
+MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 5cc36cf..2549c53 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -487,8 +487,8 @@
 
 	fbinfo->var.nonstd = 0;
 	fbinfo->var.activate = FB_ACTIVATE_NOW;
-	fbinfo->var.height = -1;
-	fbinfo->var.width = -1;
+	fbinfo->var.height = 53;
+	fbinfo->var.width = 70;
 	fbinfo->var.accel_flags = 0;
 	fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
 
@@ -634,17 +634,35 @@
 #ifdef CONFIG_PM
 static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	bfin_t350mcqb_disable_ppi();
-	disable_dma(CH_PPI);
-	bfin_write_PPI_STATUS(0xFFFF);
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
+
+	if (fbi->lq043_open_cnt) {
+		bfin_t350mcqb_disable_ppi();
+		disable_dma(CH_PPI);
+		bfin_t350mcqb_stop_timers();
+		bfin_write_PPI_STATUS(-1);
+	}
+
 
 	return 0;
 }
 
 static int bfin_t350mcqb_resume(struct platform_device *pdev)
 {
-	enable_dma(CH_PPI);
-	bfin_t350mcqb_enable_ppi();
+	struct fb_info *fbinfo = platform_get_drvdata(pdev);
+	struct bfin_t350mcqbfb_info *fbi = fbinfo->par;
+
+	if (fbi->lq043_open_cnt) {
+		bfin_t350mcqb_config_dma(fbi);
+		bfin_t350mcqb_config_ppi(fbi);
+		bfin_t350mcqb_init_timers();
+
+		/* start dma */
+		enable_dma(CH_PPI);
+		bfin_t350mcqb_enable_ppi();
+		bfin_t350mcqb_start_timers();
+	}
 
 	return 0;
 }
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index 16f5db4..99b354b 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -19,8 +19,10 @@
  *
  *  Framebuffer driver for the CLPS7111 and EP7212 processors.
  */
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/init.h>
@@ -38,14 +40,6 @@
 
 #define CMAP_MAX_SIZE	16
 
-/* The /proc entry for the backlight. */
-static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
-
-static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-		int count, int *eof, void *data);
-static int clps7111fb_proc_backlight_write(struct file *file, 
-		const char *buffer, unsigned long count, void *data);
-
 /*
  * LCD AC Prescale.  This comes from the LCD panel manufacturers specifications.
  * This determines how many clocks + 1 of CL1 before the M signal toggles.
@@ -221,26 +215,23 @@
 	.fb_imageblit	= cfb_imageblit,
 };
 
-static int 
-clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
-		int count, int *eof, void *data)
+static int backlight_proc_show(struct seq_file *m, void *v)
 {
-	/* We need at least two characters, one for the digit, and one for
-	 * the terminating NULL. */
-	if (count < 2) 
-		return -EINVAL;
-
 	if (machine_is_edb7211()) {
-		return sprintf(page, "%d\n", 
+		seq_printf(m, "%d\n",
 				(clps_readb(PDDR) & EDB_PD3_LCDBL) ? 1 : 0);
 	}
 
 	return 0;
 }
 
-static int 
-clps7111fb_proc_backlight_write(struct file *file, const char *buffer, 
-		unsigned long count, void *data)
+static int backlight_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, backlight_proc_show, NULL);
+}
+
+static ssize_t backlight_proc_write(struct file *file, const char *buffer,
+				    size_t count, loff_t *pos)
 {
 	unsigned char char_value;
 	int value;
@@ -271,6 +262,15 @@
 	return count;
 }
 
+static const struct file_operations backlight_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= backlight_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= backlight_proc_write,
+};
+
 static void __init clps711x_guess_lcd_params(struct fb_info *info)
 {
 	unsigned int lcdcon, syscon, size;
@@ -379,19 +379,11 @@
 
 	fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
 
-	/* Register the /proc entries. */
-	clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
-		NULL);
-	if (clps7111fb_backlight_proc_entry == NULL) {
+	if (!proc_create("backlight", 0444, NULL, &backlight_proc_fops)) {
 		printk("Couldn't create the /proc entry for the backlight.\n");
 		return -EINVAL;
 	}
 
-	clps7111fb_backlight_proc_entry->read_proc = 
-		&clps7111fb_proc_backlight_read;
-	clps7111fb_backlight_proc_entry->write_proc = 
-		&clps7111fb_proc_backlight_write;
-
 	/*
 	 * Power up the LCD
 	 */
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index ea1fd3f..369a5b3 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -28,6 +28,8 @@
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/console.h>
 #include <video/da8xx-fb.h>
 
 #define DRIVER_NAME "da8xx_lcdc"
@@ -113,6 +115,12 @@
 	unsigned short pseudo_palette[16];
 	unsigned int databuf_sz;
 	unsigned int palette_sz;
+	unsigned int pxl_clk;
+	int blank;
+#ifdef CONFIG_CPU_FREQ
+	struct notifier_block	freq_transition;
+#endif
+	void (*panel_power_ctrl)(int);
 };
 
 /* Variable Screen Information */
@@ -155,7 +163,7 @@
 	int		vfp;		/* Vertical front porch */
 	int		vbp;		/* Vertical back porch */
 	int		vsw;		/* Vertical Sync Pulse Width */
-	int		pxl_clk;	/* Pixel clock */
+	unsigned int	pxl_clk;	/* Pixel clock */
 	unsigned char	invert_pxl_clk;	/* Invert Pixel clock */
 };
 
@@ -171,7 +179,7 @@
 		.vfp = 2,
 		.vbp = 2,
 		.vsw = 0,
-		.pxl_clk = 0x10,
+		.pxl_clk = 4608000,
 		.invert_pxl_clk = 1,
 	},
 	/* Sharp LK043T1DG01 */
@@ -185,13 +193,23 @@
 		.vfp = 2,
 		.vbp = 2,
 		.vsw = 10,
-		.pxl_clk = 0x12,
+		.pxl_clk = 7833600,
 		.invert_pxl_clk = 0,
 	},
 };
 
+/* Enable the Raster Engine of the LCD Controller */
+static inline void lcd_enable_raster(void)
+{
+	u32 reg;
+
+	reg = lcdc_read(LCD_RASTER_CTRL_REG);
+	if (!(reg & LCD_RASTER_ENABLE))
+		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+}
+
 /* Disable the Raster Engine of the LCD Controller */
-static void lcd_disable_raster(struct da8xx_fb_par *par)
+static inline void lcd_disable_raster(void)
 {
 	u32 reg;
 
@@ -443,14 +461,25 @@
 static void lcd_reset(struct da8xx_fb_par *par)
 {
 	/* Disable the Raster if previously Enabled */
-	if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
-		lcd_disable_raster(par);
+	lcd_disable_raster();
 
 	/* DMA has to be disabled */
 	lcdc_write(0, LCD_DMA_CTRL_REG);
 	lcdc_write(0, LCD_RASTER_CTRL_REG);
 }
 
+static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
+{
+	unsigned int lcd_clk, div;
+
+	lcd_clk = clk_get_rate(par->lcdc_clk);
+	div = lcd_clk / par->pxl_clk;
+
+	/* Configure the LCD clock divisor. */
+	lcdc_write(LCD_CLK_DIVISOR(div) |
+			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+}
+
 static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg,
 		struct da8xx_panel *panel)
 {
@@ -459,9 +488,8 @@
 
 	lcd_reset(par);
 
-	/* Configure the LCD clock divisor. */
-	lcdc_write(LCD_CLK_DIVISOR(panel->pxl_clk) |
-			(LCD_RASTER_MODE & 0x1), LCD_CTRL_REG);
+	/* Calculate the divider */
+	lcd_calc_clk_divider(par);
 
 	if (panel->invert_pxl_clk)
 		lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) |
@@ -513,13 +541,11 @@
 static irqreturn_t lcdc_irq_handler(int irq, void *arg)
 {
 	u32 stat = lcdc_read(LCD_STAT_REG);
-	u32 reg;
 
 	if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
-		reg = lcdc_read(LCD_RASTER_CTRL_REG);
-		lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+		lcd_disable_raster();
 		lcdc_write(stat, LCD_STAT_REG);
-		lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+		lcd_enable_raster();
 	} else
 		lcdc_write(stat, LCD_STAT_REG);
 
@@ -574,6 +600,38 @@
 	return err;
 }
 
+#ifdef CONFIG_CPU_FREQ
+static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
+				     unsigned long val, void *data)
+{
+	struct da8xx_fb_par *par;
+
+	par = container_of(nb, struct da8xx_fb_par, freq_transition);
+	if (val == CPUFREQ_PRECHANGE) {
+		lcd_disable_raster();
+	} else if (val == CPUFREQ_POSTCHANGE) {
+		lcd_calc_clk_divider(par);
+		lcd_enable_raster();
+	}
+
+	return 0;
+}
+
+static inline int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par)
+{
+	par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition;
+
+	return cpufreq_register_notifier(&par->freq_transition,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static inline void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par)
+{
+	cpufreq_unregister_notifier(&par->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+}
+#endif
+
 static int __devexit fb_remove(struct platform_device *dev)
 {
 	struct fb_info *info = dev_get_drvdata(&dev->dev);
@@ -581,8 +639,13 @@
 	if (info) {
 		struct da8xx_fb_par *par = info->par;
 
-		if (lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE)
-			lcd_disable_raster(par);
+#ifdef CONFIG_CPU_FREQ
+		lcd_da8xx_cpufreq_deregister(par);
+#endif
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(0);
+
+		lcd_disable_raster();
 		lcdc_write(0, LCD_RASTER_CTRL_REG);
 
 		/* disable DMA  */
@@ -639,6 +702,35 @@
 	return 0;
 }
 
+static int cfb_blank(int blank, struct fb_info *info)
+{
+	struct da8xx_fb_par *par = info->par;
+	int ret = 0;
+
+	if (par->blank == blank)
+		return 0;
+
+	par->blank = blank;
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(1);
+
+		lcd_enable_raster();
+		break;
+	case FB_BLANK_POWERDOWN:
+		if (par->panel_power_ctrl)
+			par->panel_power_ctrl(0);
+
+		lcd_disable_raster();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 static struct fb_ops da8xx_fb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = fb_check_var,
@@ -647,6 +739,7 @@
 	.fb_fillrect = cfb_fillrect,
 	.fb_copyarea = cfb_copyarea,
 	.fb_imageblit = cfb_imageblit,
+	.fb_blank = cfb_blank,
 };
 
 static int __init fb_probe(struct platform_device *device)
@@ -721,6 +814,12 @@
 	}
 
 	par = da8xx_fb_info->par;
+	par->lcdc_clk = fb_clk;
+	par->pxl_clk = lcdc_info->pxl_clk;
+	if (fb_pdata->panel_power_ctrl) {
+		par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
+		par->panel_power_ctrl(1);
+	}
 
 	if (lcd_init(par, lcd_cfg, lcdc_info) < 0) {
 		dev_err(&device->dev, "lcd_init failed\n");
@@ -754,8 +853,6 @@
 	da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz;
 	da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8;
 
-	par->lcdc_clk = fb_clk;
-
 	par->irq = platform_get_irq(device, 0);
 	if (par->irq < 0) {
 		ret = -ENOENT;
@@ -814,12 +911,24 @@
 		goto err_dealloc_cmap;
 	}
 
+#ifdef CONFIG_CPU_FREQ
+	ret = lcd_da8xx_cpufreq_register(par);
+	if (ret) {
+		dev_err(&device->dev, "failed to register cpufreq\n");
+		goto err_cpu_freq;
+	}
+#endif
+
 	/* enable raster engine */
-	lcdc_write(lcdc_read(LCD_RASTER_CTRL_REG) |
-			LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+	lcd_enable_raster();
 
 	return 0;
 
+#ifdef CONFIG_CPU_FREQ
+err_cpu_freq:
+	unregister_framebuffer(da8xx_fb_info);
+#endif
+
 err_dealloc_cmap:
 	fb_dealloc_cmap(&da8xx_fb_info->cmap);
 
@@ -852,11 +961,35 @@
 #ifdef CONFIG_PM
 static int fb_suspend(struct platform_device *dev, pm_message_t state)
 {
-	 return -EBUSY;
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct da8xx_fb_par *par = info->par;
+
+	acquire_console_sem();
+	if (par->panel_power_ctrl)
+		par->panel_power_ctrl(0);
+
+	fb_set_suspend(info, 1);
+	lcd_disable_raster();
+	clk_disable(par->lcdc_clk);
+	release_console_sem();
+
+	return 0;
 }
 static int fb_resume(struct platform_device *dev)
 {
-	 return -EBUSY;
+	struct fb_info *info = platform_get_drvdata(dev);
+	struct da8xx_fb_par *par = info->par;
+
+	acquire_console_sem();
+	if (par->panel_power_ctrl)
+		par->panel_power_ctrl(1);
+
+	clk_enable(par->lcdc_clk);
+	lcd_enable_raster();
+	fb_set_suspend(info, 0);
+	release_console_sem();
+
+	return 0;
 }
 #else
 #define fb_suspend NULL
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index bd9d46f..27aab4a 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -358,6 +358,8 @@
 
 	switch (info->fix.visual) {
 	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno > 255)
+			return 1;
 		rgb = ((red & 0xff00) << 8) | (green & 0xff00) |
 			((blue & 0xff00) >> 8);
 
diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
index fc68a8b..cc781c0 100644
--- a/drivers/video/geode/lxfb.h
+++ b/drivers/video/geode/lxfb.h
@@ -1,3 +1,13 @@
+/* Geode LX framebuffer driver
+ *
+ * Copyright (C) 2006-2007, Advanced Micro Devices,Inc.
+ * Copyright (c) 2008  Andres Salomon <dilinger@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
 #ifndef _LXFB_H_
 #define _LXFB_H_
 
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
index 27fa703..b4b3670 100644
--- a/drivers/video/i810/i810_dvt.c
+++ b/drivers/video/i810/i810_dvt.c
@@ -212,24 +212,29 @@
 	*yres = (*xres * 3) >> 2;
 }
 
-void i810fb_encode_registers(const struct fb_var_screeninfo *var,
-			     struct i810fb_par *par, u32 xres, u32 yres)
+static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
 { 
 	u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; 
-	u8 hfl;
+	u8 hfl = (u8) ((xres >> 3) - 1);
 
-	hfl = (u8) ((xres >> 3) - 1);
 	for (i = 0; i < ARRAY_SIZE(std_modes); i++) { 
 		if (std_modes[i].cr01 == hfl) { 
-			if (std_modes[i].pixclock <= par->regs.pixclock)
-				diff = par->regs.pixclock - 
-					std_modes[i].pixclock;
+			if (std_modes[i].pixclock <= pixclock)
+				diff = pixclock - std_modes[i].pixclock;
 			if (diff < diff_best) {	 
 		    		i_best = i;
 		    		diff_best = diff;
 			}
 		}
 	}
+	return i_best;
+}
+
+void i810fb_encode_registers(const struct fb_var_screeninfo *var,
+			     struct i810fb_par *par, u32 xres, u32 yres)
+{
+	u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);
+
 	par->regs = std_modes[i_best];
 
 	/* overlay */
@@ -239,36 +244,36 @@
 
 void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
 {
-	struct i810fb_par par;
 	u32 total, xres, yres;
+	u32 mode, pixclock;
 
 	xres = var->xres;
 	yres = var->yres;
 	
-	par.regs.pixclock = 1000000000/var->pixclock;
-	i810fb_encode_registers(var, &par, xres, yres);
+	pixclock = 1000000000 / var->pixclock;
+	mode = i810fb_find_best_mode(xres, yres, pixclock);
 	
-	total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3;
+	total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
+	total <<= 3;
 	
-	var->pixclock = 1000000000/par.regs.pixclock;
-	var->right_margin = (par.regs.cr04 << 3) - xres;
-	var->hsync_len = ((par.regs.cr05 & 0x1F) - 
-			       (par.regs.cr04 & 0x1F)) << 3;
+	var->pixclock = 1000000000 / std_modes[mode].pixclock;
+	var->right_margin = (std_modes[mode].cr04 << 3) - xres;
+	var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
+			 (std_modes[mode].cr04 & 0x1F)) << 3;
 	var->left_margin = (total - (xres + var->right_margin + 
 				     var->hsync_len));
 	var->sync = FB_SYNC_ON_GREEN;
-	if (~(par.regs.msr & (1 << 6)))
+	if (~(std_modes[mode].msr & (1 << 6)))
 		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (~(par.regs.msr & (1 << 7)))
+	if (~(std_modes[mode].msr & (1 << 7)))
 		var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
-
-	total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F)  << 8)) + 2;
-	var->lower_margin = (par.regs.cr10 | 
-			     (par.regs.cr32 & 0x0F) << 8) - yres;
-	var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F);
-	var->upper_margin = total - (yres + var->lower_margin + 
-				     var->vsync_len);
+	total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF)  << 8) + 2;
+	var->lower_margin = (std_modes[mode].cr10 |
+			    (std_modes[mode].cr32 & 0x0F) << 8) - yres;
+	var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
+			 (var->lower_margin & 0x0F);
+	var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
 }
 
 u32 i810_get_watermark(struct fb_var_screeninfo *var,
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0cafd64..5ba3999 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -874,6 +874,9 @@
 	if (bailearly == 18)
 		bailout(dinfo);
 
+	/* read active pipe */
+	dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
+
 	/* Cursor initialisation */
 	if (dinfo->hwcursor) {
 		intelfbhw_cursor_init(dinfo);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 0689f97..8162746 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -469,6 +469,32 @@
 }
 
 
+/* Check which pipe is connected to an active display plane. */
+int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
+{
+	int pipe = -1;
+
+	/* keep old default behaviour - prefer PIPE_A */
+	if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
+		pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
+		pipe &= PIPE_MASK;
+		if (unlikely(pipe == PIPE_A))
+			return PIPE_A;
+	}
+	if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
+		pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
+		pipe &= PIPE_MASK;
+		if (likely(pipe == PIPE_A))
+			return PIPE_A;
+	}
+	/* Impossible that no pipe is selected - return PIPE_A */
+	WARN_ON(pipe == -1);
+	if (unlikely(pipe == -1))
+		pipe = PIPE_A;
+
+	return pipe;
+}
+
 void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
 			 unsigned red, unsigned green, unsigned blue,
 			 unsigned transp)
@@ -1019,7 +1045,7 @@
 			 struct intelfb_hwstate *hw,
 			 struct fb_var_screeninfo *var)
 {
-	int pipe = PIPE_A;
+	int pipe = intelfbhw_active_pipe(hw);
 	u32 *dpll, *fp0, *fp1;
 	u32 m1, m2, n, p1, p2, clock_target, clock;
 	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
@@ -1033,12 +1059,6 @@
 	/* Disable VGA */
 	hw->vgacntrl |= VGA_DISABLE;
 
-	/* Check whether pipe A or pipe B is enabled. */
-	if (hw->pipe_a_conf & PIPECONF_ENABLE)
-		pipe = PIPE_A;
-	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
-		pipe = PIPE_B;
-
 	/* Set which pipe's registers will be set. */
 	if (pipe == PIPE_B) {
 		dpll = &hw->dpll_b;
@@ -1262,7 +1282,6 @@
 int intelfbhw_program_mode(struct intelfb_info *dinfo,
 			   const struct intelfb_hwstate *hw, int blank)
 {
-	int pipe = PIPE_A;
 	u32 tmp;
 	const u32 *dpll, *fp0, *fp1, *pipe_conf;
 	const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
@@ -1272,7 +1291,7 @@
 	u32 src_size_reg;
 	u32 count, tmp_val[3];
 
-	/* Assume single pipe, display plane A, analog CRT. */
+	/* Assume single pipe */
 
 #if VERBOSE > 0
 	DBG_MSG("intelfbhw_program_mode\n");
@@ -1283,15 +1302,9 @@
 	tmp |= VGA_DISABLE;
 	OUTREG(VGACNTRL, tmp);
 
-	/* Check whether pipe A or pipe B is enabled. */
-	if (hw->pipe_a_conf & PIPECONF_ENABLE)
-		pipe = PIPE_A;
-	else if (hw->pipe_b_conf & PIPECONF_ENABLE)
-		pipe = PIPE_B;
+	dinfo->pipe = intelfbhw_active_pipe(hw);
 
-	dinfo->pipe = pipe;
-
-	if (pipe == PIPE_B) {
+	if (dinfo->pipe == PIPE_B) {
 		dpll = &hw->dpll_b;
 		fp0 = &hw->fpb0;
 		fp1 = &hw->fpb1;
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index 0b076ba..216ca20 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -604,5 +604,6 @@
 extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
 extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
 extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
+extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
 
 #endif /* _INTELFBHW_H */
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 09f6e04..c15f8a5 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -368,7 +368,8 @@
 					M1064_XDVICLKCTRL_C1DVICLKEN |
 					M1064_XDVICLKCTRL_DVILOOPCTL |
 					M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
-				matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp);
+                                /* Setting this breaks PC systems so don't do it */
+				/* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
 				matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
 						 xpwrctrl);
 
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 5e91c2b..7854c7a 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -92,6 +92,9 @@
 	/* value to be written into the palette reg. */
 	unsigned long hw_colorvalue = 0;
 
+	if (regno > 255)
+		return 1;
+
 	red   >>= 8;    /* The cmap fields are 16 bits    */
 	green >>= 8;    /* wide, but the harware colormap */
 	blue  >>= 8;    /* registers are only 8 bits wide */
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
index 0766481..d777771 100644
--- a/drivers/video/mb862xx/Makefile
+++ b/drivers/video/mb862xx/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the MB862xx framebuffer driver
 #
 
-obj-$(CONFIG_FB_MB862XX)	:= mb862xxfb.o
+obj-$(CONFIG_FB_MB862XX)	:= mb862xxfb.o mb862xxfb_accel.o
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index a28e3cf..fabb0c5 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -214,6 +214,8 @@
 	unsigned long reg, sc;
 
 	dev_dbg(par->dev, "%s\n", __func__);
+	if (par->type == BT_CORALP)
+		mb862xxfb_init_accel(fbi, fbi->var.xres);
 
 	if (par->pre_init)
 		return 0;
@@ -453,6 +455,18 @@
 		ptr += sprintf(ptr, "%08x = %08x\n",
 			       reg, inreg(disp, reg));
 
+	for (reg = 0x400; reg <= 0x410; reg += 4)
+		ptr += sprintf(ptr, "geo %08x = %08x\n",
+			       reg, inreg(geo, reg));
+
+	for (reg = 0x400; reg <= 0x410; reg += 4)
+		ptr += sprintf(ptr, "draw %08x = %08x\n",
+			       reg, inreg(draw, reg));
+
+	for (reg = 0x440; reg <= 0x450; reg += 4)
+		ptr += sprintf(ptr, "draw %08x = %08x\n",
+			       reg, inreg(draw, reg));
+
 	return ptr - buf;
 }
 
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
index c4c8f4d..d7e7cb7 100644
--- a/drivers/video/mb862xx/mb862xxfb.h
+++ b/drivers/video/mb862xx/mb862xxfb.h
@@ -61,6 +61,8 @@
 	u32			pseudo_palette[16];
 };
 
+extern void mb862xxfb_init_accel(struct fb_info *info, int xres);
+
 #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
 #error	"Select Lime GDC or CoralP/Carmine support, but not both together"
 #endif
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/mb862xx/mb862xxfb_accel.c
new file mode 100644
index 0000000..0492560
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xxfb_accel.c
@@ -0,0 +1,331 @@
+/*
+ * drivers/mb862xx/mb862xxfb_accel.c
+ *
+ * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver acceleration support
+ *
+ * (C) 2007 Alexander Shishkin <virtuoso@slind.org>
+ * (C) 2009 Valentin Sitdikov <valentin.sitdikov@siemens.com>
+ * (C) 2009 Siemens AG
+ *
+ * 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/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#if defined(CONFIG_OF)
+#include <linux/of_platform.h>
+#endif
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+#include "mb862xxfb_accel.h"
+
+static void mb862xxfb_write_fifo(u32 count, u32 *data, struct fb_info *info)
+{
+	struct mb862xxfb_par *par = info->par;
+	static u32 free;
+
+	u32 total = 0;
+	while (total < count) {
+		if (free) {
+			outreg(geo, GDC_GEO_REG_INPUT_FIFO, data[total]);
+			total++;
+			free--;
+		} else {
+			free = (u32) inreg(draw, GDC_REG_FIFO_COUNT);
+		}
+	}
+}
+
+static void mb86290fb_copyarea(struct fb_info *info,
+			       const struct fb_copyarea *area)
+{
+	__u32 cmd[6];
+
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* Set raster operation */
+	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+	cmd[2] = GDC_TYPE_BLTCOPYP << 24;
+
+	if (area->sx >= area->dx && area->sy >= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_TOP_LEFT << 16;
+	else if (area->sx >= area->dx && area->sy <= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_LEFT << 16;
+	else if (area->sx <= area->dx && area->sy >= area->dy)
+		cmd[2] |= GDC_CMD_BLTCOPY_TOP_RIGHT << 16;
+	else
+		cmd[2] |= GDC_CMD_BLTCOPY_BOTTOM_RIGHT << 16;
+
+	cmd[3] = (area->sy << 16) | area->sx;
+	cmd[4] = (area->dy << 16) | area->dx;
+	cmd[5] = (area->height << 16) | area->width;
+	mb862xxfb_write_fifo(6, cmd, info);
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 1bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit1(u32 *cmd, u16 step, u16 dx, u16 dy,
+				 u16 width, u16 height, u32 fgcolor,
+				 u32 bgcolor, const struct fb_image *image,
+				 struct fb_info *info)
+{
+	int i;
+	unsigned const char *line;
+	u16 bytes;
+
+	/* set colors and raster operation regs */
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* Set raster operation */
+	cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+	cmd[2] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
+	cmd[3] = fgcolor;
+	cmd[4] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_BACK_COLOR << 16);
+	cmd[5] = bgcolor;
+
+	i = 0;
+	line = image->data;
+	bytes = (image->width + 7) >> 3;
+
+	/* and the image */
+	cmd[6] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BITMAP << 16) | (2 + (step * height));
+	cmd[7] = (dy << 16) | dx;
+	cmd[8] = (height << 16) | width;
+
+	while (i < height) {
+		memcpy(&cmd[9 + i * step], line, step << 2);
+#ifdef __LITTLE_ENDIAN
+		{
+			int k = 0;
+			for (k = 0; k < step; k++)
+				cmd[9 + i * step + k] =
+				    cpu_to_be32(cmd[9 + i * step + k]);
+		}
+#endif
+		line += bytes;
+		i++;
+	}
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 8bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit8(u32 *cmd, u16 step, u16 dx, u16 dy,
+				 u16 width, u16 height, u32 fgcolor,
+				 u32 bgcolor, const struct fb_image *image,
+				 struct fb_info *info)
+{
+	int i, j;
+	unsigned const char *line, *ptr;
+	u16 bytes;
+
+	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BLT_DRAW << 16) | (2 + (height * step));
+	cmd[1] = (dy << 16) | dx;
+	cmd[2] = (height << 16) | width;
+
+	i = 0;
+	line = ptr = image->data;
+	bytes = image->width;
+
+	while (i < height) {
+		ptr = line;
+		for (j = 0; j < step; j++) {
+			cmd[3 + i * step + j] =
+			    (((u32 *) (info->pseudo_palette))[*ptr]) & 0xffff;
+			ptr++;
+			cmd[3 + i * step + j] |=
+			    ((((u32 *) (info->
+					pseudo_palette))[*ptr]) & 0xffff) << 16;
+			ptr++;
+		}
+
+		line += bytes;
+		i++;
+	}
+}
+
+/*
+ * Fill in the cmd array /GDC FIFO commands/ to draw a 16bit image.
+ * Make sure cmd has enough room!
+ */
+static void mb86290fb_imageblit16(u32 *cmd, u16 step, u16 dx, u16 dy,
+				  u16 width, u16 height, u32 fgcolor,
+				  u32 bgcolor, const struct fb_image *image,
+				  struct fb_info *info)
+{
+	int i;
+	unsigned const char *line;
+	u16 bytes;
+
+	i = 0;
+	line = image->data;
+	bytes = image->width << 1;
+
+	cmd[0] = (GDC_TYPE_DRAWBITMAPP << 24) |
+	    (GDC_CMD_BLT_DRAW << 16) | (2 + step * height);
+	cmd[1] = (dy << 16) | dx;
+	cmd[2] = (height << 16) | width;
+
+	while (i < height) {
+		memcpy(&cmd[3 + i * step], line, step);
+		line += bytes;
+		i++;
+	}
+}
+
+static void mb86290fb_imageblit(struct fb_info *info,
+				const struct fb_image *image)
+{
+	int mdr;
+	u32 *cmd = NULL;
+	void (*cmdfn) (u32 *, u16, u16, u16, u16, u16, u32, u32,
+		       const struct fb_image *, struct fb_info *) = NULL;
+	u32 cmdlen;
+	u32 fgcolor = 0, bgcolor = 0;
+	u16 step;
+
+	u16 width = image->width, height = image->height;
+	u16 dx = image->dx, dy = image->dy;
+	int x2, y2, vxres, vyres;
+
+	mdr = (GDC_ROP_COPY << 9);
+	x2 = image->dx + image->width;
+	y2 = image->dy + image->height;
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+	x2 = min(x2, vxres);
+	y2 = min(y2, vyres);
+	width = x2 - dx;
+	height = y2 - dy;
+
+	switch (image->depth) {
+	case 1:
+		step = (width + 31) >> 5;
+		cmdlen = 9 + height * step;
+		cmdfn = mb86290fb_imageblit1;
+		if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+			fgcolor =
+			    ((u32 *) (info->pseudo_palette))[image->fg_color];
+			bgcolor =
+			    ((u32 *) (info->pseudo_palette))[image->bg_color];
+		} else {
+			fgcolor = image->fg_color;
+			bgcolor = image->bg_color;
+		}
+
+		break;
+
+	case 8:
+		step = (width + 1) >> 1;
+		cmdlen = 3 + height * step;
+		cmdfn = mb86290fb_imageblit8;
+		break;
+
+	case 16:
+		step = (width + 1) >> 1;
+		cmdlen = 3 + height * step;
+		cmdfn = mb86290fb_imageblit16;
+		break;
+
+	default:
+		cfb_imageblit(info, image);
+		return;
+	}
+
+	cmd = kmalloc(cmdlen * 4, GFP_DMA);
+	if (!cmd)
+		return cfb_imageblit(info, image);
+	cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
+	mb862xxfb_write_fifo(cmdlen, cmd, info);
+	kfree(cmd);
+}
+
+static void mb86290fb_fillrect(struct fb_info *info,
+			       const struct fb_fillrect *rect)
+{
+
+	u32 x2, y2, vxres, vyres, height, width, fg;
+	u32 cmd[7];
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!rect->width || !rect->height || rect->dx > vxres
+	    || rect->dy > vyres)
+		return;
+
+	/* We could use hardware clipping but on many cards you get around
+	 * hardware clipping by writing to framebuffer directly. */
+	x2 = rect->dx + rect->width;
+	y2 = rect->dy + rect->height;
+	x2 = min(x2, vxres);
+	y2 = min(y2, vyres);
+	width = x2 - rect->dx;
+	height = y2 - rect->dy;
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		fg = ((u32 *) (info->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	switch (rect->rop) {
+
+	case ROP_XOR:
+		/* Set raster operation */
+		cmd[1] = (2 << 7) | (GDC_ROP_XOR << 9);
+		break;
+
+	case ROP_COPY:
+		/* Set raster operation */
+		cmd[1] = (2 << 7) | (GDC_ROP_COPY << 9);
+		break;
+
+	}
+
+	cmd[0] = (GDC_TYPE_SETREGISTER << 24) | (1 << 16) | GDC_REG_MODE_BITMAP;
+	/* cmd[1] set earlier */
+	cmd[2] =
+	    (GDC_TYPE_SETCOLORREGISTER << 24) | (GDC_CMD_BODY_FORE_COLOR << 16);
+	cmd[3] = fg;
+	cmd[4] = (GDC_TYPE_DRAWRECTP << 24) | (GDC_CMD_BLT_FILL << 16);
+	cmd[5] = (rect->dy << 16) | (rect->dx);
+	cmd[6] = (height << 16) | width;
+
+	mb862xxfb_write_fifo(7, cmd, info);
+}
+
+void mb862xxfb_init_accel(struct fb_info *info, int xres)
+{
+	struct mb862xxfb_par *par = info->par;
+
+	if (info->var.bits_per_pixel == 32) {
+		info->fbops->fb_fillrect = cfb_fillrect;
+		info->fbops->fb_copyarea = cfb_copyarea;
+		info->fbops->fb_imageblit = cfb_imageblit;
+	} else {
+		outreg(disp, GC_L0EM, 3);
+		info->fbops->fb_fillrect = mb86290fb_fillrect;
+		info->fbops->fb_copyarea = mb86290fb_copyarea;
+		info->fbops->fb_imageblit = mb86290fb_imageblit;
+	}
+	outreg(draw, GDC_REG_DRAW_BASE, 0);
+	outreg(draw, GDC_REG_MODE_MISC, 0x8000);
+	outreg(draw, GDC_REG_X_RESOLUTION, xres);
+
+	info->flags |=
+	    FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+	    FBINFO_HWACCEL_IMAGEBLIT;
+	info->fix.accel = 0xff;	/*FIXME: add right define */
+}
+EXPORT_SYMBOL(mb862xxfb_init_accel);
diff --git a/drivers/video/mb862xx/mb862xxfb_accel.h b/drivers/video/mb862xx/mb862xxfb_accel.h
new file mode 100644
index 0000000..96a2dfe
--- /dev/null
+++ b/drivers/video/mb862xx/mb862xxfb_accel.h
@@ -0,0 +1,203 @@
+#ifndef __MB826XXFB_ACCEL_H__
+#define __MB826XXFB_ACCEL_H__
+
+/* registers */
+#define GDC_GEO_REG_INPUT_FIFO 0x00000400L
+
+/* Special Registers */
+#define GDC_REG_CTRL                0x00000400L
+#define GDC_REG_FIFO_STATUS         0x00000404L
+#define GDC_REG_FIFO_COUNT          0x00000408L
+#define GDC_REG_SETUP_STATUS        0x0000040CL
+#define GDC_REG_DDA_STATUS          0x00000410L
+#define GDC_REG_ENGINE_STATUS       0x00000414L
+#define GDC_REG_ERROR_STATUS        0x00000418L
+#define GDC_REG_MODE_MISC           0x00000420L	/* MDR0 */
+#define GDC_REG_MODE_LINE           0x00000424L	/* MDR1 */
+#define GDC_REG_MODE_POLYGON        0x00000428L	/* MDR2 */
+#define GDC_REG_MODE_TEXTURE        0x0000042CL	/* MDR3 */
+#define GDC_REG_MODE_BITMAP         0x00000430L	/* MDR4 */
+#define GDC_REG_MODE_EXTENSION      0x0000043CL	/* MDR7 */
+
+/* Configuration Registers */
+#define GDC_REG_DRAW_BASE           0x00000440L
+#define GDC_REG_X_RESOLUTION        0x00000444L
+#define GDC_REG_Z_BASE              0x00000448L
+#define GDC_REG_TEXTURE_BASE        0x0000044CL
+#define GDC_REG_POLYGON_FLAG_BASE   0x00000450L
+#define GDC_REG_CLIP_XMIN           0x00000454L
+#define GDC_REG_CLIP_XMAX           0x00000458L
+#define GDC_REG_CLIP_YMIN           0x0000045CL
+#define GDC_REG_CLIP_YMAX           0x00000460L
+#define GDC_REG_TEXURE_SIZE         0x00000464L
+#define GDC_REG_TILE_SIZE           0x00000468L
+#define GDC_REG_TEX_BUF_OFFSET      0x0000046CL
+
+/* for MB86293 or later */
+#define GDC_REG_ALPHA_MAP_BASE      0x00000474L	/* ABR */
+
+/* Constant Registers */
+#define GDC_REG_FOREGROUND_COLOR    0x00000480L
+#define GDC_REG_BACKGROUND_COLOR    0x00000484L
+#define GDC_REG_ALPHA               0x00000488L
+#define GDC_REG_LINE_PATTERN        0x0000048CL
+#define GDC_REG_TEX_BORDER_COLOR    0x00000494L
+#define GDC_REG_LINE_PATTERN_OFFSET 0x000003E0L
+
+/* Coomand Code */
+#define GDC_CMD_PIXEL                   0x00000000L
+#define GDC_CMD_PIXEL_Z                 0x00000001L
+
+#define GDC_CMD_X_VECTOR                0x00000020L
+#define GDC_CMD_Y_VECTOR                0x00000021L
+#define GDC_CMD_X_VECTOR_NOEND          0x00000022L
+#define GDC_CMD_Y_VECTOR_NOEND          0x00000023L
+#define GDC_CMD_X_VECTOR_BLPO           0x00000024L
+#define GDC_CMD_Y_VECTOR_BLPO           0x00000025L
+#define GDC_CMD_X_VECTOR_NOEND_BLPO     0x00000026L
+#define GDC_CMD_Y_VECTOR_NOEND_BLPO     0x00000027L
+#define GDC_CMD_AA_X_VECTOR             0x00000028L
+#define GDC_CMD_AA_Y_VECTOR             0x00000029L
+#define GDC_CMD_AA_X_VECTOR_NOEND       0x0000002AL
+#define GDC_CMD_AA_Y_VECTOR_NOEND       0x0000002BL
+#define GDC_CMD_AA_X_VECTOR_BLPO        0x0000002CL
+#define GDC_CMD_AA_Y_VECTOR_BLPO        0x0000002DL
+#define GDC_CMD_AA_X_VECTOR_NOEND_BLPO  0x0000002EL
+#define GDC_CMD_AA_Y_VECTOR_NOEND_BLPO  0x0000002FL
+
+#define GDC_CMD_0_VECTOR                0x00000030L
+#define GDC_CMD_1_VECTOR                0x00000031L
+#define GDC_CMD_0_VECTOR_NOEND          0x00000032L
+#define GDC_CMD_1_VECTOR_NOEND          0x00000033L
+#define GDC_CMD_0_VECTOR_BLPO           0x00000034L
+#define GDC_CMD_1_VECTOR_BLPO           0x00000035L
+#define GDC_CMD_0_VECTOR_NOEND_BLPO     0x00000036L
+#define GDC_CMD_1_VECTOR_NOEND_BLPO     0x00000037L
+#define GDC_CMD_AA_0_VECTOR             0x00000038L
+#define GDC_CMD_AA_1_VECTOR             0x00000039L
+#define GDC_CMD_AA_0_VECTOR_NOEND       0x0000003AL
+#define GDC_CMD_AA_1_VECTOR_NOEND       0x0000003BL
+#define GDC_CMD_AA_0_VECTOR_BLPO        0x0000003CL
+#define GDC_CMD_AA_1_VECTOR_BLPO        0x0000003DL
+#define GDC_CMD_AA_0_VECTOR_NOEND_BLPO  0x0000003EL
+#define GDC_CMD_AA_1_VECTOR_NOEND_BLPO  0x0000003FL
+
+#define GDC_CMD_BLT_FILL                0x00000041L
+#define GDC_CMD_BLT_DRAW                0x00000042L
+#define GDC_CMD_BITMAP                  0x00000043L
+#define GDC_CMD_BLTCOPY_TOP_LEFT        0x00000044L
+#define GDC_CMD_BLTCOPY_TOP_RIGHT       0x00000045L
+#define GDC_CMD_BLTCOPY_BOTTOM_LEFT     0x00000046L
+#define GDC_CMD_BLTCOPY_BOTTOM_RIGHT    0x00000047L
+#define GDC_CMD_LOAD_TEXTURE            0x00000048L
+#define GDC_CMD_LOAD_TILE               0x00000049L
+
+#define GDC_CMD_TRAP_RIGHT              0x00000060L
+#define GDC_CMD_TRAP_LEFT               0x00000061L
+#define GDC_CMD_TRIANGLE_FAN            0x00000062L
+#define GDC_CMD_FLAG_TRIANGLE_FAN       0x00000063L
+
+#define GDC_CMD_FLUSH_FB                0x000000C1L
+#define GDC_CMD_FLUSH_Z                 0x000000C2L
+
+#define GDC_CMD_POLYGON_BEGIN           0x000000E0L
+#define GDC_CMD_POLYGON_END             0x000000E1L
+#define GDC_CMD_CLEAR_POLY_FLAG         0x000000E2L
+#define GDC_CMD_NORMAL                  0x000000FFL
+
+#define GDC_CMD_VECTOR_BLPO_FLAG        0x00040000L
+#define GDC_CMD_FAST_VECTOR_BLPO_FLAG   0x00000004L
+
+/* for MB86293 or later */
+#define GDC_CMD_MDR1                            0x00000000L
+#define GDC_CMD_MDR1S                           0x00000002L
+#define GDC_CMD_MDR1B                           0x00000004L
+#define GDC_CMD_MDR2                            0x00000001L
+#define GDC_CMD_MDR2S                           0x00000003L
+#define GDC_CMD_MDR2TL                          0x00000007L
+#define GDC_CMD_GMDR1E                          0x00000010L
+#define GDC_CMD_GMDR2E                          0x00000020L
+#define GDC_CMD_OVERLAP_SHADOW_XY               0x00000000L
+#define GDC_CMD_OVERLAP_SHADOW_XY_COMPOSITION   0x00000001L
+#define GDC_CMD_OVERLAP_Z_PACKED_ONBS           0x00000007L
+#define GDC_CMD_OVERLAP_Z_ORIGIN                0x00000000L
+#define GDC_CMD_OVERLAP_Z_NON_TOPLEFT           0x00000001L
+#define GDC_CMD_OVERLAP_Z_BORDER                0x00000002L
+#define GDC_CMD_OVERLAP_Z_SHADOW                0x00000003L
+#define GDC_CMD_BLTCOPY_ALT_ALPHA               0x00000000L	/* Reserverd */
+#define GDC_CMD_DC_LOGOUT                       0x00000000L	/* Reserverd */
+#define GDC_CMD_BODY_FORE_COLOR                 0x00000000L
+#define GDC_CMD_BODY_BACK_COLOR                 0x00000001L
+#define GDC_CMD_SHADOW_FORE_COLOR               0x00000002L
+#define GDC_CMD_SHADOW_BACK_COLOR               0x00000003L
+#define GDC_CMD_BORDER_FORE_COLOR               0x00000004L
+#define GDC_CMD_BORDER_BACK_COLOR               0x00000005L
+
+/* Type Code Table */
+#define GDC_TYPE_G_NOP                                  0x00000020L
+#define GDC_TYPE_G_BEGIN                                0x00000021L
+#define GDC_TYPE_G_BEGINCONT                            0x00000022L
+#define GDC_TYPE_G_END                                  0x00000023L
+#define GDC_TYPE_G_VERTEX                               0x00000030L
+#define GDC_TYPE_G_VERTEXLOG                            0x00000032L
+#define GDC_TYPE_G_VERTEXNOPLOG                         0x00000033L
+#define GDC_TYPE_G_INIT                                 0x00000040L
+#define GDC_TYPE_G_VIEWPORT                             0x00000041L
+#define GDC_TYPE_G_DEPTHRANGE                           0x00000042L
+#define GDC_TYPE_G_LOADMATRIX                           0x00000043L
+#define GDC_TYPE_G_VIEWVOLUMEXYCLIP                     0x00000044L
+#define GDC_TYPE_G_VIEWVOLUMEZCLIP                      0x00000045L
+#define GDC_TYPE_G_VIEWVOLUMEWCLIP                      0x00000046L
+#define GDC_TYPE_SETLVERTEX2I                           0x00000072L
+#define GDC_TYPE_SETLVERTEX2IP                          0x00000073L
+#define GDC_TYPE_SETMODEREGISTER                        0x000000C0L
+#define GDC_TYPE_SETGMODEREGISTER                       0x000000C1L
+#define GDC_TYPE_OVERLAPXYOFFT                          0x000000C8L
+#define GDC_TYPE_OVERLAPZOFFT                           0x000000C9L
+#define GDC_TYPE_DC_LOGOUTADDR                          0x000000CCL
+#define GDC_TYPE_SETCOLORREGISTER                       0x000000CEL
+#define GDC_TYPE_G_BEGINE                               0x000000E1L
+#define GDC_TYPE_G_BEGINCONTE                           0x000000E2L
+#define GDC_TYPE_G_ENDE                                 0x000000E3L
+#define GDC_TYPE_DRAWPIXEL                              0x00000000L
+#define GDC_TYPE_DRAWPIXELZ                             0x00000001L
+#define GDC_TYPE_DRAWLINE                               0x00000002L
+#define GDC_TYPE_DRAWLINE2I                             0x00000003L
+#define GDC_TYPE_DRAWLINE2IP                            0x00000004L
+#define GDC_TYPE_DRAWTRAP                               0x00000005L
+#define GDC_TYPE_DRAWVERTEX2I                           0x00000006L
+#define GDC_TYPE_DRAWVERTEX2IP                          0x00000007L
+#define GDC_TYPE_DRAWRECTP                              0x00000009L
+#define GDC_TYPE_DRAWBITMAPP                            0x0000000BL
+#define GDC_TYPE_BLTCOPYP                               0x0000000DL
+#define GDC_TYPE_BLTCOPYALTERNATEP                      0x0000000FL
+#define GDC_TYPE_LOADTEXTUREP                           0x00000011L
+#define GDC_TYPE_BLTTEXTUREP                            0x00000013L
+#define GDC_TYPE_BLTCOPYALTALPHABLENDP                  0x0000001FL
+#define GDC_TYPE_SETVERTEX2I                            0x00000070L
+#define GDC_TYPE_SETVERTEX2IP                           0x00000071L
+#define GDC_TYPE_DRAW                                   0x000000F0L
+#define GDC_TYPE_SETREGISTER                            0x000000F1L
+#define GDC_TYPE_SYNC                                   0x000000FCL
+#define GDC_TYPE_INTERRUPT                              0x000000FDL
+#define GDC_TYPE_NOP                                    0x0
+
+/* Raster operation */
+#define GDC_ROP_CLEAR                   0x0000
+#define GDC_ROP_AND                     0x0001
+#define GDC_ROP_AND_REVERSE             0x0002
+#define GDC_ROP_COPY                    0x0003
+#define GDC_ROP_AND_INVERTED            0x0004
+#define GDC_ROP_NOP                     0x0005
+#define GDC_ROP_XOR                     0x0006
+#define GDC_ROP_OR                      0x0007
+#define GDC_ROP_NOR                     0x0008
+#define GDC_ROP_EQUIV                   0x0009
+#define GDC_ROP_INVERT                  0x000A
+#define GDC_ROP_OR_REVERSE              0x000B
+#define GDC_ROP_COPY_INVERTED           0x000C
+#define GDC_ROP_OR_INVERTED             0x000D
+#define GDC_ROP_NAND                    0x000E
+#define GDC_ROP_SET                     0x000F
+
+#endif
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 34e4e79..0129f1b 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -13,6 +13,7 @@
 
 #include <linux/module.h>
 #include <linux/fb.h>
+#include <linux/kernel.h>
 
 #undef DEBUG
 
@@ -402,21 +403,6 @@
 EXPORT_SYMBOL(vesa_modes);
 #endif /* CONFIG_FB_MODE_HELPERS */
 
-static int my_atoi(const char *name)
-{
-    int val = 0;
-
-    for (;; name++) {
-	switch (*name) {
-	    case '0' ... '9':
-		val = 10*val+(*name-'0');
-		break;
-	    default:
-		return val;
-	}
-    }
-}
-
 /**
  *	fb_try_mode - test a video mode
  *	@var: frame buffer user defined part of display
@@ -539,7 +525,7 @@
 		    namelen = i;
 		    if (!refresh_specified && !bpp_specified &&
 			!yres_specified) {
-			refresh = my_atoi(&name[i+1]);
+			refresh = simple_strtol(&name[i+1], NULL, 10);
 			refresh_specified = 1;
 			if (cvt || rb)
 			    cvt = 0;
@@ -549,7 +535,7 @@
 		case '-':
 		    namelen = i;
 		    if (!bpp_specified && !yres_specified) {
-			bpp = my_atoi(&name[i+1]);
+			bpp = simple_strtol(&name[i+1], NULL, 10);
 			bpp_specified = 1;
 			if (cvt || rb)
 			    cvt = 0;
@@ -558,7 +544,7 @@
 		    break;
 		case 'x':
 		    if (!yres_specified) {
-			yres = my_atoi(&name[i+1]);
+			yres = simple_strtol(&name[i+1], NULL, 10);
 			yres_specified = 1;
 		    } else
 			goto done;
@@ -586,7 +572,7 @@
 	    }
 	}
 	if (i < 0 && yres_specified) {
-	    xres = my_atoi(name);
+	    xres = simple_strtol(name, NULL, 10);
 	    res_specified = 1;
 	}
 done:
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 0573ec6..0f361b6 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -98,7 +98,8 @@
 {
 	struct pmagbafb_par *par = info->par;
 
-	BUG_ON(regno >= info->cmap.len);
+	if (regno >= info->cmap.len)
+		return 1;
 
 	red   >>= 8;	/* The cmap fields are 16 bits    */
 	green >>= 8;	/* wide, but the hardware colormap */
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 9874872..2de0806 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -102,7 +102,8 @@
 {
 	struct pmagbbfb_par *par = info->par;
 
-	BUG_ON(regno >= info->cmap.len);
+	if (regno >= info->cmap.len)
+		return 1;
 
 	red   >>= 8;	/* The cmap fields are 16 bits    */
 	green >>= 8;	/* wide, but the hardware colormap */
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index b7e5805..415858b 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1221,13 +1221,14 @@
 static int pxafb_smart_thread(void *arg)
 {
 	struct pxafb_info *fbi = arg;
-	struct pxafb_mach_info *inf = fbi->dev->platform_data;
+	struct pxafb_mach_info *inf;
 
-	if (!fbi || !inf->smart_update) {
+	if (!fbi || !fbi->dev->platform_data->smart_update) {
 		pr_err("%s: not properly initialized, thread terminated\n",
 				__func__);
 		return -EINVAL;
 	}
+	inf = fbi->dev->platform_data;
 
 	pr_debug("%s(): task starting\n", __func__);
 
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 8a65fb6..a69830d 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -281,6 +281,7 @@
 				       struct list_head *pagelist)
 {
 	struct sh_mobile_lcdc_chan *ch = info->par;
+	struct sh_mobile_lcdc_board_cfg	*bcfg = &ch->cfg.board_cfg;
 
 	/* enable clocks before accessing hardware */
 	sh_mobile_lcdc_clk_on(ch->lcdc);
@@ -305,10 +306,17 @@
 
 		/* trigger panel update */
 		dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
+		if (bcfg->start_transfer)
+			bcfg->start_transfer(bcfg->board_data, ch,
+					     &sh_mobile_lcdc_sys_bus_ops);
 		lcdc_write_chan(ch, LDSM2R, 1);
 		dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
-	} else
+	} else {
+		if (bcfg->start_transfer)
+			bcfg->start_transfer(bcfg->board_data, ch,
+					     &sh_mobile_lcdc_sys_bus_ops);
 		lcdc_write_chan(ch, LDSM2R, 1);
+	}
 }
 
 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index a4e05e4..9d2b6bc 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -2115,7 +2115,7 @@
 	   if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) &&
 	       (!((ivideo->sisvga_engine == SIS_315_VGA) &&
 			(ivideo->vbflags2 & VB2_CHRONTEL))) ) {
-	      if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
+	      if(ivideo->sisfb_tvstd & (TV_PALM | TV_PALN | TV_NTSCJ)) {
 		 ivideo->sisfb_tvstd = -1;
 		 printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
 	      }
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 924d794..35370d0 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -29,8 +29,8 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/console.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/div64.h>
 
@@ -66,6 +66,7 @@
 	struct fb_info		*fb[2];		/* fb info for both heads */
 	struct resource		*fbmem_res;	/* framebuffer resource */
 	struct resource		*regs_res;	/* registers resource */
+	struct resource		*regs2d_res;	/* 2d registers resource */
 	struct sm501_platdata_fb *pdata;	/* our platform data */
 
 	unsigned long		 pm_crt_ctrl;	/* pm: crt ctrl save */
@@ -73,6 +74,7 @@
 	int			 irq;
 	int			 swap_endian;	/* set to swap rgb=>bgr */
 	void __iomem		*regs;		/* remapped registers */
+	void __iomem		*regs2d;	/* 2d remapped registers */
 	void __iomem		*fbmem;		/* remapped framebuffer */
 	size_t			 fbmem_len;	/* length of remapped region */
 };
@@ -123,9 +125,9 @@
  * This is an attempt to lay out memory for the two framebuffers and
  * everything else
  *
- * |fbmem_res->start	                                       fbmem_res->end|
- * |                                                                         |
- * |fb[0].fix.smem_start    |         |fb[1].fix.smem_start    |     2K      |
+ * |fbmem_res->start					       fbmem_res->end|
+ * |									     |
+ * |fb[0].fix.smem_start    |	      |fb[1].fix.smem_start    |     2K	     |
  * |-> fb[0].fix.smem_len <-| spare   |-> fb[1].fix.smem_len <-|-> cursors <-|
  *
  * The "spare" space is for the 2d engine data
@@ -1246,7 +1248,173 @@
 
 static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL);
 
-/* framebuffer ops */
+/* acceleration operations */
+static int sm501fb_sync(struct fb_info *info)
+{
+	int count = 1000000;
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+
+	/* wait for the 2d engine to be ready */
+	while ((count > 0) &&
+	       (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+		SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
+		count--;
+
+	if (count <= 0) {
+		dev_err(info->dev, "Timeout waiting for 2d engine sync\n");
+		return 1;
+	}
+	return 0;
+}
+
+static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	int width = area->width;
+	int height = area->height;
+	int sx = area->sx;
+	int sy = area->sy;
+	int dx = area->dx;
+	int dy = area->dy;
+	unsigned long rtl = 0;
+
+	/* source clip */
+	if ((sx >= info->var.xres_virtual) ||
+	    (sy >= info->var.yres_virtual))
+		/* source Area not within virtual screen, skipping */
+		return;
+	if ((sx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - sx - 1;
+	if ((sy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - sy - 1;
+
+	/* dest clip */
+	if ((dx >= info->var.xres_virtual) ||
+	    (dy >= info->var.yres_virtual))
+		/* Destination Area not within virtual screen, skipping */
+		return;
+	if ((dx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - dx - 1;
+	if ((dy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - dy - 1;
+
+	if ((sx < dx) || (sy < dy)) {
+		rtl = 1 << 27;
+		sx += width - 1;
+		dx += width - 1;
+		sy += height - 1;
+		dy += height - 1;
+	}
+
+	if (sm501fb_sync(info))
+		return;
+
+	/* set the base addresses */
+	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+
+	/* set the window width */
+	writel((info->var.xres << 16) | info->var.xres,
+	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
+
+	/* set window stride */
+	writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	       fbi->regs2d + SM501_2D_PITCH);
+
+	/* set data format */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 16:
+		writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 32:
+		writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	}
+
+	/* 2d compare mask */
+	writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+
+	/* 2d mask */
+	writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+
+	/* source and destination x y */
+	writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+	writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+
+	/* w/h */
+	writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+
+	/* do area move */
+	writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+}
+
+static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct sm501fb_par  *par = info->par;
+	struct sm501fb_info *fbi = par->info;
+	int width = rect->width, height = rect->height;
+
+	if ((rect->dx >= info->var.xres_virtual) ||
+	    (rect->dy >= info->var.yres_virtual))
+		/* Rectangle not within virtual screen, skipping */
+		return;
+	if ((rect->dx + width) >= info->var.xres_virtual)
+		width = info->var.xres_virtual - rect->dx - 1;
+	if ((rect->dy + height) >= info->var.yres_virtual)
+		height = info->var.yres_virtual - rect->dy - 1;
+
+	if (sm501fb_sync(info))
+		return;
+
+	/* set the base addresses */
+	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+
+	/* set the window width */
+	writel((info->var.xres << 16) | info->var.xres,
+	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
+
+	/* set window stride */
+	writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	       fbi->regs2d + SM501_2D_PITCH);
+
+	/* set data format */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 16:
+		writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	case 32:
+		writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		break;
+	}
+
+	/* 2d compare mask */
+	writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+
+	/* 2d mask */
+	writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+
+	/* colour */
+	writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+
+	/* x y */
+	writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
+
+	/* w/h */
+	writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+
+	/* do rectangle fill */
+	writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+}
+
 
 static struct fb_ops sm501fb_ops_crt = {
 	.owner		= THIS_MODULE,
@@ -1256,9 +1424,10 @@
 	.fb_setcolreg	= sm501fb_setcolreg,
 	.fb_pan_display	= sm501fb_pan_crt,
 	.fb_cursor	= sm501fb_cursor,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
+	.fb_fillrect	= sm501fb_fillrect,
+	.fb_copyarea	= sm501fb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= sm501fb_sync,
 };
 
 static struct fb_ops sm501fb_ops_pnl = {
@@ -1269,9 +1438,10 @@
 	.fb_blank	= sm501fb_blank_pnl,
 	.fb_setcolreg	= sm501fb_setcolreg,
 	.fb_cursor	= sm501fb_cursor,
-	.fb_fillrect	= cfb_fillrect,
-	.fb_copyarea	= cfb_copyarea,
+	.fb_fillrect	= sm501fb_fillrect,
+	.fb_copyarea	= sm501fb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= sm501fb_sync,
 };
 
 /* sm501_init_cursor
@@ -1329,7 +1499,8 @@
 		dev_warn(dev, "no irq for device\n");
 	}
 
-	/* allocate, reserve and remap resources for registers */
+	/* allocate, reserve and remap resources for display
+	 * controller registers */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
 		dev_err(dev, "no resource definition for registers\n");
@@ -1338,7 +1509,7 @@
 	}
 
 	info->regs_res = request_mem_region(res->start,
-					    res->end - res->start,
+					    resource_size(res),
 					    pdev->name);
 
 	if (info->regs_res == NULL) {
@@ -1347,37 +1518,63 @@
 		goto err_release;
 	}
 
-	info->regs = ioremap(res->start, (res->end - res->start)+1);
+	info->regs = ioremap(res->start, resource_size(res));
 	if (info->regs == NULL) {
 		dev_err(dev, "cannot remap registers\n");
 		ret = -ENXIO;
 		goto err_regs_res;
 	}
 
+	/* allocate, reserve and remap resources for 2d
+	 * controller registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL) {
+		dev_err(dev, "no resource definition for 2d registers\n");
+		ret = -ENOENT;
+		goto err_regs_map;
+	}
+
+	info->regs2d_res = request_mem_region(res->start,
+					      resource_size(res),
+					      pdev->name);
+
+	if (info->regs2d_res == NULL) {
+		dev_err(dev, "cannot claim registers\n");
+		ret = -ENXIO;
+		goto err_regs_map;
+	}
+
+	info->regs2d = ioremap(res->start, resource_size(res));
+	if (info->regs2d == NULL) {
+		dev_err(dev, "cannot remap registers\n");
+		ret = -ENXIO;
+		goto err_regs2d_res;
+	}
+
 	/* allocate, reserve resources for framebuffer */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
 	if (res == NULL) {
 		dev_err(dev, "no memory resource defined\n");
 		ret = -ENXIO;
-		goto err_regs_map;
+		goto err_regs2d_map;
 	}
 
 	info->fbmem_res = request_mem_region(res->start,
-					     (res->end - res->start)+1,
+					     resource_size(res),
 					     pdev->name);
 	if (info->fbmem_res == NULL) {
 		dev_err(dev, "cannot claim framebuffer\n");
 		ret = -ENXIO;
-		goto err_regs_map;
+		goto err_regs2d_map;
 	}
 
-	info->fbmem = ioremap(res->start, (res->end - res->start)+1);
+	info->fbmem = ioremap(res->start, resource_size(res));
 	if (info->fbmem == NULL) {
 		dev_err(dev, "cannot remap framebuffer\n");
 		goto err_mem_res;
 	}
 
-	info->fbmem_len = (res->end - res->start)+1;
+	info->fbmem_len = resource_size(res);
 
 	/* clear framebuffer memory - avoids garbage data on unused fb */
 	memset(info->fbmem, 0, info->fbmem_len);
@@ -1389,8 +1586,10 @@
 	/* enable display controller */
 	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
 
-	/* setup cursors */
+	/* enable 2d controller */
+	sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1);
 
+	/* setup cursors */
 	sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR);
 	sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR);
 
@@ -1400,6 +1599,13 @@
 	release_resource(info->fbmem_res);
 	kfree(info->fbmem_res);
 
+ err_regs2d_map:
+	iounmap(info->regs2d);
+
+ err_regs2d_res:
+	release_resource(info->regs2d_res);
+	kfree(info->regs2d_res);
+
  err_regs_map:
 	iounmap(info->regs);
 
@@ -1420,6 +1626,10 @@
 	release_resource(info->fbmem_res);
 	kfree(info->fbmem_res);
 
+	iounmap(info->regs2d);
+	release_resource(info->regs2d_res);
+	kfree(info->regs2d_res);
+
 	iounmap(info->regs);
 	release_resource(info->regs_res);
 	kfree(info->regs_res);
@@ -1486,7 +1696,8 @@
 		par->ops.fb_cursor = NULL;
 
 	fb->fbops = &par->ops;
-	fb->flags = FBINFO_FLAG_DEFAULT |
+	fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
 		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
 
 	/* fixed data */
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index e3e597f..09353e2 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -1134,45 +1134,33 @@
 			    *plvds_setting_info,
 			    struct lvds_chip_information *plvds_chip_info)
 {
-	bool turn_on_first_powersequence = false;
-	bool turn_on_second_powersequence = false;
-
 	DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
 		  plvds_chip_info->output_interface);
 	if (plvds_setting_info->lcd_mode == LCD_SPWG)
 		viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
-	 else
+	else
 		viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
-	if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
-		turn_on_first_powersequence = true;
-	if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
-		turn_on_first_powersequence = true;
-	if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
-		turn_on_second_powersequence = true;
 
-	if (turn_on_second_powersequence) {
-		/* Use second power sequence control: */
-
-		/* Use hardware control power sequence. */
-		viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
-
-		/* Turn on back light. */
-		viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
-
-		/* Turn on hardware power sequence. */
-		viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
-	}
-	if (turn_on_first_powersequence) {
+	switch (plvds_chip_info->output_interface) {
+	case INTERFACE_LVDS0LVDS1:
+	case INTERFACE_LVDS0:
 		/* Use first power sequence control: */
-
 		/* Use hardware control power sequence. */
 		viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
-
 		/* Turn on back light. */
 		viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
-
 		/* Turn on hardware power sequence. */
 		viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
+		break;
+	case INTERFACE_LVDS1:
+		/* Use second power sequence control: */
+		/* Use hardware control power sequence. */
+		viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
+		/* Turn on back light. */
+		viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
+		/* Turn on hardware power sequence. */
+		viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
+		break;
 	}
 
 	/* Turn DFP High/Low pad on. */
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 56ec696..d8df17a 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -680,7 +680,7 @@
 		if (!viafb_gamma_table)
 			return -ENOMEM;
 		if (copy_from_user(viafb_gamma_table, argp,
-				sizeof(viafb_gamma_table))) {
+				256 * sizeof(u32))) {
 			kfree(viafb_gamma_table);
 			return -EFAULT;
 		}
@@ -694,7 +694,7 @@
 			return -ENOMEM;
 		viafb_get_gamma_table(viafb_gamma_table);
 		if (copy_to_user(argp, viafb_gamma_table,
-			sizeof(viafb_gamma_table))) {
+			256 * sizeof(u32))) {
 			kfree(viafb_gamma_table);
 			return -EFAULT;
 		}
@@ -1797,7 +1797,7 @@
 static void viafb_init_proc(struct proc_dir_entry **viafb_entry)
 {
 	*viafb_entry = proc_mkdir("viafb", NULL);
-	if (viafb_entry) {
+	if (*viafb_entry) {
 		proc_create("dvp0", 0, *viafb_entry, &viafb_dvp0_proc_fops);
 		proc_create("dvp1", 0, *viafb_entry, &viafb_dvp1_proc_fops);
 		proc_create("dfph", 0, *viafb_entry, &viafb_dfph_proc_fops);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d958b76..da84fd0 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -815,16 +815,6 @@
 	  timer has expired and no process has written to /dev/watchdog during
 	  that time.
 
-config WDT_RM9K_GPI
-	tristate "RM9000/GPI hardware watchdog"
-	depends on CPU_RM9000
-	help
-	  Watchdog implementation using the GPI hardware found on
-	  PMC-Sierra RM9xxx CPUs.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called rm9k_wdt.
-
 config SIBYTE_WDOG
 	tristate "Sibyte SoC hardware watchdog"
 	depends on CPU_SB1
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 89c045d..475c611 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -109,7 +109,6 @@
 obj-$(CONFIG_INDYDOG) += indydog.o
 obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
 obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
-obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
 obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
 obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
 obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c
deleted file mode 100644
index bb66958..0000000
--- a/drivers/watchdog/rm9k_wdt.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- *  Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx
- *  chips.
- *
- *  Copyright (C) 2004 by Basler Vision Technologies AG
- *  Author: Thomas Koeller <thomas.koeller@baslerweb.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/platform_device.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <asm/atomic.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/rm9k-ocd.h>
-
-#include <rm9k_wdt.h>
-
-
-#define CLOCK                  125000000
-#define MAX_TIMEOUT_SECONDS    32
-#define CPCCR                  0x0080
-#define CPGIG1SR               0x0044
-#define CPGIG1ER               0x0054
-
-
-/* Function prototypes */
-static irqreturn_t wdt_gpi_irqhdl(int, void *);
-static void wdt_gpi_start(void);
-static void wdt_gpi_stop(void);
-static void wdt_gpi_set_timeout(unsigned int);
-static int wdt_gpi_open(struct inode *, struct file *);
-static int wdt_gpi_release(struct inode *, struct file *);
-static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t,
-								loff_t *);
-static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long);
-static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *);
-static const struct resource *wdt_gpi_get_resource(struct platform_device *,
-						const char *, unsigned int);
-static int __init wdt_gpi_probe(struct platform_device *);
-static int __exit wdt_gpi_remove(struct platform_device *);
-
-
-static const char wdt_gpi_name[] = "wdt_gpi";
-static atomic_t opencnt;
-static int expect_close;
-static int locked;
-
-
-/* These are set from device resources */
-static void __iomem *wd_regs;
-static unsigned int wd_irq, wd_ctr;
-
-
-/* Module arguments */
-static int timeout = MAX_TIMEOUT_SECONDS;
-module_param(timeout, int, 0444);
-MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
-
-static unsigned long resetaddr = 0xbffdc200;
-module_param(resetaddr, ulong, 0444);
-MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset");
-
-static unsigned long flagaddr = 0xbffdc104;
-module_param(flagaddr, ulong, 0444);
-MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to");
-
-static int powercycle;
-module_param(powercycle, bool, 0444);
-MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, bool, 0444);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started");
-
-
-/* Kernel interfaces */
-static const struct file_operations fops = {
-	.owner		= THIS_MODULE,
-	.open		= wdt_gpi_open,
-	.release	= wdt_gpi_release,
-	.write		= wdt_gpi_write,
-	.unlocked_ioctl	= wdt_gpi_ioctl,
-};
-
-static struct miscdevice miscdev = {
-	.minor		= WATCHDOG_MINOR,
-	.name		= wdt_gpi_name,
-	.fops		= &fops,
-};
-
-static struct notifier_block wdt_gpi_shutdown = {
-	.notifier_call	= wdt_gpi_notify,
-};
-
-
-/* Interrupt handler */
-static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt)
-{
-	if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1))
-		return IRQ_NONE;
-	__raw_writel(0x1, wd_regs + 0x0008);
-
-
-	printk(KERN_CRIT "%s: watchdog expired - resetting system\n",
-		wdt_gpi_name);
-
-	*(volatile char *) flagaddr |= 0x01;
-	*(volatile char *) resetaddr = powercycle ? 0x01 : 0x2;
-	iob();
-	while (1)
-		cpu_relax();
-}
-
-
-/* Watchdog functions */
-static void wdt_gpi_start(void)
-{
-	u32 reg;
-
-	lock_titan_regs();
-	reg = titan_readl(CPGIG1ER);
-	titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER);
-	iob();
-	unlock_titan_regs();
-}
-
-static void wdt_gpi_stop(void)
-{
-	u32 reg;
-
-	lock_titan_regs();
-	reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-	titan_writel(reg, CPCCR);
-	reg = titan_readl(CPGIG1ER);
-	titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER);
-	iob();
-	unlock_titan_regs();
-}
-
-static void wdt_gpi_set_timeout(unsigned int to)
-{
-	u32 reg;
-	const u32 wdval = (to * CLOCK) & ~0x0000000f;
-
-	lock_titan_regs();
-	reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4));
-	titan_writel(reg, CPCCR);
-	wmb();
-	__raw_writel(wdval, wd_regs + 0x0000);
-	wmb();
-	titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR);
-	wmb();
-	titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR);
-	iob();
-	unlock_titan_regs();
-}
-
-
-/* /dev/watchdog operations */
-static int wdt_gpi_open(struct inode *inode, struct file *file)
-{
-	int res;
-
-	if (unlikely(atomic_dec_if_positive(&opencnt) < 0))
-		return -EBUSY;
-
-	expect_close = 0;
-	if (locked) {
-		module_put(THIS_MODULE);
-		free_irq(wd_irq, &miscdev);
-		locked = 0;
-	}
-
-	res = request_irq(wd_irq, wdt_gpi_irqhdl, IRQF_SHARED | IRQF_DISABLED,
-			  wdt_gpi_name, &miscdev);
-	if (unlikely(res))
-		return res;
-
-	wdt_gpi_set_timeout(timeout);
-	wdt_gpi_start();
-
-	printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n",
-		wdt_gpi_name, timeout);
-	return nonseekable_open(inode, file);
-}
-
-static int wdt_gpi_release(struct inode *inode, struct file *file)
-{
-	if (nowayout) {
-		printk(KERN_INFO "%s: no way out - watchdog left running\n",
-			wdt_gpi_name);
-		__module_get(THIS_MODULE);
-		locked = 1;
-	} else {
-		if (expect_close) {
-			wdt_gpi_stop();
-			free_irq(wd_irq, &miscdev);
-			printk(KERN_INFO "%s: watchdog stopped\n",
-							wdt_gpi_name);
-		} else {
-			printk(KERN_CRIT "%s: unexpected close() -"
-				" watchdog left running\n",
-				wdt_gpi_name);
-			wdt_gpi_set_timeout(timeout);
-			__module_get(THIS_MODULE);
-			locked = 1;
-		}
-	}
-
-	atomic_inc(&opencnt);
-	return 0;
-}
-
-static ssize_t wdt_gpi_write(struct file *f, const char __user *d, size_t s,
-								loff_t *o)
-{
-	char val;
-
-	wdt_gpi_set_timeout(timeout);
-	expect_close = (s > 0) && !get_user(val, d) && (val == 'V');
-	return s ? 1 : 0;
-}
-
-static long wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-	long res = -ENOTTY;
-	const long size = _IOC_SIZE(cmd);
-	int stat;
-	void __user *argp = (void __user *)arg;
-	static struct watchdog_info wdinfo = {
-		.identity               = "RM9xxx/GPI watchdog",
-		.firmware_version       = 0,
-		.options                = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
-	};
-
-	if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE))
-		return -ENOTTY;
-
-	if ((_IOC_DIR(cmd) & _IOC_READ)
-	    && !access_ok(VERIFY_WRITE, arg, size))
-		return -EFAULT;
-
-	if ((_IOC_DIR(cmd) & _IOC_WRITE)
-	    && !access_ok(VERIFY_READ, arg, size))
-		return -EFAULT;
-
-	expect_close = 0;
-
-	switch (cmd) {
-	case WDIOC_GETSUPPORT:
-		wdinfo.options = nowayout ?
-			WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING :
-			WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-			WDIOF_MAGICCLOSE;
-		res = __copy_to_user(argp, &wdinfo, size) ?  -EFAULT : size;
-		break;
-
-	case WDIOC_GETSTATUS:
-		break;
-
-	case WDIOC_GETBOOTSTATUS:
-		stat = (*(volatile char *) flagaddr & 0x01)
-			? WDIOF_CARDRESET : 0;
-		res = __copy_to_user(argp, &stat, size) ?
-			-EFAULT : size;
-		break;
-
-	case WDIOC_SETOPTIONS:
-		break;
-
-	case WDIOC_KEEPALIVE:
-		wdt_gpi_set_timeout(timeout);
-		res = size;
-		break;
-
-	case WDIOC_SETTIMEOUT:
-		{
-			int val;
-			if (unlikely(__copy_from_user(&val, argp, size))) {
-				res = -EFAULT;
-				break;
-			}
-
-			if (val > MAX_TIMEOUT_SECONDS)
-				val = MAX_TIMEOUT_SECONDS;
-			timeout = val;
-			wdt_gpi_set_timeout(val);
-			res = size;
-			printk(KERN_INFO "%s: timeout set to %u seconds\n",
-				wdt_gpi_name, timeout);
-		}
-		break;
-
-	case WDIOC_GETTIMEOUT:
-		res = __copy_to_user(argp, &timeout, size) ?
-			-EFAULT : size;
-		break;
-	}
-
-	return res;
-}
-
-
-/* Shutdown notifier */
-static int wdt_gpi_notify(struct notifier_block *this, unsigned long code,
-			  void *unused)
-{
-	if (code == SYS_DOWN || code == SYS_HALT)
-		wdt_gpi_stop();
-
-	return NOTIFY_DONE;
-}
-
-
-/* Init & exit procedures */
-static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv,
-					const char *name, unsigned int type)
-{
-	char buf[80];
-	if (snprintf(buf, sizeof(buf), "%s_0", name) >= sizeof(buf))
-		return NULL;
-	return platform_get_resource_byname(pdv, type, buf);
-}
-
-/* No hotplugging on the platform bus - use __devinit */
-static int __devinit wdt_gpi_probe(struct platform_device *pdv)
-{
-	int res;
-	const struct resource
-		* const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS,
-						  IORESOURCE_MEM),
-		* const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ,
-						  IORESOURCE_IRQ),
-		* const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER,
-						  0);
-
-	if (unlikely(!rr || !ri || !rc))
-		return -ENXIO;
-
-	wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start);
-	if (unlikely(!wd_regs))
-		return -ENOMEM;
-	wd_irq = ri->start;
-	wd_ctr = rc->start;
-	res = misc_register(&miscdev);
-	if (res)
-		iounmap(wd_regs);
-	else
-		register_reboot_notifier(&wdt_gpi_shutdown);
-	return res;
-}
-
-static int __devexit wdt_gpi_remove(struct platform_device *dev)
-{
-	int res;
-
-	unregister_reboot_notifier(&wdt_gpi_shutdown);
-	res = misc_deregister(&miscdev);
-	iounmap(wd_regs);
-	wd_regs = NULL;
-	return res;
-}
-
-
-/* Device driver init & exit */
-static struct platform_driver wgt_gpi_driver = {
-	.driver = {
-		.name		= wdt_gpi_name,
-		.owner		= THIS_MODULE,
-	},
-	.probe		= wdt_gpi_probe,
-	.remove		= __devexit_p(wdt_gpi_remove),
-};
-
-static int __init wdt_gpi_init_module(void)
-{
-	atomic_set(&opencnt, 1);
-	if (timeout > MAX_TIMEOUT_SECONDS)
-		timeout = MAX_TIMEOUT_SECONDS;
-	return platform_driver_register(&wdt_gpi_driver);
-}
-
-static void __exit wdt_gpi_cleanup_module(void)
-{
-	platform_driver_unregister(&wdt_gpi_driver);
-}
-
-module_init(wdt_gpi_init_module);
-module_exit(wdt_gpi_cleanup_module);
-
-MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
-MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-
diff --git a/fs/Kconfig b/fs/Kconfig
index f8fccaa..64d44ef 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -6,10 +6,6 @@
 
 if BLOCK
 
-config FS_JOURNAL_INFO
-	bool
-	default n
-
 source "fs/ext2/Kconfig"
 source "fs/ext3/Kconfig"
 source "fs/ext4/Kconfig"
diff --git a/fs/aio.c b/fs/aio.c
index c30dfc0..1cf12b3 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -711,10 +711,8 @@
 	 */
 	ret = retry(iocb);
 
-	if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
-		BUG_ON(!list_empty(&iocb->ki_wait.task_list));
+	if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED)
 		aio_complete(iocb, ret, 0);
-	}
 out:
 	spin_lock_irq(&ctx->ctx_lock);
 
@@ -866,13 +864,6 @@
 	unsigned long flags;
 	int run = 0;
 
-	/* We're supposed to be the only path putting the iocb back on the run
-	 * list.  If we find that the iocb is *back* on a wait queue already
-	 * than retry has happened before we could queue the iocb.  This also
-	 * means that the retry could have completed and freed our iocb, no
-	 * good. */
-	BUG_ON((!list_empty(&iocb->ki_wait.task_list)));
-
 	spin_lock_irqsave(&ctx->ctx_lock, flags);
 	/* set this inside the lock so that we can't race with aio_run_iocb()
 	 * testing it and putting the iocb on the run list under the lock */
@@ -886,7 +877,7 @@
 /*
  * kick_iocb:
  *      Called typically from a wait queue callback context
- *      (aio_wake_function) to trigger a retry of the iocb.
+ *      to trigger a retry of the iocb.
  *      The retry is usually executed by aio workqueue
  *      threads (See aio_kick_handler).
  */
@@ -1520,31 +1511,6 @@
 	return 0;
 }
 
-/*
- * aio_wake_function:
- * 	wait queue callback function for aio notification,
- * 	Simply triggers a retry of the operation via kick_iocb.
- *
- * 	This callback is specified in the wait queue entry in
- *	a kiocb.
- *
- * Note:
- * This routine is executed with the wait queue lock held.
- * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests
- * the ioctx lock inside the wait queue lock. This is safe
- * because this callback isn't used for wait queues which
- * are nested inside ioctx lock (i.e. ctx->wait)
- */
-static int aio_wake_function(wait_queue_t *wait, unsigned mode,
-			     int sync, void *key)
-{
-	struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
-
-	list_del_init(&wait->task_list);
-	kick_iocb(iocb);
-	return 1;
-}
-
 static void aio_batch_add(struct address_space *mapping,
 			  struct hlist_head *batch_hash)
 {
@@ -1642,8 +1608,6 @@
 	req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
 	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
 	req->ki_opcode = iocb->aio_lio_opcode;
-	init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
-	INIT_LIST_HEAD(&req->ki_wait.task_list);
 
 	ret = aio_setup_iocb(req);
 
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 2ca7a7c..2c99459 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -35,14 +35,13 @@
 			     mnt);
 }
 
-static int anon_inodefs_delete_dentry(struct dentry *dentry)
+/*
+ * anon_inodefs_dname() is called from d_path().
+ */
+static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
 {
-	/*
-	 * We faked vfs to believe the dentry was hashed when we created it.
-	 * Now we restore the flag so that dput() will work correctly.
-	 */
-	dentry->d_flags |= DCACHE_UNHASHED;
-	return 1;
+	return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
+				dentry->d_name.name);
 }
 
 static struct file_system_type anon_inode_fs_type = {
@@ -51,7 +50,7 @@
 	.kill_sb	= kill_anon_super,
 };
 static const struct dentry_operations anon_inodefs_dentry_operations = {
-	.d_delete	= anon_inodefs_delete_dentry,
+	.d_dname	= anon_inodefs_dname,
 };
 
 /*
@@ -88,7 +87,7 @@
 				void *priv, int flags)
 {
 	struct qstr this;
-	struct dentry *dentry;
+	struct path path;
 	struct file *file;
 	int error;
 
@@ -106,10 +105,11 @@
 	this.name = name;
 	this.len = strlen(name);
 	this.hash = 0;
-	dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
-	if (!dentry)
+	path.dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+	if (!path.dentry)
 		goto err_module;
 
+	path.mnt = mntget(anon_inode_mnt);
 	/*
 	 * We know the anon_inode inode count is always greater than zero,
 	 * so we can avoid doing an igrab() and we can use an open-coded
@@ -117,14 +117,11 @@
 	 */
 	atomic_inc(&anon_inode_inode->i_count);
 
-	dentry->d_op = &anon_inodefs_dentry_operations;
-	/* Do not publish this dentry inside the global dentry hash table */
-	dentry->d_flags &= ~DCACHE_UNHASHED;
-	d_instantiate(dentry, anon_inode_inode);
+	path.dentry->d_op = &anon_inodefs_dentry_operations;
+	d_instantiate(path.dentry, anon_inode_inode);
 
 	error = -ENFILE;
-	file = alloc_file(anon_inode_mnt, dentry,
-			  FMODE_READ | FMODE_WRITE, fops);
+	file = alloc_file(&path, FMODE_READ | FMODE_WRITE, fops);
 	if (!file)
 		goto err_dput;
 	file->f_mapping = anon_inode_inode->i_mapping;
@@ -137,7 +134,7 @@
 	return file;
 
 err_dput:
-	dput(dentry);
+	path_put(&path);
 err_module:
 	module_put(fops->owner);
 	return ERR_PTR(error);
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 8f7cdde..0118d67 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -60,6 +60,11 @@
 		current->pid, __func__, ##args);	\
 } while (0)
 
+struct rehash_entry {
+	struct task_struct *task;
+	struct list_head list;
+};
+
 /* Unified info structure.  This is pointed to by both the dentry and
    inode structures.  Each file in the filesystem has an instance of this
    structure.  It holds a reference to the dentry, so dentries are never
@@ -75,6 +80,9 @@
 	struct completion expire_complete;
 
 	struct list_head active;
+	int active_count;
+	struct list_head rehash_list;
+
 	struct list_head expiring;
 
 	struct autofs_sb_info *sbi;
@@ -95,6 +103,8 @@
 
 #define AUTOFS_INF_EXPIRING	(1<<0) /* dentry is in the process of expiring */
 #define AUTOFS_INF_MOUNTPOINT	(1<<1) /* mountpoint status for direct expire */
+#define AUTOFS_INF_PENDING	(1<<2) /* dentry pending mount */
+#define AUTOFS_INF_REHASH	(1<<3) /* dentry in transit to ->lookup() */
 
 struct autofs_wait_queue {
 	wait_queue_head_t queue;
@@ -161,7 +171,7 @@
 {
 	struct autofs_info *inf = autofs4_dentry_ino(dentry);
 
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
+	if (inf->flags & AUTOFS_INF_PENDING)
 		return 1;
 
 	if (inf->flags & AUTOFS_INF_EXPIRING)
@@ -264,5 +274,31 @@
 	return ret;
 }
 
+static inline void autofs4_add_expiring(struct dentry *dentry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino) {
+		spin_lock(&sbi->lookup_lock);
+		if (list_empty(&ino->expiring))
+			list_add(&ino->expiring, &sbi->expiring_list);
+		spin_unlock(&sbi->lookup_lock);
+	}
+	return;
+}
+
+static inline void autofs4_del_expiring(struct dentry *dentry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino) {
+		spin_lock(&sbi->lookup_lock);
+		if (!list_empty(&ino->expiring))
+			list_del_init(&ino->expiring);
+		spin_unlock(&sbi->lookup_lock);
+	}
+	return;
+}
+
 void autofs4_dentry_release(struct dentry *);
 extern void autofs4_kill_sb(struct super_block *);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 3da18d4..74bc9aa 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -27,7 +27,7 @@
 		return 0;
 
 	/* No point expiring a pending mount */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING)
+	if (ino->flags & AUTOFS_INF_PENDING)
 		return 0;
 
 	if (!do_now) {
@@ -279,6 +279,7 @@
 			root->d_mounted--;
 		}
 		ino->flags |= AUTOFS_INF_EXPIRING;
+		autofs4_add_expiring(root);
 		init_completion(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);
 		return root;
@@ -406,6 +407,7 @@
 		expired, (int)expired->d_name.len, expired->d_name.name);
 	ino = autofs4_dentry_ino(expired);
 	ino->flags |= AUTOFS_INF_EXPIRING;
+	autofs4_add_expiring(expired);
 	init_completion(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
 	spin_lock(&dcache_lock);
@@ -433,7 +435,7 @@
 
 		DPRINTK("expire done status=%d", status);
 
-		if (d_unhashed(dentry))
+		if (d_unhashed(dentry) && IS_DEADDIR(dentry->d_inode))
 			return -EAGAIN;
 
 		return status;
@@ -473,6 +475,7 @@
 	spin_lock(&sbi->fs_lock);
 	ino = autofs4_dentry_ino(dentry);
 	ino->flags &= ~AUTOFS_INF_EXPIRING;
+	autofs4_del_expiring(dentry);
 	complete_all(&ino->expire_complete);
 	spin_unlock(&sbi->fs_lock);
 
@@ -503,6 +506,7 @@
 			ino->flags &= ~AUTOFS_INF_MOUNTPOINT;
 		}
 		ino->flags &= ~AUTOFS_INF_EXPIRING;
+		autofs4_del_expiring(dentry);
 		complete_all(&ino->expire_complete);
 		spin_unlock(&sbi->fs_lock);
 		dput(dentry);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 69c8142..d0a3de2 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -49,6 +49,8 @@
 		ino->dentry = NULL;
 		ino->size = 0;
 		INIT_LIST_HEAD(&ino->active);
+		INIT_LIST_HEAD(&ino->rehash_list);
+		ino->active_count = 0;
 		INIT_LIST_HEAD(&ino->expiring);
 		atomic_set(&ino->count, 0);
 	}
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index b96a3c5..30cc9dd 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -72,6 +72,139 @@
 	.rmdir		= autofs4_dir_rmdir,
 };
 
+static void autofs4_add_active(struct dentry *dentry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino) {
+		spin_lock(&sbi->lookup_lock);
+		if (!ino->active_count) {
+			if (list_empty(&ino->active))
+				list_add(&ino->active, &sbi->active_list);
+		}
+		ino->active_count++;
+		spin_unlock(&sbi->lookup_lock);
+	}
+	return;
+}
+
+static void autofs4_del_active(struct dentry *dentry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino) {
+		spin_lock(&sbi->lookup_lock);
+		ino->active_count--;
+		if (!ino->active_count) {
+			if (!list_empty(&ino->active))
+				list_del_init(&ino->active);
+		}
+		spin_unlock(&sbi->lookup_lock);
+	}
+	return;
+}
+
+static void autofs4_add_rehash_entry(struct autofs_info *ino,
+				     struct rehash_entry *entry)
+{
+	entry->task = current;
+	INIT_LIST_HEAD(&entry->list);
+	list_add(&entry->list, &ino->rehash_list);
+	return;
+}
+
+static void autofs4_remove_rehash_entry(struct autofs_info *ino)
+{
+	struct list_head *head = &ino->rehash_list;
+	struct rehash_entry *entry;
+	list_for_each_entry(entry, head, list) {
+		if (entry->task == current) {
+			list_del(&entry->list);
+			kfree(entry);
+			break;
+		}
+	}
+	return;
+}
+
+static void autofs4_remove_rehash_entrys(struct autofs_info *ino)
+{
+	struct autofs_sb_info *sbi = ino->sbi;
+	struct rehash_entry *entry, *next;
+	struct list_head *head;
+
+	spin_lock(&sbi->fs_lock);
+	spin_lock(&sbi->lookup_lock);
+	if (!(ino->flags & AUTOFS_INF_REHASH)) {
+		spin_unlock(&sbi->lookup_lock);
+		spin_unlock(&sbi->fs_lock);
+		return;
+	}
+	ino->flags &= ~AUTOFS_INF_REHASH;
+	head = &ino->rehash_list;
+	list_for_each_entry_safe(entry, next, head, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	spin_unlock(&sbi->lookup_lock);
+	spin_unlock(&sbi->fs_lock);
+	dput(ino->dentry);
+
+	return;
+}
+
+static void autofs4_revalidate_drop(struct dentry *dentry,
+				    struct rehash_entry *entry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	/*
+	 * Add to the active list so we can pick this up in
+	 * ->lookup(). Also add an entry to a rehash list so
+	 * we know when there are no dentrys in flight so we
+	 * know when we can rehash the dentry.
+	 */
+	spin_lock(&sbi->lookup_lock);
+	if (list_empty(&ino->active))
+		list_add(&ino->active, &sbi->active_list);
+	autofs4_add_rehash_entry(ino, entry);
+	spin_unlock(&sbi->lookup_lock);
+	if (!(ino->flags & AUTOFS_INF_REHASH)) {
+		ino->flags |= AUTOFS_INF_REHASH;
+		dget(dentry);
+		spin_lock(&dentry->d_lock);
+		__d_drop(dentry);
+		spin_unlock(&dentry->d_lock);
+	}
+	return;
+}
+
+static void autofs4_revalidate_rehash(struct dentry *dentry)
+{
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	if (ino->flags & AUTOFS_INF_REHASH) {
+		spin_lock(&sbi->lookup_lock);
+		autofs4_remove_rehash_entry(ino);
+		if (list_empty(&ino->rehash_list)) {
+			spin_unlock(&sbi->lookup_lock);
+			ino->flags &= ~AUTOFS_INF_REHASH;
+			d_rehash(dentry);
+			dput(ino->dentry);
+		} else
+			spin_unlock(&sbi->lookup_lock);
+	}
+	return;
+}
+
+static unsigned int autofs4_need_mount(unsigned int flags)
+{
+	unsigned int res = 0;
+	if (flags & (TRIGGER_FLAGS | TRIGGER_INTENTS))
+		res = 1;
+	return res;
+}
+
 static int autofs4_dir_open(struct inode *inode, struct file *file)
 {
 	struct dentry *dentry = file->f_path.dentry;
@@ -93,7 +226,7 @@
 	 * it.
 	 */
 	spin_lock(&dcache_lock);
-	if (!d_mountpoint(dentry) && __simple_empty(dentry)) {
+	if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
 		spin_unlock(&dcache_lock);
 		return -ENOENT;
 	}
@@ -103,7 +236,7 @@
 	return dcache_dir_open(inode, file);
 }
 
-static int try_to_fill_dentry(struct dentry *dentry, int flags)
+static int try_to_fill_dentry(struct dentry *dentry)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 	struct autofs_info *ino = autofs4_dentry_ino(dentry);
@@ -116,55 +249,17 @@
 	 * Wait for a pending mount, triggering one if there
 	 * isn't one already
 	 */
-	if (dentry->d_inode == NULL) {
-		DPRINTK("waiting for mount name=%.*s",
-			 dentry->d_name.len, dentry->d_name.name);
+	DPRINTK("waiting for mount name=%.*s",
+		 dentry->d_name.len, dentry->d_name.name);
 
-		status = autofs4_wait(sbi, dentry, NFY_MOUNT);
+	status = autofs4_wait(sbi, dentry, NFY_MOUNT);
 
-		DPRINTK("mount done status=%d", status);
+	DPRINTK("mount done status=%d", status);
 
-		/* Turn this into a real negative dentry? */
-		if (status == -ENOENT) {
-			spin_lock(&dentry->d_lock);
-			dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-			spin_unlock(&dentry->d_lock);
-			return status;
-		} else if (status) {
-			/* Return a negative dentry, but leave it "pending" */
-			return status;
-		}
-	/* Trigger mount for path component or follow link */
-	} else if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
-			flags & (TRIGGER_FLAGS | TRIGGER_INTENTS) ||
-			current->link_count) {
-		DPRINTK("waiting for mount name=%.*s",
-			dentry->d_name.len, dentry->d_name.name);
+	/* Update expiry counter */
+	ino->last_used = jiffies;
 
-		spin_lock(&dentry->d_lock);
-		dentry->d_flags |= DCACHE_AUTOFS_PENDING;
-		spin_unlock(&dentry->d_lock);
-		status = autofs4_wait(sbi, dentry, NFY_MOUNT);
-
-		DPRINTK("mount done status=%d", status);
-
-		if (status) {
-			spin_lock(&dentry->d_lock);
-			dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-			spin_unlock(&dentry->d_lock);
-			return status;
-		}
-	}
-
-	/* Initialize expiry counter after successful mount */
-	if (ino)
-		ino->last_used = jiffies;
-
-	spin_lock(&dentry->d_lock);
-	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-	spin_unlock(&dentry->d_lock);
-
-	return 0;
+	return status;
 }
 
 /* For autofs direct mounts the follow link triggers the mount */
@@ -202,27 +297,39 @@
 	autofs4_expire_wait(dentry);
 
 	/* We trigger a mount for almost all flags */
-	lookup_type = nd->flags & (TRIGGER_FLAGS | TRIGGER_INTENTS);
-	if (!(lookup_type || dentry->d_flags & DCACHE_AUTOFS_PENDING))
+	lookup_type = autofs4_need_mount(nd->flags);
+	spin_lock(&sbi->fs_lock);
+	spin_lock(&dcache_lock);
+	if (!(lookup_type || ino->flags & AUTOFS_INF_PENDING)) {
+		spin_unlock(&dcache_lock);
+		spin_unlock(&sbi->fs_lock);
 		goto follow;
+	}
 
 	/*
 	 * If the dentry contains directories then it is an autofs
 	 * multi-mount with no root mount offset. So don't try to
 	 * mount it again.
 	 */
-	spin_lock(&dcache_lock);
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING ||
-	    (!d_mountpoint(dentry) && __simple_empty(dentry))) {
+	if (ino->flags & AUTOFS_INF_PENDING ||
+	    (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs))) {
+		ino->flags |= AUTOFS_INF_PENDING;
 		spin_unlock(&dcache_lock);
+		spin_unlock(&sbi->fs_lock);
 
-		status = try_to_fill_dentry(dentry, 0);
+		status = try_to_fill_dentry(dentry);
+
+		spin_lock(&sbi->fs_lock);
+		ino->flags &= ~AUTOFS_INF_PENDING;
+		spin_unlock(&sbi->fs_lock);
+
 		if (status)
 			goto out_error;
 
 		goto follow;
 	}
 	spin_unlock(&dcache_lock);
+	spin_unlock(&sbi->fs_lock);
 follow:
 	/*
 	 * If there is no root mount it must be an autofs
@@ -254,18 +361,47 @@
 {
 	struct inode *dir = dentry->d_parent->d_inode;
 	struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
-	int oz_mode = autofs4_oz_mode(sbi);
+	struct autofs_info *ino = autofs4_dentry_ino(dentry);
+	struct rehash_entry *entry;
 	int flags = nd ? nd->flags : 0;
-	int status = 1;
+	unsigned int mutex_aquired;
 
-	/* Pending dentry */
+	DPRINTK("name = %.*s oz_mode = %d",
+		dentry->d_name.len, dentry->d_name.name, oz_mode);
+
+	/* Daemon never causes a mount to trigger */
+	if (autofs4_oz_mode(sbi))
+		return 1;
+
+	entry = kmalloc(sizeof(struct rehash_entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	mutex_aquired = mutex_trylock(&dir->i_mutex);
+
 	spin_lock(&sbi->fs_lock);
+	spin_lock(&dcache_lock);
+	/* Pending dentry */
 	if (autofs4_ispending(dentry)) {
-		/* The daemon never causes a mount to trigger */
-		spin_unlock(&sbi->fs_lock);
+		int status;
 
-		if (oz_mode)
-			return 1;
+		/*
+		 * We can only unhash and send this to ->lookup() if
+		 * the directory mutex is held over d_revalidate() and
+		 * ->lookup(). This prevents the VFS from incorrectly
+		 * seeing the dentry as non-existent.
+		 */
+		ino->flags |= AUTOFS_INF_PENDING;
+		if (!mutex_aquired) {
+			autofs4_revalidate_drop(dentry, entry);
+			spin_unlock(&dcache_lock);
+			spin_unlock(&sbi->fs_lock);
+			return 0;
+		}
+		spin_unlock(&dcache_lock);
+		spin_unlock(&sbi->fs_lock);
+		mutex_unlock(&dir->i_mutex);
+		kfree(entry);
 
 		/*
 		 * If the directory has gone away due to an expire
@@ -279,46 +415,82 @@
 		 * A zero status is success otherwise we have a
 		 * negative error code.
 		 */
-		status = try_to_fill_dentry(dentry, flags);
+		status = try_to_fill_dentry(dentry);
+
+		spin_lock(&sbi->fs_lock);
+		ino->flags &= ~AUTOFS_INF_PENDING;
+		spin_unlock(&sbi->fs_lock);
+
 		if (status == 0)
 			return 1;
 
 		return status;
 	}
-	spin_unlock(&sbi->fs_lock);
-
-	/* Negative dentry.. invalidate if "old" */
-	if (dentry->d_inode == NULL)
-		return 0;
 
 	/* Check for a non-mountpoint directory with no contents */
-	spin_lock(&dcache_lock);
 	if (S_ISDIR(dentry->d_inode->i_mode) &&
-	    !d_mountpoint(dentry) && 
-	    __simple_empty(dentry)) {
+	    !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) {
 		DPRINTK("dentry=%p %.*s, emptydir",
 			 dentry, dentry->d_name.len, dentry->d_name.name);
-		spin_unlock(&dcache_lock);
 
-		/* The daemon never causes a mount to trigger */
-		if (oz_mode)
-			return 1;
+		if (autofs4_need_mount(flags) || current->link_count) {
+			int status;
 
-		/*
-		 * A zero status is success otherwise we have a
-		 * negative error code.
-		 */
-		status = try_to_fill_dentry(dentry, flags);
-		if (status == 0)
-			return 1;
+			/*
+			 * We can only unhash and send this to ->lookup() if
+			 * the directory mutex is held over d_revalidate() and
+			 * ->lookup(). This prevents the VFS from incorrectly
+			 * seeing the dentry as non-existent.
+			 */
+			ino->flags |= AUTOFS_INF_PENDING;
+			if (!mutex_aquired) {
+				autofs4_revalidate_drop(dentry, entry);
+				spin_unlock(&dcache_lock);
+				spin_unlock(&sbi->fs_lock);
+				return 0;
+			}
+			spin_unlock(&dcache_lock);
+			spin_unlock(&sbi->fs_lock);
+			mutex_unlock(&dir->i_mutex);
+			kfree(entry);
 
-		return status;
+			/*
+			 * A zero status is success otherwise we have a
+			 * negative error code.
+			 */
+			status = try_to_fill_dentry(dentry);
+
+			spin_lock(&sbi->fs_lock);
+			ino->flags &= ~AUTOFS_INF_PENDING;
+			spin_unlock(&sbi->fs_lock);
+
+			if (status == 0)
+				return 1;
+
+			return status;
+		}
 	}
 	spin_unlock(&dcache_lock);
+	spin_unlock(&sbi->fs_lock);
+
+	if (mutex_aquired)
+		mutex_unlock(&dir->i_mutex);
+
+	kfree(entry);
 
 	return 1;
 }
 
+static void autofs4_free_rehash_entrys(struct autofs_info *inf)
+{
+	struct list_head *head = &inf->rehash_list;
+	struct rehash_entry *entry, *next;
+	list_for_each_entry_safe(entry, next, head, list) {
+		list_del(&entry->list);
+		kfree(entry);
+	}
+}
+
 void autofs4_dentry_release(struct dentry *de)
 {
 	struct autofs_info *inf;
@@ -337,6 +509,8 @@
 				list_del(&inf->active);
 			if (!list_empty(&inf->expiring))
 				list_del(&inf->expiring);
+			if (!list_empty(&inf->rehash_list))
+				autofs4_free_rehash_entrys(inf);
 			spin_unlock(&sbi->lookup_lock);
 		}
 
@@ -359,35 +533,52 @@
 	.d_release	= autofs4_dentry_release,
 };
 
-static struct dentry *autofs4_lookup_active(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+static struct dentry *autofs4_lookup_active(struct dentry *dentry)
 {
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct dentry *parent = dentry->d_parent;
+	struct qstr *name = &dentry->d_name;
 	unsigned int len = name->len;
 	unsigned int hash = name->hash;
 	const unsigned char *str = name->name;
 	struct list_head *p, *head;
 
+restart:
 	spin_lock(&dcache_lock);
 	spin_lock(&sbi->lookup_lock);
 	head = &sbi->active_list;
 	list_for_each(p, head) {
 		struct autofs_info *ino;
-		struct dentry *dentry;
+		struct dentry *active;
 		struct qstr *qstr;
 
 		ino = list_entry(p, struct autofs_info, active);
-		dentry = ino->dentry;
+		active = ino->dentry;
 
-		spin_lock(&dentry->d_lock);
+		spin_lock(&active->d_lock);
 
 		/* Already gone? */
-		if (atomic_read(&dentry->d_count) == 0)
+		if (atomic_read(&active->d_count) == 0)
 			goto next;
 
-		qstr = &dentry->d_name;
-
-		if (dentry->d_name.hash != hash)
+		if (active->d_inode && IS_DEADDIR(active->d_inode)) {
+			if (!list_empty(&ino->rehash_list)) {
+				dget(active);
+				spin_unlock(&active->d_lock);
+				spin_unlock(&sbi->lookup_lock);
+				spin_unlock(&dcache_lock);
+				autofs4_remove_rehash_entrys(ino);
+				dput(active);
+				goto restart;
+			}
 			goto next;
-		if (dentry->d_parent != parent)
+		}
+
+		qstr = &active->d_name;
+
+		if (active->d_name.hash != hash)
+			goto next;
+		if (active->d_parent != parent)
 			goto next;
 
 		if (qstr->len != len)
@@ -395,15 +586,13 @@
 		if (memcmp(qstr->name, str, len))
 			goto next;
 
-		if (d_unhashed(dentry)) {
-			dget(dentry);
-			spin_unlock(&dentry->d_lock);
-			spin_unlock(&sbi->lookup_lock);
-			spin_unlock(&dcache_lock);
-			return dentry;
-		}
+		dget(active);
+		spin_unlock(&active->d_lock);
+		spin_unlock(&sbi->lookup_lock);
+		spin_unlock(&dcache_lock);
+		return active;
 next:
-		spin_unlock(&dentry->d_lock);
+		spin_unlock(&active->d_lock);
 	}
 	spin_unlock(&sbi->lookup_lock);
 	spin_unlock(&dcache_lock);
@@ -411,8 +600,11 @@
 	return NULL;
 }
 
-static struct dentry *autofs4_lookup_expiring(struct autofs_sb_info *sbi, struct dentry *parent, struct qstr *name)
+static struct dentry *autofs4_lookup_expiring(struct dentry *dentry)
 {
+	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+	struct dentry *parent = dentry->d_parent;
+	struct qstr *name = &dentry->d_name;
 	unsigned int len = name->len;
 	unsigned int hash = name->hash;
 	const unsigned char *str = name->name;
@@ -423,23 +615,23 @@
 	head = &sbi->expiring_list;
 	list_for_each(p, head) {
 		struct autofs_info *ino;
-		struct dentry *dentry;
+		struct dentry *expiring;
 		struct qstr *qstr;
 
 		ino = list_entry(p, struct autofs_info, expiring);
-		dentry = ino->dentry;
+		expiring = ino->dentry;
 
-		spin_lock(&dentry->d_lock);
+		spin_lock(&expiring->d_lock);
 
 		/* Bad luck, we've already been dentry_iput */
-		if (!dentry->d_inode)
+		if (!expiring->d_inode)
 			goto next;
 
-		qstr = &dentry->d_name;
+		qstr = &expiring->d_name;
 
-		if (dentry->d_name.hash != hash)
+		if (expiring->d_name.hash != hash)
 			goto next;
-		if (dentry->d_parent != parent)
+		if (expiring->d_parent != parent)
 			goto next;
 
 		if (qstr->len != len)
@@ -447,15 +639,13 @@
 		if (memcmp(qstr->name, str, len))
 			goto next;
 
-		if (d_unhashed(dentry)) {
-			dget(dentry);
-			spin_unlock(&dentry->d_lock);
-			spin_unlock(&sbi->lookup_lock);
-			spin_unlock(&dcache_lock);
-			return dentry;
-		}
+		dget(expiring);
+		spin_unlock(&expiring->d_lock);
+		spin_unlock(&sbi->lookup_lock);
+		spin_unlock(&dcache_lock);
+		return expiring;
 next:
-		spin_unlock(&dentry->d_lock);
+		spin_unlock(&expiring->d_lock);
 	}
 	spin_unlock(&sbi->lookup_lock);
 	spin_unlock(&dcache_lock);
@@ -463,13 +653,56 @@
 	return NULL;
 }
 
+static struct autofs_info *init_new_dentry(struct autofs_sb_info *sbi,
+					   struct dentry *dentry, int oz_mode)
+{
+	struct autofs_info *ino;
+
+	/*
+	 * Mark the dentry incomplete but don't hash it. We do this
+	 * to serialize our inode creation operations (symlink and
+	 * mkdir) which prevents deadlock during the callback to
+	 * the daemon. Subsequent user space lookups for the same
+	 * dentry are placed on the wait queue while the daemon
+	 * itself is allowed passage unresticted so the create
+	 * operation itself can then hash the dentry. Finally,
+	 * we check for the hashed dentry and return the newly
+	 * hashed dentry.
+	 */
+	dentry->d_op = &autofs4_root_dentry_operations;
+
+	/*
+	 * And we need to ensure that the same dentry is used for
+	 * all following lookup calls until it is hashed so that
+	 * the dentry flags are persistent throughout the request.
+	 */
+	ino = autofs4_init_ino(NULL, sbi, 0555);
+	if (!ino)
+		return ERR_PTR(-ENOMEM);
+
+	dentry->d_fsdata = ino;
+	ino->dentry = dentry;
+
+	/*
+	 * Only set the mount pending flag for new dentrys not created
+	 * by the daemon.
+	 */
+	if (!oz_mode)
+		ino->flags |= AUTOFS_INF_PENDING;
+
+	d_instantiate(dentry, NULL);
+
+	return ino;
+}
+
 /* Lookups in the root directory */
 static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct autofs_sb_info *sbi;
 	struct autofs_info *ino;
-	struct dentry *expiring, *unhashed;
+	struct dentry *expiring, *active;
 	int oz_mode;
+	int status = 0;
 
 	DPRINTK("name = %.*s",
 		dentry->d_name.len, dentry->d_name.name);
@@ -484,122 +717,99 @@
 	DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
 		 current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode);
 
-	unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name);
-	if (unhashed)
-		dentry = unhashed;
-	else {
-		/*
-		 * Mark the dentry incomplete but don't hash it. We do this
-		 * to serialize our inode creation operations (symlink and
-		 * mkdir) which prevents deadlock during the callback to
-		 * the daemon. Subsequent user space lookups for the same
-		 * dentry are placed on the wait queue while the daemon
-		 * itself is allowed passage unresticted so the create
-		 * operation itself can then hash the dentry. Finally,
-		 * we check for the hashed dentry and return the newly
-		 * hashed dentry.
-		 */
-		dentry->d_op = &autofs4_root_dentry_operations;
-
-		/*
-		 * And we need to ensure that the same dentry is used for
-		 * all following lookup calls until it is hashed so that
-		 * the dentry flags are persistent throughout the request.
-		 */
-		ino = autofs4_init_ino(NULL, sbi, 0555);
-		if (!ino)
-			return ERR_PTR(-ENOMEM);
-
-		dentry->d_fsdata = ino;
-		ino->dentry = dentry;
-
-		spin_lock(&sbi->lookup_lock);
-		list_add(&ino->active, &sbi->active_list);
-		spin_unlock(&sbi->lookup_lock);
-
-		d_instantiate(dentry, NULL);
+	spin_lock(&sbi->fs_lock);
+	active = autofs4_lookup_active(dentry);
+	if (active) {
+		dentry = active;
+		ino = autofs4_dentry_ino(dentry);
+		/* If this came from revalidate, rehash it */
+		autofs4_revalidate_rehash(dentry);
+		spin_unlock(&sbi->fs_lock);
+	} else {
+		spin_unlock(&sbi->fs_lock);
+		ino = init_new_dentry(sbi, dentry, oz_mode);
+		if (IS_ERR(ino))
+			return (struct dentry *) ino;
 	}
 
+	autofs4_add_active(dentry);
+
 	if (!oz_mode) {
+		expiring = autofs4_lookup_expiring(dentry);
 		mutex_unlock(&dir->i_mutex);
-		expiring = autofs4_lookup_expiring(sbi,
-						   dentry->d_parent,
-						   &dentry->d_name);
 		if (expiring) {
 			/*
 			 * If we are racing with expire the request might not
 			 * be quite complete but the directory has been removed
 			 * so it must have been successful, so just wait for it.
 			 */
-			ino = autofs4_dentry_ino(expiring);
 			autofs4_expire_wait(expiring);
-			spin_lock(&sbi->lookup_lock);
-			if (!list_empty(&ino->expiring))
-				list_del_init(&ino->expiring);
-			spin_unlock(&sbi->lookup_lock);
 			dput(expiring);
 		}
-
-		spin_lock(&dentry->d_lock);
-		dentry->d_flags |= DCACHE_AUTOFS_PENDING;
-		spin_unlock(&dentry->d_lock);
-		if (dentry->d_op && dentry->d_op->d_revalidate)
-			(dentry->d_op->d_revalidate)(dentry, nd);
+		status = try_to_fill_dentry(dentry);
 		mutex_lock(&dir->i_mutex);
+		spin_lock(&sbi->fs_lock);
+		ino->flags &= ~AUTOFS_INF_PENDING;
+		spin_unlock(&sbi->fs_lock);
 	}
 
+	autofs4_del_active(dentry);
+
 	/*
-	 * If we are still pending, check if we had to handle
+	 * If we had a mount fail, check if we had to handle
 	 * a signal. If so we can force a restart..
 	 */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
+	if (status) {
 		/* See if we were interrupted */
 		if (signal_pending(current)) {
 			sigset_t *sigset = &current->pending.signal;
 			if (sigismember (sigset, SIGKILL) ||
 			    sigismember (sigset, SIGQUIT) ||
 			    sigismember (sigset, SIGINT)) {
-			    if (unhashed)
-				dput(unhashed);
+			    if (active)
+				dput(active);
 			    return ERR_PTR(-ERESTARTNOINTR);
 			}
 		}
-		if (!oz_mode) {
-			spin_lock(&dentry->d_lock);
-			dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-			spin_unlock(&dentry->d_lock);
-		}
 	}
 
 	/*
-	 * If this dentry is unhashed, then we shouldn't honour this
-	 * lookup.  Returning ENOENT here doesn't do the right thing
-	 * for all system calls, but it should be OK for the operations
-	 * we permit from an autofs.
+	 * User space can (and has done in the past) remove and re-create
+	 * this directory during the callback. This can leave us with an
+	 * unhashed dentry, but a successful mount!  So we need to
+	 * perform another cached lookup in case the dentry now exists.
 	 */
-	if (!oz_mode && d_unhashed(dentry)) {
-		/*
-		 * A user space application can (and has done in the past)
-		 * remove and re-create this directory during the callback.
-		 * This can leave us with an unhashed dentry, but a
-		 * successful mount!  So we need to perform another
-		 * cached lookup in case the dentry now exists.
-		 */
-		struct dentry *parent = dentry->d_parent;
-		struct dentry *new = d_lookup(parent, &dentry->d_name);
-		if (new != NULL)
-			dentry = new;
-		else
-			dentry = ERR_PTR(-ENOENT);
-
-		if (unhashed)
-			dput(unhashed);
-
-		return dentry;
+	if (!oz_mode && !have_submounts(dentry)) {
+		struct dentry *new;
+		new = d_lookup(dentry->d_parent, &dentry->d_name);
+		if (new) {
+			if (active)
+				dput(active);
+			return new;
+		} else {
+			if (!status)
+				status = -ENOENT;
+		}
 	}
 
-	if (unhashed)
-		return unhashed;
+	/*
+	 * If we had a mount failure, return status to user space.
+	 * If the mount succeeded and we used a dentry from the active queue
+	 * return it.
+	 */
+	if (status) {
+		dentry = ERR_PTR(status);
+		if (active)
+			dput(active);
+		return dentry;
+	} else {
+		/*
+		 * Valid successful mount, return active dentry or NULL
+		 * for a new dentry.
+		 */
+		if (active)
+			return active;
+	}
 
 	return NULL;
 }
@@ -624,11 +834,6 @@
 	if (!ino)
 		return -ENOMEM;
 
-	spin_lock(&sbi->lookup_lock);
-	if (!list_empty(&ino->active))
-		list_del_init(&ino->active);
-	spin_unlock(&sbi->lookup_lock);
-
 	ino->size = strlen(symname);
 	cp = kmalloc(ino->size + 1, GFP_KERNEL);
 	if (!cp) {
@@ -705,10 +910,6 @@
 	dir->i_mtime = CURRENT_TIME;
 
 	spin_lock(&dcache_lock);
-	spin_lock(&sbi->lookup_lock);
-	if (list_empty(&ino->expiring))
-		list_add(&ino->expiring, &sbi->expiring_list);
-	spin_unlock(&sbi->lookup_lock);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
@@ -734,10 +935,6 @@
 		spin_unlock(&dcache_lock);
 		return -ENOTEMPTY;
 	}
-	spin_lock(&sbi->lookup_lock);
-	if (list_empty(&ino->expiring))
-		list_add(&ino->expiring, &sbi->expiring_list);
-	spin_unlock(&sbi->lookup_lock);
 	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
 	spin_unlock(&dentry->d_lock);
@@ -775,11 +972,6 @@
 	if (!ino)
 		return -ENOMEM;
 
-	spin_lock(&sbi->lookup_lock);
-	if (!list_empty(&ino->active))
-		list_del_init(&ino->active);
-	spin_unlock(&sbi->lookup_lock);
-
 	inode = autofs4_get_inode(dir->i_sb, ino);
 	if (!inode) {
 		if (!dentry->d_fsdata)
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index b639dcf..346b694 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -32,7 +32,7 @@
 
 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
 static int load_aout_library(struct file*);
-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int aout_core_dump(struct coredump_params *cprm);
 
 static struct linux_binfmt aout_format = {
 	.module		= THIS_MODULE,
@@ -89,8 +89,9 @@
  * dumping of the process results in another error..
  */
 
-static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int aout_core_dump(struct coredump_params *cprm)
 {
+	struct file *file = cprm->file;
 	mm_segment_t fs;
 	int has_dumped = 0;
 	unsigned long dump_start, dump_size;
@@ -108,16 +109,16 @@
 	current->flags |= PF_DUMPCORE;
        	strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm));
 	dump.u_ar0 = offsetof(struct user, regs);
-	dump.signal = signr;
-	aout_dump_thread(regs, &dump);
+	dump.signal = cprm->signr;
+	aout_dump_thread(cprm->regs, &dump);
 
 /* If the size of the dump file exceeds the rlimit, then see what would happen
    if we wrote the stack, but not the data area.  */
-	if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit)
+	if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > cprm->limit)
 		dump.u_dsize = 0;
 
 /* Make sure we have enough room to write the stack and data areas. */
-	if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
+	if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
 		dump.u_ssize = 0;
 
 /* make sure we actually have a data and stack area to dump */
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d15ea17..edd90c4 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -44,8 +44,8 @@
  * If we don't support core dumping, then supply a NULL so we
  * don't even try.
  */
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+#ifdef CONFIG_ELF_CORE
+static int elf_core_dump(struct coredump_params *cprm);
 #else
 #define elf_core_dump	NULL
 #endif
@@ -1101,12 +1101,7 @@
 	return error;
 }
 
-/*
- * Note that some platforms still use traditional core dumps and not
- * the ELF core dump.  Each platform can select it as appropriate.
- */
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-
+#ifdef CONFIG_ELF_CORE
 /*
  * ELF core dumper
  *
@@ -1277,8 +1272,9 @@
 }
 #undef DUMP_WRITE
 
-#define DUMP_WRITE(addr, nr)	\
-	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)				\
+	if ((size += (nr)) > cprm->limit ||		\
+	    !dump_write(cprm->file, (addr), (nr)))	\
 		goto end_coredump;
 
 static void fill_elf_header(struct elfhdr *elf, int segs,
@@ -1906,7 +1902,7 @@
  * and then they are actually written out.  If we run out of core limit
  * we just truncate.
  */
-static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int elf_core_dump(struct coredump_params *cprm)
 {
 	int has_dumped = 0;
 	mm_segment_t fs;
@@ -1952,7 +1948,7 @@
 	 * notes.  This also sets up the file header.
 	 */
 	if (!fill_note_info(elf, segs + 1, /* including notes section */
-			    &info, signr, regs))
+			    &info, cprm->signr, cprm->regs))
 		goto cleanup;
 
 	has_dumped = 1;
@@ -2014,14 +2010,14 @@
 #endif
 
  	/* write out the notes section */
-	if (!write_note_info(&info, file, &foffset))
+	if (!write_note_info(&info, cprm->file, &foffset))
 		goto end_coredump;
 
-	if (elf_coredump_extra_notes_write(file, &foffset))
+	if (elf_coredump_extra_notes_write(cprm->file, &foffset))
 		goto end_coredump;
 
 	/* Align to page */
-	if (!dump_seek(file, dataoff - foffset))
+	if (!dump_seek(cprm->file, dataoff - foffset))
 		goto end_coredump;
 
 	for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -2038,12 +2034,13 @@
 			page = get_dump_page(addr);
 			if (page) {
 				void *kaddr = kmap(page);
-				stop = ((size += PAGE_SIZE) > limit) ||
-					!dump_write(file, kaddr, PAGE_SIZE);
+				stop = ((size += PAGE_SIZE) > cprm->limit) ||
+					!dump_write(cprm->file, kaddr,
+						    PAGE_SIZE);
 				kunmap(page);
 				page_cache_release(page);
 			} else
-				stop = !dump_seek(file, PAGE_SIZE);
+				stop = !dump_seek(cprm->file, PAGE_SIZE);
 			if (stop)
 				goto end_coredump;
 		}
@@ -2063,7 +2060,7 @@
 	return has_dumped;
 }
 
-#endif		/* USE_ELF_CORE_DUMP */
+#endif		/* CONFIG_ELF_CORE */
 
 static int __init init_elf_binfmt(void)
 {
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 79d2b1a..c25256a 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -75,14 +75,14 @@
 static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
 					     struct file *, struct mm_struct *);
 
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_fdpic_core_dump(long, struct pt_regs *, struct file *, unsigned long limit);
+#ifdef CONFIG_ELF_CORE
+static int elf_fdpic_core_dump(struct coredump_params *cprm);
 #endif
 
 static struct linux_binfmt elf_fdpic_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_elf_fdpic_binary,
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+#ifdef CONFIG_ELF_CORE
 	.core_dump	= elf_fdpic_core_dump,
 #endif
 	.min_coredump	= ELF_EXEC_PAGESIZE,
@@ -1201,7 +1201,7 @@
  *
  * Modelled on fs/binfmt_elf.c core dumper
  */
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+#ifdef CONFIG_ELF_CORE
 
 /*
  * These are the only things you should do on a core-file: use only these
@@ -1326,8 +1326,9 @@
 #undef DUMP_WRITE
 #undef DUMP_SEEK
 
-#define DUMP_WRITE(addr, nr)	\
-	if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
+#define DUMP_WRITE(addr, nr)				\
+	if ((size += (nr)) > cprm->limit ||		\
+	    !dump_write(cprm->file, (addr), (nr)))	\
 		goto end_coredump;
 
 static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
@@ -1582,8 +1583,7 @@
  * and then they are actually written out.  If we run out of core limit
  * we just truncate.
  */
-static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
-			       struct file *file, unsigned long limit)
+static int elf_fdpic_core_dump(struct coredump_params *cprm)
 {
 #define	NUM_NOTES	6
 	int has_dumped = 0;
@@ -1642,7 +1642,7 @@
 		goto cleanup;
 #endif
 
-	if (signr) {
+	if (cprm->signr) {
 		struct core_thread *ct;
 		struct elf_thread_status *tmp;
 
@@ -1661,14 +1661,14 @@
 			int sz;
 
 			tmp = list_entry(t, struct elf_thread_status, list);
-			sz = elf_dump_thread_status(signr, tmp);
+			sz = elf_dump_thread_status(cprm->signr, tmp);
 			thread_status_size += sz;
 		}
 	}
 
 	/* now collect the dump for the current */
-	fill_prstatus(prstatus, current, signr);
-	elf_core_copy_regs(&prstatus->pr_reg, regs);
+	fill_prstatus(prstatus, current, cprm->signr);
+	elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
 
 	segs = current->mm->map_count;
 #ifdef ELF_CORE_EXTRA_PHDRS
@@ -1703,7 +1703,7 @@
 
   	/* Try to dump the FPU. */
 	if ((prstatus->pr_fpvalid =
-	     elf_core_copy_task_fpregs(current, regs, fpu)))
+	     elf_core_copy_task_fpregs(current, cprm->regs, fpu)))
 		fill_note(notes + numnote++,
 			  "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 #ifdef ELF_CORE_COPY_XFPREGS
@@ -1774,7 +1774,7 @@
 
  	/* write out the notes section */
 	for (i = 0; i < numnote; i++)
-		if (!writenote(notes + i, file))
+		if (!writenote(notes + i, cprm->file))
 			goto end_coredump;
 
 	/* write out the thread status notes section */
@@ -1783,14 +1783,15 @@
 				list_entry(t, struct elf_thread_status, list);
 
 		for (i = 0; i < tmp->num_notes; i++)
-			if (!writenote(&tmp->notes[i], file))
+			if (!writenote(&tmp->notes[i], cprm->file))
 				goto end_coredump;
 	}
 
-	if (!dump_seek(file, dataoff))
+	if (!dump_seek(cprm->file, dataoff))
 		goto end_coredump;
 
-	if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0)
+	if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
+				    mm_flags) < 0)
 		goto end_coredump;
 
 #ifdef ELF_CORE_WRITE_EXTRA_DATA
@@ -1826,4 +1827,4 @@
 #undef NUM_NOTES
 }
 
-#endif		/* USE_ELF_CORE_DUMP */
+#endif		/* CONFIG_ELF_CORE */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index a279665..d4a00ea 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -87,7 +87,7 @@
 #endif
 
 static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+static int flat_core_dump(struct coredump_params *cprm);
 
 static struct linux_binfmt flat_format = {
 	.module		= THIS_MODULE,
@@ -102,10 +102,10 @@
  * Currently only a stub-function.
  */
 
-static int flat_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit)
+static int flat_core_dump(struct coredump_params *cprm)
 {
 	printk("Process %s:%d received signr %d and should have core dumped\n",
-			current->comm, current->pid, (int) signr);
+			current->comm, current->pid, (int) cprm->signr);
 	return(1);
 }
 
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index eff74b9..2a9b533 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -43,7 +43,7 @@
  * don't even try.
  */
 #if 0
-static int som_core_dump(long signr, struct pt_regs *regs, unsigned long limit);
+static int som_core_dump(struct coredump_params *cprm);
 #else
 #define som_core_dump	NULL
 #endif
diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig
index 402afe0..7bb3c02 100644
--- a/fs/btrfs/Kconfig
+++ b/fs/btrfs/Kconfig
@@ -4,7 +4,6 @@
 	select LIBCRC32C
 	select ZLIB_INFLATE
 	select ZLIB_DEFLATE
-	select FS_JOURNAL_INFO
 	help
 	  Btrfs is a new filesystem with extents, writable snapshotting,
 	  support for multiple devices and many more features.
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 3616042..2e9e699 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -73,13 +73,13 @@
 	return acl;
 }
 
-static int btrfs_xattr_get_acl(struct inode *inode, int type,
-			       void *value, size_t size)
+static int btrfs_xattr_acl_get(struct dentry *dentry, const char *name,
+		void *value, size_t size, int type)
 {
 	struct posix_acl *acl;
 	int ret = 0;
 
-	acl = btrfs_get_acl(inode, type);
+	acl = btrfs_get_acl(dentry->d_inode, type);
 
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
@@ -94,7 +94,8 @@
 /*
  * Needs to be called with fs_mutex held
  */
-static int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+static int btrfs_set_acl(struct btrfs_trans_handle *trans,
+			 struct inode *inode, struct posix_acl *acl, int type)
 {
 	int ret, size = 0;
 	const char *name;
@@ -140,8 +141,7 @@
 			goto out;
 	}
 
-	ret = __btrfs_setxattr(inode, name, value, size, 0);
-
+	ret = __btrfs_setxattr(trans, inode, name, value, size, 0);
 out:
 	kfree(value);
 
@@ -151,10 +151,10 @@
 	return ret;
 }
 
-static int btrfs_xattr_set_acl(struct inode *inode, int type,
-			       const void *value, size_t size)
+static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
-	int ret = 0;
+	int ret;
 	struct posix_acl *acl = NULL;
 
 	if (value) {
@@ -167,38 +167,13 @@
 		}
 	}
 
-	ret = btrfs_set_acl(inode, acl, type);
+	ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type);
 
 	posix_acl_release(acl);
 
 	return ret;
 }
 
-
-static int btrfs_xattr_acl_access_get(struct inode *inode, const char *name,
-				      void *value, size_t size)
-{
-	return btrfs_xattr_get_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int btrfs_xattr_acl_access_set(struct inode *inode, const char *name,
-				      const void *value, size_t size, int flags)
-{
-	return btrfs_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int btrfs_xattr_acl_default_get(struct inode *inode, const char *name,
-				       void *value, size_t size)
-{
-	return btrfs_xattr_get_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
-static int btrfs_xattr_acl_default_set(struct inode *inode, const char *name,
-			       const void *value, size_t size, int flags)
-{
-	return btrfs_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 int btrfs_check_acl(struct inode *inode, int mask)
 {
 	struct posix_acl *acl;
@@ -221,7 +196,8 @@
  * stuff has been fixed to work with that.  If the locking stuff changes, we
  * need to re-evaluate the acl locking stuff.
  */
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir)
 {
 	struct posix_acl *acl = NULL;
 	int ret = 0;
@@ -246,7 +222,8 @@
 		mode_t mode;
 
 		if (S_ISDIR(inode->i_mode)) {
-			ret = btrfs_set_acl(inode, acl, ACL_TYPE_DEFAULT);
+			ret = btrfs_set_acl(trans, inode, acl,
+					    ACL_TYPE_DEFAULT);
 			if (ret)
 				goto failed;
 		}
@@ -261,7 +238,7 @@
 			inode->i_mode = mode;
 			if (ret > 0) {
 				/* we need an acl */
-				ret = btrfs_set_acl(inode, clone,
+				ret = btrfs_set_acl(trans, inode, clone,
 						    ACL_TYPE_ACCESS);
 			}
 		}
@@ -294,7 +271,7 @@
 
 	ret = posix_acl_chmod_masq(clone, inode->i_mode);
 	if (!ret)
-		ret = btrfs_set_acl(inode, clone, ACL_TYPE_ACCESS);
+		ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
 
 	posix_acl_release(clone);
 
@@ -303,14 +280,16 @@
 
 struct xattr_handler btrfs_xattr_acl_default_handler = {
 	.prefix = POSIX_ACL_XATTR_DEFAULT,
-	.get	= btrfs_xattr_acl_default_get,
-	.set	= btrfs_xattr_acl_default_set,
+	.flags	= ACL_TYPE_DEFAULT,
+	.get	= btrfs_xattr_acl_get,
+	.set	= btrfs_xattr_acl_set,
 };
 
 struct xattr_handler btrfs_xattr_acl_access_handler = {
 	.prefix = POSIX_ACL_XATTR_ACCESS,
-	.get	= btrfs_xattr_acl_access_get,
-	.set	= btrfs_xattr_acl_access_set,
+	.flags	= ACL_TYPE_ACCESS,
+	.get	= btrfs_xattr_acl_get,
+	.set	= btrfs_xattr_acl_set,
 };
 
 #else /* CONFIG_BTRFS_FS_POSIX_ACL */
@@ -320,7 +299,8 @@
 	return 0;
 }
 
-int btrfs_init_acl(struct inode *inode, struct inode *dir)
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir)
 {
 	return 0;
 }
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index f6783a4..3f1f50d 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -44,9 +44,6 @@
 	 */
 	struct extent_io_tree io_failure_tree;
 
-	/* held while inesrting or deleting extents from files */
-	struct mutex extent_mutex;
-
 	/* held while logging the inode in tree-log.c */
 	struct mutex log_mutex;
 
@@ -166,7 +163,7 @@
 
 static inline void btrfs_i_size_write(struct inode *inode, u64 size)
 {
-	inode->i_size = size;
+	i_size_write(inode, size);
 	BTRFS_I(inode)->disk_i_size = size;
 }
 
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ec96f3a..c4bc570 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -37,6 +37,11 @@
 			      struct extent_buffer *src_buf);
 static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		   struct btrfs_path *path, int level, int slot);
+static int setup_items_for_insert(struct btrfs_trans_handle *trans,
+			struct btrfs_root *root, struct btrfs_path *path,
+			struct btrfs_key *cpu_key, u32 *data_size,
+			u32 total_data, u32 total_size, int nr);
+
 
 struct btrfs_path *btrfs_alloc_path(void)
 {
@@ -451,9 +456,8 @@
 		extent_buffer_get(cow);
 		spin_unlock(&root->node_lock);
 
-		btrfs_free_extent(trans, root, buf->start, buf->len,
-				  parent_start, root->root_key.objectid,
-				  level, 0);
+		btrfs_free_tree_block(trans, root, buf->start, buf->len,
+				parent_start, root->root_key.objectid, level);
 		free_extent_buffer(buf);
 		add_root_to_dirty_list(root);
 	} else {
@@ -468,9 +472,8 @@
 		btrfs_set_node_ptr_generation(parent, parent_slot,
 					      trans->transid);
 		btrfs_mark_buffer_dirty(parent);
-		btrfs_free_extent(trans, root, buf->start, buf->len,
-				  parent_start, root->root_key.objectid,
-				  level, 0);
+		btrfs_free_tree_block(trans, root, buf->start, buf->len,
+				parent_start, root->root_key.objectid, level);
 	}
 	if (unlock_orig)
 		btrfs_tree_unlock(buf);
@@ -1030,8 +1033,8 @@
 		btrfs_tree_unlock(mid);
 		/* once for the path */
 		free_extent_buffer(mid);
-		ret = btrfs_free_extent(trans, root, mid->start, mid->len,
-					0, root->root_key.objectid, level, 1);
+		ret = btrfs_free_tree_block(trans, root, mid->start, mid->len,
+					    0, root->root_key.objectid, level);
 		/* once for the root ptr */
 		free_extent_buffer(mid);
 		return ret;
@@ -1095,10 +1098,10 @@
 				       1);
 			if (wret)
 				ret = wret;
-			wret = btrfs_free_extent(trans, root, bytenr,
-						 blocksize, 0,
-						 root->root_key.objectid,
-						 level, 0);
+			wret = btrfs_free_tree_block(trans, root,
+						     bytenr, blocksize, 0,
+						     root->root_key.objectid,
+						     level);
 			if (wret)
 				ret = wret;
 		} else {
@@ -1143,9 +1146,8 @@
 		wret = del_ptr(trans, root, path, level + 1, pslot);
 		if (wret)
 			ret = wret;
-		wret = btrfs_free_extent(trans, root, bytenr, blocksize,
-					 0, root->root_key.objectid,
-					 level, 0);
+		wret = btrfs_free_tree_block(trans, root, bytenr, blocksize,
+					 0, root->root_key.objectid, level);
 		if (wret)
 			ret = wret;
 	} else {
@@ -2997,75 +2999,85 @@
 	return ret;
 }
 
-/*
- * This function splits a single item into two items,
- * giving 'new_key' to the new item and splitting the
- * old one at split_offset (from the start of the item).
- *
- * The path may be released by this operation.  After
- * the split, the path is pointing to the old item.  The
- * new item is going to be in the same node as the old one.
- *
- * Note, the item being split must be smaller enough to live alone on
- * a tree block with room for one extra struct btrfs_item
- *
- * This allows us to split the item in place, keeping a lock on the
- * leaf the entire time.
- */
-int btrfs_split_item(struct btrfs_trans_handle *trans,
-		     struct btrfs_root *root,
-		     struct btrfs_path *path,
-		     struct btrfs_key *new_key,
-		     unsigned long split_offset)
+static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans,
+					 struct btrfs_root *root,
+					 struct btrfs_path *path, int ins_len)
 {
-	u32 item_size;
+	struct btrfs_key key;
 	struct extent_buffer *leaf;
-	struct btrfs_key orig_key;
-	struct btrfs_item *item;
-	struct btrfs_item *new_item;
-	int ret = 0;
-	int slot;
-	u32 nritems;
-	u32 orig_offset;
-	struct btrfs_disk_key disk_key;
-	char *buf;
+	struct btrfs_file_extent_item *fi;
+	u64 extent_len = 0;
+	u32 item_size;
+	int ret;
 
 	leaf = path->nodes[0];
-	btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
-	if (btrfs_leaf_free_space(root, leaf) >= sizeof(struct btrfs_item))
-		goto split;
+	btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+
+	BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY &&
+	       key.type != BTRFS_EXTENT_CSUM_KEY);
+
+	if (btrfs_leaf_free_space(root, leaf) >= ins_len)
+		return 0;
 
 	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+	if (key.type == BTRFS_EXTENT_DATA_KEY) {
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		extent_len = btrfs_file_extent_num_bytes(leaf, fi);
+	}
 	btrfs_release_path(root, path);
 
-	path->search_for_split = 1;
 	path->keep_locks = 1;
-
-	ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1);
+	path->search_for_split = 1;
+	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 	path->search_for_split = 0;
+	if (ret < 0)
+		goto err;
 
+	ret = -EAGAIN;
+	leaf = path->nodes[0];
 	/* if our item isn't there or got smaller, return now */
-	if (ret != 0 || item_size != btrfs_item_size_nr(path->nodes[0],
-							path->slots[0])) {
-		path->keep_locks = 0;
-		return -EAGAIN;
+	if (ret > 0 || item_size != btrfs_item_size_nr(leaf, path->slots[0]))
+		goto err;
+
+	if (key.type == BTRFS_EXTENT_DATA_KEY) {
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		if (extent_len != btrfs_file_extent_num_bytes(leaf, fi))
+			goto err;
 	}
 
 	btrfs_set_path_blocking(path);
-	ret = split_leaf(trans, root, &orig_key, path,
-			 sizeof(struct btrfs_item), 1);
-	path->keep_locks = 0;
+	ret = split_leaf(trans, root, &key, path, ins_len, 1);
 	BUG_ON(ret);
 
+	path->keep_locks = 0;
 	btrfs_unlock_up_safe(path, 1);
+	return 0;
+err:
+	path->keep_locks = 0;
+	return ret;
+}
+
+static noinline int split_item(struct btrfs_trans_handle *trans,
+			       struct btrfs_root *root,
+			       struct btrfs_path *path,
+			       struct btrfs_key *new_key,
+			       unsigned long split_offset)
+{
+	struct extent_buffer *leaf;
+	struct btrfs_item *item;
+	struct btrfs_item *new_item;
+	int slot;
+	char *buf;
+	u32 nritems;
+	u32 item_size;
+	u32 orig_offset;
+	struct btrfs_disk_key disk_key;
+
 	leaf = path->nodes[0];
 	BUG_ON(btrfs_leaf_free_space(root, leaf) < sizeof(struct btrfs_item));
 
-split:
-	/*
-	 * make sure any changes to the path from split_leaf leave it
-	 * in a blocking state
-	 */
 	btrfs_set_path_blocking(path);
 
 	item = btrfs_item_nr(leaf, path->slots[0]);
@@ -3073,19 +3085,19 @@
 	item_size = btrfs_item_size(leaf, item);
 
 	buf = kmalloc(item_size, GFP_NOFS);
+	if (!buf)
+		return -ENOMEM;
+
 	read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
 			    path->slots[0]), item_size);
+
 	slot = path->slots[0] + 1;
-	leaf = path->nodes[0];
-
 	nritems = btrfs_header_nritems(leaf);
-
 	if (slot != nritems) {
 		/* shift the items */
 		memmove_extent_buffer(leaf, btrfs_item_nr_offset(slot + 1),
-			      btrfs_item_nr_offset(slot),
-			      (nritems - slot) * sizeof(struct btrfs_item));
-
+				btrfs_item_nr_offset(slot),
+				(nritems - slot) * sizeof(struct btrfs_item));
 	}
 
 	btrfs_cpu_key_to_disk(&disk_key, new_key);
@@ -3113,16 +3125,81 @@
 			    item_size - split_offset);
 	btrfs_mark_buffer_dirty(leaf);
 
-	ret = 0;
-	if (btrfs_leaf_free_space(root, leaf) < 0) {
-		btrfs_print_leaf(root, leaf);
-		BUG();
-	}
+	BUG_ON(btrfs_leaf_free_space(root, leaf) < 0);
 	kfree(buf);
+	return 0;
+}
+
+/*
+ * This function splits a single item into two items,
+ * giving 'new_key' to the new item and splitting the
+ * old one at split_offset (from the start of the item).
+ *
+ * The path may be released by this operation.  After
+ * the split, the path is pointing to the old item.  The
+ * new item is going to be in the same node as the old one.
+ *
+ * Note, the item being split must be smaller enough to live alone on
+ * a tree block with room for one extra struct btrfs_item
+ *
+ * This allows us to split the item in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_split_item(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     struct btrfs_path *path,
+		     struct btrfs_key *new_key,
+		     unsigned long split_offset)
+{
+	int ret;
+	ret = setup_leaf_for_split(trans, root, path,
+				   sizeof(struct btrfs_item));
+	if (ret)
+		return ret;
+
+	ret = split_item(trans, root, path, new_key, split_offset);
 	return ret;
 }
 
 /*
+ * This function duplicate a item, giving 'new_key' to the new item.
+ * It guarantees both items live in the same tree leaf and the new item
+ * is contiguous with the original item.
+ *
+ * This allows us to split file extent in place, keeping a lock on the
+ * leaf the entire time.
+ */
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 struct btrfs_key *new_key)
+{
+	struct extent_buffer *leaf;
+	int ret;
+	u32 item_size;
+
+	leaf = path->nodes[0];
+	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
+	ret = setup_leaf_for_split(trans, root, path,
+				   item_size + sizeof(struct btrfs_item));
+	if (ret)
+		return ret;
+
+	path->slots[0]++;
+	ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
+				     item_size, item_size +
+				     sizeof(struct btrfs_item), 1);
+	BUG_ON(ret);
+
+	leaf = path->nodes[0];
+	memcpy_extent_buffer(leaf,
+			     btrfs_item_ptr_offset(leaf, path->slots[0]),
+			     btrfs_item_ptr_offset(leaf, path->slots[0] - 1),
+			     item_size);
+	return 0;
+}
+
+/*
  * make the item pointed to by the path smaller.  new_size indicates
  * how small to make it, and from_end tells us if we just chop bytes
  * off the end of the item or if we shift the item to chop bytes off
@@ -3714,8 +3791,8 @@
 	 */
 	btrfs_unlock_up_safe(path, 0);
 
-	ret = btrfs_free_extent(trans, root, leaf->start, leaf->len,
-				0, root->root_key.objectid, 0, 0);
+	ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len,
+				    0, root->root_key.objectid, 0);
 	return ret;
 }
 /*
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 444b3e9..9f806dd 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -310,6 +310,9 @@
 #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
 					sizeof(struct btrfs_item) - \
 					sizeof(struct btrfs_file_extent_item))
+#define BTRFS_MAX_XATTR_SIZE(r)	(BTRFS_LEAF_DATA_SIZE(r) - \
+				 sizeof(struct btrfs_item) -\
+				 sizeof(struct btrfs_dir_item))
 
 
 /*
@@ -859,8 +862,9 @@
 	struct mutex ordered_operations_mutex;
 	struct rw_semaphore extent_commit_sem;
 
-	struct rw_semaphore subvol_sem;
+	struct rw_semaphore cleanup_work_sem;
 
+	struct rw_semaphore subvol_sem;
 	struct srcu_struct subvol_srcu;
 
 	struct list_head trans_list;
@@ -868,6 +872,9 @@
 	struct list_head dead_roots;
 	struct list_head caching_block_groups;
 
+	spinlock_t delayed_iput_lock;
+	struct list_head delayed_iputs;
+
 	atomic_t nr_async_submits;
 	atomic_t async_submit_draining;
 	atomic_t nr_async_bios;
@@ -1034,12 +1041,12 @@
 	int ref_cows;
 	int track_dirty;
 	int in_radix;
+	int clean_orphans;
 
 	u64 defrag_trans_start;
 	struct btrfs_key defrag_progress;
 	struct btrfs_key defrag_max;
 	int defrag_running;
-	int defrag_level;
 	char *name;
 	int in_sysfs;
 
@@ -1975,6 +1982,10 @@
 					u64 parent, u64 root_objectid,
 					struct btrfs_disk_key *key, int level,
 					u64 hint, u64 empty_size);
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u32 blocksize,
+			  u64 parent, u64 root_objectid, int level);
 struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 					    struct btrfs_root *root,
 					    u64 bytenr, u32 blocksize,
@@ -2089,6 +2100,10 @@
 		     struct btrfs_path *path,
 		     struct btrfs_key *new_key,
 		     unsigned long split_offset);
+int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 struct btrfs_key *new_key);
 int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, struct btrfs_path *p, int
 		      ins_len, int cow);
@@ -2196,9 +2211,10 @@
 			      struct btrfs_path *path,
 			      struct btrfs_dir_item *di);
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-			    struct btrfs_root *root, const char *name,
-			    u16 name_len, const void *data, u16 data_len,
-			    u64 dir);
+			    struct btrfs_root *root,
+			    struct btrfs_path *path, u64 objectid,
+			    const char *name, u16 name_len,
+			    const void *data, u16 data_len);
 struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
 					  struct btrfs_root *root,
 					  struct btrfs_path *path, u64 dir,
@@ -2292,7 +2308,7 @@
 			       struct inode *inode, u64 new_size,
 			       u32 min_type);
 
-int btrfs_start_delalloc_inodes(struct btrfs_root *root);
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
 int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end);
 int btrfs_writepages(struct address_space *mapping,
 		     struct writeback_control *wbc);
@@ -2332,6 +2348,8 @@
 void btrfs_orphan_cleanup(struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t size);
 int btrfs_invalidate_inodes(struct btrfs_root *root);
+void btrfs_add_delayed_iput(struct inode *inode);
+void btrfs_run_delayed_iputs(struct btrfs_root *root);
 extern const struct dentry_operations btrfs_dentry_operations;
 
 /* ioctl.c */
@@ -2345,12 +2363,9 @@
 			    int skip_pinned);
 int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 extern const struct file_operations btrfs_file_operations;
-int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 locked_end,
-		       u64 inline_limit, u64 *hint_block, int drop_cache);
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+		       u64 start, u64 end, u64 *hint_byte, int drop_cache);
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-			      struct btrfs_root *root,
 			      struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
 
@@ -2380,7 +2395,8 @@
 #else
 #define btrfs_check_acl NULL
 #endif
-int btrfs_init_acl(struct inode *inode, struct inode *dir);
+int btrfs_init_acl(struct btrfs_trans_handle *trans,
+		   struct inode *inode, struct inode *dir);
 int btrfs_acl_chmod(struct inode *inode);
 
 /* relocation.c */
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index f3a6075..e9103b3 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -68,12 +68,12 @@
  * into the tree
  */
 int btrfs_insert_xattr_item(struct btrfs_trans_handle *trans,
-			    struct btrfs_root *root, const char *name,
-			    u16 name_len, const void *data, u16 data_len,
-			    u64 dir)
+			    struct btrfs_root *root,
+			    struct btrfs_path *path, u64 objectid,
+			    const char *name, u16 name_len,
+			    const void *data, u16 data_len)
 {
 	int ret = 0;
-	struct btrfs_path *path;
 	struct btrfs_dir_item *dir_item;
 	unsigned long name_ptr, data_ptr;
 	struct btrfs_key key, location;
@@ -81,15 +81,11 @@
 	struct extent_buffer *leaf;
 	u32 data_size;
 
-	key.objectid = dir;
+	BUG_ON(name_len + data_len > BTRFS_MAX_XATTR_SIZE(root));
+
+	key.objectid = objectid;
 	btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
 	key.offset = btrfs_name_hash(name, name_len);
-	path = btrfs_alloc_path();
-	if (!path)
-		return -ENOMEM;
-	if (name_len + data_len + sizeof(struct btrfs_dir_item) >
-	    BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item))
-		return -ENOSPC;
 
 	data_size = sizeof(*dir_item) + name_len + data_len;
 	dir_item = insert_with_overflow(trans, root, path, &key, data_size,
@@ -117,7 +113,6 @@
 	write_extent_buffer(leaf, data, data_ptr, data_len);
 	btrfs_mark_buffer_dirty(path->nodes[0]);
 
-	btrfs_free_path(path);
 	return ret;
 }
 
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 02b6afb..009e3bd 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -892,6 +892,8 @@
 	root->stripesize = stripesize;
 	root->ref_cows = 0;
 	root->track_dirty = 0;
+	root->in_radix = 0;
+	root->clean_orphans = 0;
 
 	root->fs_info = fs_info;
 	root->objectid = objectid;
@@ -928,7 +930,6 @@
 	root->defrag_trans_start = fs_info->generation;
 	init_completion(&root->kobj_unregister);
 	root->defrag_running = 0;
-	root->defrag_level = 0;
 	root->root_key.objectid = objectid;
 	root->anon_super.s_root = NULL;
 	root->anon_super.s_dev = 0;
@@ -980,12 +981,12 @@
 
 	while (1) {
 		ret = find_first_extent_bit(&log_root_tree->dirty_log_pages,
-				    0, &start, &end, EXTENT_DIRTY);
+				0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
 		if (ret)
 			break;
 
-		clear_extent_dirty(&log_root_tree->dirty_log_pages,
-				   start, end, GFP_NOFS);
+		clear_extent_bits(&log_root_tree->dirty_log_pages, start, end,
+				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
 	}
 	eb = fs_info->log_root_tree->node;
 
@@ -1210,8 +1211,10 @@
 	ret = radix_tree_insert(&fs_info->fs_roots_radix,
 				(unsigned long)root->root_key.objectid,
 				root);
-	if (ret == 0)
+	if (ret == 0) {
 		root->in_radix = 1;
+		root->clean_orphans = 1;
+	}
 	spin_unlock(&fs_info->fs_roots_radix_lock);
 	radix_tree_preload_end();
 	if (ret) {
@@ -1225,10 +1228,6 @@
 	ret = btrfs_find_dead_roots(fs_info->tree_root,
 				    root->root_key.objectid);
 	WARN_ON(ret);
-
-	if (!(fs_info->sb->s_flags & MS_RDONLY))
-		btrfs_orphan_cleanup(root);
-
 	return root;
 fail:
 	free_fs_root(root);
@@ -1477,6 +1476,7 @@
 
 		if (!(root->fs_info->sb->s_flags & MS_RDONLY) &&
 		    mutex_trylock(&root->fs_info->cleaner_mutex)) {
+			btrfs_run_delayed_iputs(root);
 			btrfs_clean_old_snapshots(root);
 			mutex_unlock(&root->fs_info->cleaner_mutex);
 		}
@@ -1606,6 +1606,7 @@
 	INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC);
 	INIT_LIST_HEAD(&fs_info->trans_list);
 	INIT_LIST_HEAD(&fs_info->dead_roots);
+	INIT_LIST_HEAD(&fs_info->delayed_iputs);
 	INIT_LIST_HEAD(&fs_info->hashers);
 	INIT_LIST_HEAD(&fs_info->delalloc_inodes);
 	INIT_LIST_HEAD(&fs_info->ordered_operations);
@@ -1614,6 +1615,7 @@
 	spin_lock_init(&fs_info->new_trans_lock);
 	spin_lock_init(&fs_info->ref_cache_lock);
 	spin_lock_init(&fs_info->fs_roots_radix_lock);
+	spin_lock_init(&fs_info->delayed_iput_lock);
 
 	init_completion(&fs_info->kobj_unregister);
 	fs_info->tree_root = tree_root;
@@ -1689,6 +1691,7 @@
 	mutex_init(&fs_info->cleaner_mutex);
 	mutex_init(&fs_info->volume_mutex);
 	init_rwsem(&fs_info->extent_commit_sem);
+	init_rwsem(&fs_info->cleanup_work_sem);
 	init_rwsem(&fs_info->subvol_sem);
 
 	btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
@@ -2386,8 +2389,14 @@
 	int ret;
 
 	mutex_lock(&root->fs_info->cleaner_mutex);
+	btrfs_run_delayed_iputs(root);
 	btrfs_clean_old_snapshots(root);
 	mutex_unlock(&root->fs_info->cleaner_mutex);
+
+	/* wait until ongoing cleanup work done */
+	down_write(&root->fs_info->cleanup_work_sem);
+	up_write(&root->fs_info->cleanup_work_sem);
+
 	trans = btrfs_start_transaction(root, 1);
 	ret = btrfs_commit_transaction(trans, root);
 	BUG_ON(ret);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 94627c4..56e5013 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -195,6 +195,14 @@
 	int stripe_len;
 	int i, nr, ret;
 
+	if (cache->key.objectid < BTRFS_SUPER_INFO_OFFSET) {
+		stripe_len = BTRFS_SUPER_INFO_OFFSET - cache->key.objectid;
+		cache->bytes_super += stripe_len;
+		ret = add_excluded_extent(root, cache->key.objectid,
+					  stripe_len);
+		BUG_ON(ret);
+	}
+
 	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
 		bytenr = btrfs_sb_offset(i);
 		ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
@@ -255,7 +263,7 @@
 		if (ret)
 			break;
 
-		if (extent_start == start) {
+		if (extent_start <= start) {
 			start = extent_end + 1;
 		} else if (extent_start > start && extent_start < end) {
 			size = extent_start - start;
@@ -2880,9 +2888,9 @@
 	root = async->root;
 	info = async->info;
 
-	btrfs_start_delalloc_inodes(root);
+	btrfs_start_delalloc_inodes(root, 0);
 	wake_up(&info->flush_wait);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	spin_lock(&info->lock);
 	info->flushing = 0;
@@ -2956,8 +2964,8 @@
 	return;
 
 flush:
-	btrfs_start_delalloc_inodes(root);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_start_delalloc_inodes(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	spin_lock(&info->lock);
 	info->flushing = 0;
@@ -3454,14 +3462,6 @@
 	else
 		old_val -= num_bytes;
 	btrfs_set_super_bytes_used(&info->super_copy, old_val);
-
-	/* block accounting for root item */
-	old_val = btrfs_root_used(&root->root_item);
-	if (alloc)
-		old_val += num_bytes;
-	else
-		old_val -= num_bytes;
-	btrfs_set_root_used(&root->root_item, old_val);
 	spin_unlock(&info->delalloc_lock);
 
 	while (total) {
@@ -4049,6 +4049,21 @@
 	return ret;
 }
 
+int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u32 blocksize,
+			  u64 parent, u64 root_objectid, int level)
+{
+	u64 used;
+	spin_lock(&root->node_lock);
+	used = btrfs_root_used(&root->root_item) - blocksize;
+	btrfs_set_root_used(&root->root_item, used);
+	spin_unlock(&root->node_lock);
+
+	return btrfs_free_extent(trans, root, bytenr, blocksize,
+				 parent, root_objectid, level, 0);
+}
+
 static u64 stripe_align(struct btrfs_root *root, u64 val)
 {
 	u64 mask = ((u64)root->stripesize - 1);
@@ -4578,7 +4593,6 @@
 {
 	int ret;
 	u64 search_start = 0;
-	struct btrfs_fs_info *info = root->fs_info;
 
 	data = btrfs_get_alloc_profile(root, data);
 again:
@@ -4586,17 +4600,9 @@
 	 * the only place that sets empty_size is btrfs_realloc_node, which
 	 * is not called recursively on allocations
 	 */
-	if (empty_size || root->ref_cows) {
-		if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
-			ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-				     2 * 1024 * 1024,
-				     BTRFS_BLOCK_GROUP_METADATA |
-				     (info->metadata_alloc_profile &
-				      info->avail_metadata_alloc_bits), 0);
-		}
+	if (empty_size || root->ref_cows)
 		ret = do_chunk_alloc(trans, root->fs_info->extent_root,
 				     num_bytes + 2 * 1024 * 1024, data, 0);
-	}
 
 	WARN_ON(num_bytes < root->sectorsize);
 	ret = find_free_extent(trans, root, num_bytes, empty_size,
@@ -4897,6 +4903,14 @@
 					extent_op);
 		BUG_ON(ret);
 	}
+
+	if (root_objectid == root->root_key.objectid) {
+		u64 used;
+		spin_lock(&root->node_lock);
+		used = btrfs_root_used(&root->root_item) + num_bytes;
+		btrfs_set_root_used(&root->root_item, used);
+		spin_unlock(&root->node_lock);
+	}
 	return ret;
 }
 
@@ -4919,8 +4933,16 @@
 	btrfs_set_buffer_uptodate(buf);
 
 	if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
-		set_extent_dirty(&root->dirty_log_pages, buf->start,
-			 buf->start + buf->len - 1, GFP_NOFS);
+		/*
+		 * we allow two log transactions at a time, use different
+		 * EXENT bit to differentiate dirty pages.
+		 */
+		if (root->log_transid % 2 == 0)
+			set_extent_dirty(&root->dirty_log_pages, buf->start,
+					buf->start + buf->len - 1, GFP_NOFS);
+		else
+			set_extent_new(&root->dirty_log_pages, buf->start,
+					buf->start + buf->len - 1, GFP_NOFS);
 	} else {
 		set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
 			 buf->start + buf->len - 1, GFP_NOFS);
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 77f7593..feaa13b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -179,18 +179,14 @@
 		}
 		flags = em->flags;
 		if (skip_pinned && test_bit(EXTENT_FLAG_PINNED, &em->flags)) {
-			if (em->start <= start &&
-			    (!testend || em->start + em->len >= start + len)) {
+			if (testend && em->start + em->len >= start + len) {
 				free_extent_map(em);
 				write_unlock(&em_tree->lock);
 				break;
 			}
-			if (start < em->start) {
-				len = em->start - start;
-			} else {
+			start = em->start + em->len;
+			if (testend)
 				len = start + len - (em->start + em->len);
-				start = em->start + em->len;
-			}
 			free_extent_map(em);
 			write_unlock(&em_tree->lock);
 			continue;
@@ -265,319 +261,247 @@
  * If an extent intersects the range but is not entirely inside the range
  * it is either truncated or split.  Anything entirely inside the range
  * is deleted from the tree.
- *
- * inline_limit is used to tell this code which offsets in the file to keep
- * if they contain inline extents.
  */
-noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans,
-		       struct btrfs_root *root, struct inode *inode,
-		       u64 start, u64 end, u64 locked_end,
-		       u64 inline_limit, u64 *hint_byte, int drop_cache)
+int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
+		       u64 start, u64 end, u64 *hint_byte, int drop_cache)
 {
-	u64 extent_end = 0;
-	u64 search_start = start;
-	u64 ram_bytes = 0;
-	u64 disk_bytenr = 0;
-	u64 orig_locked_end = locked_end;
-	u8 compression;
-	u8 encryption;
-	u16 other_encoding = 0;
+	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_buffer *leaf;
-	struct btrfs_file_extent_item *extent;
+	struct btrfs_file_extent_item *fi;
 	struct btrfs_path *path;
 	struct btrfs_key key;
-	struct btrfs_file_extent_item old;
-	int keep;
-	int slot;
-	int bookend;
-	int found_type = 0;
-	int found_extent;
-	int found_inline;
+	struct btrfs_key new_key;
+	u64 search_start = start;
+	u64 disk_bytenr = 0;
+	u64 num_bytes = 0;
+	u64 extent_offset = 0;
+	u64 extent_end = 0;
+	int del_nr = 0;
+	int del_slot = 0;
+	int extent_type;
 	int recow;
 	int ret;
 
-	inline_limit = 0;
 	if (drop_cache)
 		btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
+
 	while (1) {
 		recow = 0;
-		btrfs_release_path(root, path);
 		ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
 					       search_start, -1);
 		if (ret < 0)
-			goto out;
-		if (ret > 0) {
-			if (path->slots[0] == 0) {
-				ret = 0;
-				goto out;
-			}
-			path->slots[0]--;
+			break;
+		if (ret > 0 && path->slots[0] > 0 && search_start == start) {
+			leaf = path->nodes[0];
+			btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
+			if (key.objectid == inode->i_ino &&
+			    key.type == BTRFS_EXTENT_DATA_KEY)
+				path->slots[0]--;
 		}
-next_slot:
-		keep = 0;
-		bookend = 0;
-		found_extent = 0;
-		found_inline = 0;
-		compression = 0;
-		encryption = 0;
-		extent = NULL;
-		leaf = path->nodes[0];
-		slot = path->slots[0];
 		ret = 0;
-		btrfs_item_key_to_cpu(leaf, &key, slot);
-		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY &&
-		    key.offset >= end) {
-			goto out;
-		}
-		if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
-		    key.objectid != inode->i_ino) {
-			goto out;
-		}
-		if (recow) {
-			search_start = max(key.offset, start);
-			continue;
-		}
-		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
-			extent = btrfs_item_ptr(leaf, slot,
-						struct btrfs_file_extent_item);
-			found_type = btrfs_file_extent_type(leaf, extent);
-			compression = btrfs_file_extent_compression(leaf,
-								    extent);
-			encryption = btrfs_file_extent_encryption(leaf,
-								  extent);
-			other_encoding = btrfs_file_extent_other_encoding(leaf,
-								  extent);
-			if (found_type == BTRFS_FILE_EXTENT_REG ||
-			    found_type == BTRFS_FILE_EXTENT_PREALLOC) {
-				extent_end =
-				     btrfs_file_extent_disk_bytenr(leaf,
-								   extent);
-				if (extent_end)
-					*hint_byte = extent_end;
-
-				extent_end = key.offset +
-				     btrfs_file_extent_num_bytes(leaf, extent);
-				ram_bytes = btrfs_file_extent_ram_bytes(leaf,
-								extent);
-				found_extent = 1;
-			} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
-				found_inline = 1;
-				extent_end = key.offset +
-				     btrfs_file_extent_inline_len(leaf, extent);
+next_slot:
+		leaf = path->nodes[0];
+		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
+			BUG_ON(del_nr > 0);
+			ret = btrfs_next_leaf(root, path);
+			if (ret < 0)
+				break;
+			if (ret > 0) {
+				ret = 0;
+				break;
 			}
+			leaf = path->nodes[0];
+			recow = 1;
+		}
+
+		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
+		if (key.objectid > inode->i_ino ||
+		    key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+			break;
+
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+		extent_type = btrfs_file_extent_type(leaf, fi);
+
+		if (extent_type == BTRFS_FILE_EXTENT_REG ||
+		    extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
+			disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
+			num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
+			extent_offset = btrfs_file_extent_offset(leaf, fi);
+			extent_end = key.offset +
+				btrfs_file_extent_num_bytes(leaf, fi);
+		} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+			extent_end = key.offset +
+				btrfs_file_extent_inline_len(leaf, fi);
 		} else {
+			WARN_ON(1);
 			extent_end = search_start;
 		}
 
-		/* we found nothing we can drop */
-		if ((!found_extent && !found_inline) ||
-		    search_start >= extent_end) {
-			int nextret;
-			u32 nritems;
-			nritems = btrfs_header_nritems(leaf);
-			if (slot >= nritems - 1) {
-				nextret = btrfs_next_leaf(root, path);
-				if (nextret)
-					goto out;
-				recow = 1;
-			} else {
-				path->slots[0]++;
-			}
+		if (extent_end <= search_start) {
+			path->slots[0]++;
 			goto next_slot;
 		}
 
-		if (end <= extent_end && start >= key.offset && found_inline)
-			*hint_byte = EXTENT_MAP_INLINE;
-
-		if (found_extent) {
-			read_extent_buffer(leaf, &old, (unsigned long)extent,
-					   sizeof(old));
-		}
-
-		if (end < extent_end && end >= key.offset) {
-			bookend = 1;
-			if (found_inline && start <= key.offset)
-				keep = 1;
-		}
-
-		if (bookend && found_extent) {
-			if (locked_end < extent_end) {
-				ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-						locked_end, extent_end - 1,
-						GFP_NOFS);
-				if (!ret) {
-					btrfs_release_path(root, path);
-					lock_extent(&BTRFS_I(inode)->io_tree,
-						locked_end, extent_end - 1,
-						GFP_NOFS);
-					locked_end = extent_end;
-					continue;
-				}
-				locked_end = extent_end;
-			}
-			disk_bytenr = le64_to_cpu(old.disk_bytenr);
-			if (disk_bytenr != 0) {
-				ret = btrfs_inc_extent_ref(trans, root,
-					   disk_bytenr,
-					   le64_to_cpu(old.disk_num_bytes), 0,
-					   root->root_key.objectid,
-					   key.objectid, key.offset -
-					   le64_to_cpu(old.offset));
-				BUG_ON(ret);
-			}
-		}
-
-		if (found_inline) {
-			u64 mask = root->sectorsize - 1;
-			search_start = (extent_end + mask) & ~mask;
-		} else
-			search_start = extent_end;
-
-		/* truncate existing extent */
-		if (start > key.offset) {
-			u64 new_num;
-			u64 old_num;
-			keep = 1;
-			WARN_ON(start & (root->sectorsize - 1));
-			if (found_extent) {
-				new_num = start - key.offset;
-				old_num = btrfs_file_extent_num_bytes(leaf,
-								      extent);
-				*hint_byte =
-					btrfs_file_extent_disk_bytenr(leaf,
-								      extent);
-				if (btrfs_file_extent_disk_bytenr(leaf,
-								  extent)) {
-					inode_sub_bytes(inode, old_num -
-							new_num);
-				}
-				btrfs_set_file_extent_num_bytes(leaf,
-							extent, new_num);
-				btrfs_mark_buffer_dirty(leaf);
-			} else if (key.offset < inline_limit &&
-				   (end > extent_end) &&
-				   (inline_limit < extent_end)) {
-				u32 new_size;
-				new_size = btrfs_file_extent_calc_inline_size(
-						   inline_limit - key.offset);
-				inode_sub_bytes(inode, extent_end -
-						inline_limit);
-				btrfs_set_file_extent_ram_bytes(leaf, extent,
-							new_size);
-				if (!compression && !encryption) {
-					btrfs_truncate_item(trans, root, path,
-							    new_size, 1);
-				}
-			}
-		}
-		/* delete the entire extent */
-		if (!keep) {
-			if (found_inline)
-				inode_sub_bytes(inode, extent_end -
-						key.offset);
-			ret = btrfs_del_item(trans, root, path);
-			/* TODO update progress marker and return */
-			BUG_ON(ret);
-			extent = NULL;
+		search_start = max(key.offset, start);
+		if (recow) {
 			btrfs_release_path(root, path);
-			/* the extent will be freed later */
+			continue;
 		}
-		if (bookend && found_inline && start <= key.offset) {
-			u32 new_size;
-			new_size = btrfs_file_extent_calc_inline_size(
-						   extent_end - end);
-			inode_sub_bytes(inode, end - key.offset);
-			btrfs_set_file_extent_ram_bytes(leaf, extent,
-							new_size);
-			if (!compression && !encryption)
-				ret = btrfs_truncate_item(trans, root, path,
-							  new_size, 0);
-			BUG_ON(ret);
-		}
-		/* create bookend, splitting the extent in two */
-		if (bookend && found_extent) {
-			struct btrfs_key ins;
-			ins.objectid = inode->i_ino;
-			ins.offset = end;
-			btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
 
-			btrfs_release_path(root, path);
-			path->leave_spinning = 1;
-			ret = btrfs_insert_empty_item(trans, root, path, &ins,
-						      sizeof(*extent));
-			BUG_ON(ret);
+		/*
+		 *     | - range to drop - |
+		 *  | -------- extent -------- |
+		 */
+		if (start > key.offset && end < extent_end) {
+			BUG_ON(del_nr > 0);
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+			memcpy(&new_key, &key, sizeof(new_key));
+			new_key.offset = start;
+			ret = btrfs_duplicate_item(trans, root, path,
+						   &new_key);
+			if (ret == -EAGAIN) {
+				btrfs_release_path(root, path);
+				continue;
+			}
+			if (ret < 0)
+				break;
 
 			leaf = path->nodes[0];
-			extent = btrfs_item_ptr(leaf, path->slots[0],
-						struct btrfs_file_extent_item);
-			write_extent_buffer(leaf, &old,
-					    (unsigned long)extent, sizeof(old));
+			fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
+					    struct btrfs_file_extent_item);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							start - key.offset);
 
-			btrfs_set_file_extent_compression(leaf, extent,
-							  compression);
-			btrfs_set_file_extent_encryption(leaf, extent,
-							 encryption);
-			btrfs_set_file_extent_other_encoding(leaf, extent,
-							     other_encoding);
-			btrfs_set_file_extent_offset(leaf, extent,
-				    le64_to_cpu(old.offset) + end - key.offset);
-			WARN_ON(le64_to_cpu(old.num_bytes) <
-				(extent_end - end));
-			btrfs_set_file_extent_num_bytes(leaf, extent,
-							extent_end - end);
+			fi = btrfs_item_ptr(leaf, path->slots[0],
+					    struct btrfs_file_extent_item);
 
-			/*
-			 * set the ram bytes to the size of the full extent
-			 * before splitting.  This is a worst case flag,
-			 * but its the best we can do because we don't know
-			 * how splitting affects compression
-			 */
-			btrfs_set_file_extent_ram_bytes(leaf, extent,
-							ram_bytes);
-			btrfs_set_file_extent_type(leaf, extent, found_type);
+			extent_offset += start - key.offset;
+			btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							extent_end - start);
+			btrfs_mark_buffer_dirty(leaf);
 
-			btrfs_unlock_up_safe(path, 1);
-			btrfs_mark_buffer_dirty(path->nodes[0]);
-			btrfs_set_lock_blocking(path->nodes[0]);
-
-			path->leave_spinning = 0;
-			btrfs_release_path(root, path);
-			if (disk_bytenr != 0)
-				inode_add_bytes(inode, extent_end - end);
-		}
-
-		if (found_extent && !keep) {
-			u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr);
-
-			if (old_disk_bytenr != 0) {
-				inode_sub_bytes(inode,
-						le64_to_cpu(old.num_bytes));
-				ret = btrfs_free_extent(trans, root,
-						old_disk_bytenr,
-						le64_to_cpu(old.disk_num_bytes),
-						0, root->root_key.objectid,
-						key.objectid, key.offset -
-						le64_to_cpu(old.offset));
+			if (disk_bytenr > 0) {
+				ret = btrfs_inc_extent_ref(trans, root,
+						disk_bytenr, num_bytes, 0,
+						root->root_key.objectid,
+						new_key.objectid,
+						start - extent_offset);
 				BUG_ON(ret);
-				*hint_byte = old_disk_bytenr;
+				*hint_byte = disk_bytenr;
 			}
+			key.offset = start;
+		}
+		/*
+		 *  | ---- range to drop ----- |
+		 *      | -------- extent -------- |
+		 */
+		if (start <= key.offset && end < extent_end) {
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+			memcpy(&new_key, &key, sizeof(new_key));
+			new_key.offset = end;
+			btrfs_set_item_key_safe(trans, root, path, &new_key);
+
+			extent_offset += end - key.offset;
+			btrfs_set_file_extent_offset(leaf, fi, extent_offset);
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							extent_end - end);
+			btrfs_mark_buffer_dirty(leaf);
+			if (disk_bytenr > 0) {
+				inode_sub_bytes(inode, end - key.offset);
+				*hint_byte = disk_bytenr;
+			}
+			break;
 		}
 
-		if (search_start >= end) {
-			ret = 0;
-			goto out;
+		search_start = extent_end;
+		/*
+		 *       | ---- range to drop ----- |
+		 *  | -------- extent -------- |
+		 */
+		if (start > key.offset && end >= extent_end) {
+			BUG_ON(del_nr > 0);
+			BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
+
+			btrfs_set_file_extent_num_bytes(leaf, fi,
+							start - key.offset);
+			btrfs_mark_buffer_dirty(leaf);
+			if (disk_bytenr > 0) {
+				inode_sub_bytes(inode, extent_end - start);
+				*hint_byte = disk_bytenr;
+			}
+			if (end == extent_end)
+				break;
+
+			path->slots[0]++;
+			goto next_slot;
 		}
+
+		/*
+		 *  | ---- range to drop ----- |
+		 *    | ------ extent ------ |
+		 */
+		if (start <= key.offset && end >= extent_end) {
+			if (del_nr == 0) {
+				del_slot = path->slots[0];
+				del_nr = 1;
+			} else {
+				BUG_ON(del_slot + del_nr != path->slots[0]);
+				del_nr++;
+			}
+
+			if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
+				inode_sub_bytes(inode,
+						extent_end - key.offset);
+				extent_end = ALIGN(extent_end,
+						   root->sectorsize);
+			} else if (disk_bytenr > 0) {
+				ret = btrfs_free_extent(trans, root,
+						disk_bytenr, num_bytes, 0,
+						root->root_key.objectid,
+						key.objectid, key.offset -
+						extent_offset);
+				BUG_ON(ret);
+				inode_sub_bytes(inode,
+						extent_end - key.offset);
+				*hint_byte = disk_bytenr;
+			}
+
+			if (end == extent_end)
+				break;
+
+			if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
+				path->slots[0]++;
+				goto next_slot;
+			}
+
+			ret = btrfs_del_items(trans, root, path, del_slot,
+					      del_nr);
+			BUG_ON(ret);
+
+			del_nr = 0;
+			del_slot = 0;
+
+			btrfs_release_path(root, path);
+			continue;
+		}
+
+		BUG_ON(1);
 	}
-out:
+
+	if (del_nr > 0) {
+		ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+		BUG_ON(ret);
+	}
+
 	btrfs_free_path(path);
-	if (locked_end > orig_locked_end) {
-		unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end,
-			      locked_end - 1, GFP_NOFS);
-	}
 	return ret;
 }
 
@@ -620,23 +544,23 @@
  * two or three.
  */
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
-			      struct btrfs_root *root,
 			      struct inode *inode, u64 start, u64 end)
 {
+	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_buffer *leaf;
 	struct btrfs_path *path;
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_key key;
+	struct btrfs_key new_key;
 	u64 bytenr;
 	u64 num_bytes;
 	u64 extent_end;
 	u64 orig_offset;
 	u64 other_start;
 	u64 other_end;
-	u64 split = start;
-	u64 locked_end = end;
-	int extent_type;
-	int split_end = 1;
+	u64 split;
+	int del_nr = 0;
+	int del_slot = 0;
 	int ret;
 
 	btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -644,12 +568,10 @@
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 again:
+	split = start;
 	key.objectid = inode->i_ino;
 	key.type = BTRFS_EXTENT_DATA_KEY;
-	if (split == start)
-		key.offset = split;
-	else
-		key.offset = split - 1;
+	key.offset = split;
 
 	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
 	if (ret > 0 && path->slots[0] > 0)
@@ -661,8 +583,8 @@
 	       key.type != BTRFS_EXTENT_DATA_KEY);
 	fi = btrfs_item_ptr(leaf, path->slots[0],
 			    struct btrfs_file_extent_item);
-	extent_type = btrfs_file_extent_type(leaf, fi);
-	BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC);
+	BUG_ON(btrfs_file_extent_type(leaf, fi) !=
+	       BTRFS_FILE_EXTENT_PREALLOC);
 	extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
 	BUG_ON(key.offset > start || extent_end < end);
 
@@ -670,150 +592,91 @@
 	num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
 	orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi);
 
-	if (key.offset == start)
-		split = end;
+	while (start > key.offset || end < extent_end) {
+		if (key.offset == start)
+			split = end;
 
-	if (key.offset == start && extent_end == end) {
-		int del_nr = 0;
-		int del_slot = 0;
-		other_start = end;
-		other_end = 0;
-		if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			extent_end = other_end;
-			del_slot = path->slots[0] + 1;
-			del_nr++;
-			ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-						0, root->root_key.objectid,
-						inode->i_ino, orig_offset);
-			BUG_ON(ret);
+		memcpy(&new_key, &key, sizeof(new_key));
+		new_key.offset = split;
+		ret = btrfs_duplicate_item(trans, root, path, &new_key);
+		if (ret == -EAGAIN) {
+			btrfs_release_path(root, path);
+			goto again;
 		}
-		other_start = 0;
-		other_end = start;
-		if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			key.offset = other_start;
-			del_slot = path->slots[0];
-			del_nr++;
-			ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-						0, root->root_key.objectid,
-						inode->i_ino, orig_offset);
-			BUG_ON(ret);
-		}
-		split_end = 0;
-		if (del_nr == 0) {
-			btrfs_set_file_extent_type(leaf, fi,
-						   BTRFS_FILE_EXTENT_REG);
-			goto done;
-		}
+		BUG_ON(ret < 0);
 
-		fi = btrfs_item_ptr(leaf, del_slot - 1,
+		leaf = path->nodes[0];
+		fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
 				    struct btrfs_file_extent_item);
-		btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
 		btrfs_set_file_extent_num_bytes(leaf, fi,
-						extent_end - key.offset);
+						split - key.offset);
+
+		fi = btrfs_item_ptr(leaf, path->slots[0],
+				    struct btrfs_file_extent_item);
+
+		btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
+		btrfs_set_file_extent_num_bytes(leaf, fi,
+						extent_end - split);
 		btrfs_mark_buffer_dirty(leaf);
 
-		ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+		ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
+					   root->root_key.objectid,
+					   inode->i_ino, orig_offset);
 		BUG_ON(ret);
-		goto release;
-	} else if (split == start) {
-		if (locked_end < extent_end) {
-			ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-					locked_end, extent_end - 1, GFP_NOFS);
-			if (!ret) {
-				btrfs_release_path(root, path);
-				lock_extent(&BTRFS_I(inode)->io_tree,
-					locked_end, extent_end - 1, GFP_NOFS);
-				locked_end = extent_end;
-				goto again;
-			}
-			locked_end = extent_end;
-		}
-		btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset);
-	} else  {
-		BUG_ON(key.offset != start);
-		key.offset = split;
-		btrfs_set_file_extent_offset(leaf, fi, key.offset -
-					     orig_offset);
-		btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split);
-		btrfs_set_item_key_safe(trans, root, path, &key);
-		extent_end = split;
-	}
 
-	if (extent_end == end) {
-		split_end = 0;
-		extent_type = BTRFS_FILE_EXTENT_REG;
-	}
-	if (extent_end == end && split == start) {
-		other_start = end;
-		other_end = 0;
-		if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
-			path->slots[0]++;
-			fi = btrfs_item_ptr(leaf, path->slots[0],
-					    struct btrfs_file_extent_item);
-			key.offset = split;
-			btrfs_set_item_key_safe(trans, root, path, &key);
-			btrfs_set_file_extent_offset(leaf, fi, key.offset -
-						     orig_offset);
-			btrfs_set_file_extent_num_bytes(leaf, fi,
-							other_end - split);
-			goto done;
-		}
-	}
-	if (extent_end == end && split == end) {
-		other_start = 0;
-		other_end = start;
-		if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino,
-				     bytenr, &other_start, &other_end)) {
+		if (split == start) {
+			key.offset = start;
+		} else {
+			BUG_ON(start != key.offset);
 			path->slots[0]--;
-			fi = btrfs_item_ptr(leaf, path->slots[0],
-					    struct btrfs_file_extent_item);
-			btrfs_set_file_extent_num_bytes(leaf, fi, extent_end -
-							other_start);
-			goto done;
+			extent_end = end;
 		}
 	}
 
-	btrfs_mark_buffer_dirty(leaf);
-
-	ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
-				   root->root_key.objectid,
-				   inode->i_ino, orig_offset);
-	BUG_ON(ret);
-	btrfs_release_path(root, path);
-
-	key.offset = start;
-	ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi));
-	BUG_ON(ret);
-
-	leaf = path->nodes[0];
 	fi = btrfs_item_ptr(leaf, path->slots[0],
 			    struct btrfs_file_extent_item);
-	btrfs_set_file_extent_generation(leaf, fi, trans->transid);
-	btrfs_set_file_extent_type(leaf, fi, extent_type);
-	btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr);
-	btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
-	btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset);
-	btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset);
-	btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
-	btrfs_set_file_extent_compression(leaf, fi, 0);
-	btrfs_set_file_extent_encryption(leaf, fi, 0);
-	btrfs_set_file_extent_other_encoding(leaf, fi, 0);
-done:
+
+	other_start = end;
+	other_end = 0;
+	if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
+			     bytenr, &other_start, &other_end)) {
+		extent_end = other_end;
+		del_slot = path->slots[0] + 1;
+		del_nr++;
+		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+					0, root->root_key.objectid,
+					inode->i_ino, orig_offset);
+		BUG_ON(ret);
+	}
+	other_start = 0;
+	other_end = start;
+	if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
+			     bytenr, &other_start, &other_end)) {
+		key.offset = other_start;
+		del_slot = path->slots[0];
+		del_nr++;
+		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
+					0, root->root_key.objectid,
+					inode->i_ino, orig_offset);
+		BUG_ON(ret);
+	}
+	if (del_nr == 0) {
+		btrfs_set_file_extent_type(leaf, fi,
+					   BTRFS_FILE_EXTENT_REG);
+		btrfs_mark_buffer_dirty(leaf);
+		goto out;
+	}
+
+	fi = btrfs_item_ptr(leaf, del_slot - 1,
+			    struct btrfs_file_extent_item);
+	btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
+	btrfs_set_file_extent_num_bytes(leaf, fi,
+					extent_end - key.offset);
 	btrfs_mark_buffer_dirty(leaf);
 
-release:
-	btrfs_release_path(root, path);
-	if (split_end && split == start) {
-		split = end;
-		goto again;
-	}
-	if (locked_end > end) {
-		unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1,
-			      GFP_NOFS);
-	}
+	ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
+	BUG_ON(ret);
+out:
 	btrfs_free_path(path);
 	return 0;
 }
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b3ad168..5440bab 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -88,13 +88,14 @@
 				   u64 start, u64 end, int *page_started,
 				   unsigned long *nr_written, int unlock);
 
-static int btrfs_init_inode_security(struct inode *inode,  struct inode *dir)
+static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
+				     struct inode *inode,  struct inode *dir)
 {
 	int err;
 
-	err = btrfs_init_acl(inode, dir);
+	err = btrfs_init_acl(trans, inode, dir);
 	if (!err)
-		err = btrfs_xattr_security_init(inode, dir);
+		err = btrfs_xattr_security_init(trans, inode, dir);
 	return err;
 }
 
@@ -188,8 +189,18 @@
 	btrfs_mark_buffer_dirty(leaf);
 	btrfs_free_path(path);
 
+	/*
+	 * we're an inline extent, so nobody can
+	 * extend the file past i_size without locking
+	 * a page we already have locked.
+	 *
+	 * We must do any isize and inode updates
+	 * before we unlock the pages.  Otherwise we
+	 * could end up racing with unlink.
+	 */
 	BTRFS_I(inode)->disk_i_size = inode->i_size;
 	btrfs_update_inode(trans, root, inode);
+
 	return 0;
 fail:
 	btrfs_free_path(path);
@@ -230,8 +241,7 @@
 		return 1;
 	}
 
-	ret = btrfs_drop_extents(trans, root, inode, start,
-				 aligned_end, aligned_end, start,
+	ret = btrfs_drop_extents(trans, inode, start, aligned_end,
 				 &hint_byte, 1);
 	BUG_ON(ret);
 
@@ -416,7 +426,6 @@
 						    start, end,
 						    total_compressed, pages);
 		}
-		btrfs_end_transaction(trans, root);
 		if (ret == 0) {
 			/*
 			 * inline extent creation worked, we don't need
@@ -430,9 +439,11 @@
 			     EXTENT_CLEAR_DELALLOC |
 			     EXTENT_CLEAR_ACCOUNTING |
 			     EXTENT_SET_WRITEBACK | EXTENT_END_WRITEBACK);
-			ret = 0;
+
+			btrfs_end_transaction(trans, root);
 			goto free_pages_out;
 		}
+		btrfs_end_transaction(trans, root);
 	}
 
 	if (will_compress) {
@@ -543,7 +554,6 @@
 	if (list_empty(&async_cow->extents))
 		return 0;
 
-	trans = btrfs_join_transaction(root, 1);
 
 	while (!list_empty(&async_cow->extents)) {
 		async_extent = list_entry(async_cow->extents.next,
@@ -590,19 +600,15 @@
 		lock_extent(io_tree, async_extent->start,
 			    async_extent->start + async_extent->ram_size - 1,
 			    GFP_NOFS);
-		/*
-		 * here we're doing allocation and writeback of the
-		 * compressed pages
-		 */
-		btrfs_drop_extent_cache(inode, async_extent->start,
-					async_extent->start +
-					async_extent->ram_size - 1, 0);
 
+		trans = btrfs_join_transaction(root, 1);
 		ret = btrfs_reserve_extent(trans, root,
 					   async_extent->compressed_size,
 					   async_extent->compressed_size,
 					   0, alloc_hint,
 					   (u64)-1, &ins, 1);
+		btrfs_end_transaction(trans, root);
+
 		if (ret) {
 			int i;
 			for (i = 0; i < async_extent->nr_pages; i++) {
@@ -618,6 +624,14 @@
 			goto retry;
 		}
 
+		/*
+		 * here we're doing allocation and writeback of the
+		 * compressed pages
+		 */
+		btrfs_drop_extent_cache(inode, async_extent->start,
+					async_extent->start +
+					async_extent->ram_size - 1, 0);
+
 		em = alloc_extent_map(GFP_NOFS);
 		em->start = async_extent->start;
 		em->len = async_extent->ram_size;
@@ -649,8 +663,6 @@
 					       BTRFS_ORDERED_COMPRESSED);
 		BUG_ON(ret);
 
-		btrfs_end_transaction(trans, root);
-
 		/*
 		 * clear dirty, set writeback and unlock the pages.
 		 */
@@ -672,13 +684,11 @@
 				    async_extent->nr_pages);
 
 		BUG_ON(ret);
-		trans = btrfs_join_transaction(root, 1);
 		alloc_hint = ins.objectid + ins.offset;
 		kfree(async_extent);
 		cond_resched();
 	}
 
-	btrfs_end_transaction(trans, root);
 	return 0;
 }
 
@@ -742,6 +752,7 @@
 				     EXTENT_CLEAR_DIRTY |
 				     EXTENT_SET_WRITEBACK |
 				     EXTENT_END_WRITEBACK);
+
 			*nr_written = *nr_written +
 			     (end - start + PAGE_CACHE_SIZE) / PAGE_CACHE_SIZE;
 			*page_started = 1;
@@ -1596,7 +1607,6 @@
 				       struct inode *inode, u64 file_pos,
 				       u64 disk_bytenr, u64 disk_num_bytes,
 				       u64 num_bytes, u64 ram_bytes,
-				       u64 locked_end,
 				       u8 compression, u8 encryption,
 				       u16 other_encoding, int extent_type)
 {
@@ -1622,9 +1632,8 @@
 	 * the caller is expected to unpin it and allow it to be merged
 	 * with the others.
 	 */
-	ret = btrfs_drop_extents(trans, root, inode, file_pos,
-				 file_pos + num_bytes, locked_end,
-				 file_pos, &hint, 0);
+	ret = btrfs_drop_extents(trans, inode, file_pos, file_pos + num_bytes,
+				 &hint, 0);
 	BUG_ON(ret);
 
 	ins.objectid = inode->i_ino;
@@ -1730,23 +1739,32 @@
 		}
 	}
 
-	trans = btrfs_join_transaction(root, 1);
-
 	if (!ordered_extent)
 		ordered_extent = btrfs_lookup_ordered_extent(inode, start);
 	BUG_ON(!ordered_extent);
-	if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags))
-		goto nocow;
+	if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
+		BUG_ON(!list_empty(&ordered_extent->list));
+		ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+		if (!ret) {
+			trans = btrfs_join_transaction(root, 1);
+			ret = btrfs_update_inode(trans, root, inode);
+			BUG_ON(ret);
+			btrfs_end_transaction(trans, root);
+		}
+		goto out;
+	}
 
 	lock_extent(io_tree, ordered_extent->file_offset,
 		    ordered_extent->file_offset + ordered_extent->len - 1,
 		    GFP_NOFS);
 
+	trans = btrfs_join_transaction(root, 1);
+
 	if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
 		compressed = 1;
 	if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
 		BUG_ON(compressed);
-		ret = btrfs_mark_extent_written(trans, root, inode,
+		ret = btrfs_mark_extent_written(trans, inode,
 						ordered_extent->file_offset,
 						ordered_extent->file_offset +
 						ordered_extent->len);
@@ -1758,8 +1776,6 @@
 						ordered_extent->disk_len,
 						ordered_extent->len,
 						ordered_extent->len,
-						ordered_extent->file_offset +
-						ordered_extent->len,
 						compressed, 0, 0,
 						BTRFS_FILE_EXTENT_REG);
 		unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
@@ -1770,22 +1786,20 @@
 	unlock_extent(io_tree, ordered_extent->file_offset,
 		    ordered_extent->file_offset + ordered_extent->len - 1,
 		    GFP_NOFS);
-nocow:
 	add_pending_csums(trans, inode, ordered_extent->file_offset,
 			  &ordered_extent->list);
 
-	mutex_lock(&BTRFS_I(inode)->extent_mutex);
-	btrfs_ordered_update_i_size(inode, ordered_extent);
-	btrfs_update_inode(trans, root, inode);
-	btrfs_remove_ordered_extent(inode, ordered_extent);
-	mutex_unlock(&BTRFS_I(inode)->extent_mutex);
-
+	/* this also removes the ordered extent from the tree */
+	btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+	ret = btrfs_update_inode(trans, root, inode);
+	BUG_ON(ret);
+	btrfs_end_transaction(trans, root);
+out:
 	/* once for us */
 	btrfs_put_ordered_extent(ordered_extent);
 	/* once for the tree */
 	btrfs_put_ordered_extent(ordered_extent);
 
-	btrfs_end_transaction(trans, root);
 	return 0;
 }
 
@@ -2008,6 +2022,54 @@
 	return -EIO;
 }
 
+struct delayed_iput {
+	struct list_head list;
+	struct inode *inode;
+};
+
+void btrfs_add_delayed_iput(struct inode *inode)
+{
+	struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
+	struct delayed_iput *delayed;
+
+	if (atomic_add_unless(&inode->i_count, -1, 1))
+		return;
+
+	delayed = kmalloc(sizeof(*delayed), GFP_NOFS | __GFP_NOFAIL);
+	delayed->inode = inode;
+
+	spin_lock(&fs_info->delayed_iput_lock);
+	list_add_tail(&delayed->list, &fs_info->delayed_iputs);
+	spin_unlock(&fs_info->delayed_iput_lock);
+}
+
+void btrfs_run_delayed_iputs(struct btrfs_root *root)
+{
+	LIST_HEAD(list);
+	struct btrfs_fs_info *fs_info = root->fs_info;
+	struct delayed_iput *delayed;
+	int empty;
+
+	spin_lock(&fs_info->delayed_iput_lock);
+	empty = list_empty(&fs_info->delayed_iputs);
+	spin_unlock(&fs_info->delayed_iput_lock);
+	if (empty)
+		return;
+
+	down_read(&root->fs_info->cleanup_work_sem);
+	spin_lock(&fs_info->delayed_iput_lock);
+	list_splice_init(&fs_info->delayed_iputs, &list);
+	spin_unlock(&fs_info->delayed_iput_lock);
+
+	while (!list_empty(&list)) {
+		delayed = list_entry(list.next, struct delayed_iput, list);
+		list_del(&delayed->list);
+		iput(delayed->inode);
+		kfree(delayed);
+	}
+	up_read(&root->fs_info->cleanup_work_sem);
+}
+
 /*
  * This creates an orphan entry for the given inode in case something goes
  * wrong in the middle of an unlink/truncate.
@@ -2080,16 +2142,17 @@
 	struct inode *inode;
 	int ret = 0, nr_unlink = 0, nr_truncate = 0;
 
-	path = btrfs_alloc_path();
-	if (!path)
+	if (!xchg(&root->clean_orphans, 0))
 		return;
+
+	path = btrfs_alloc_path();
+	BUG_ON(!path);
 	path->reada = -1;
 
 	key.objectid = BTRFS_ORPHAN_OBJECTID;
 	btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY);
 	key.offset = (u64)-1;
 
-
 	while (1) {
 		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 		if (ret < 0) {
@@ -2834,37 +2897,40 @@
  * min_type is the minimum key type to truncate down to.  If set to 0, this
  * will kill all the items on this inode, including the INODE_ITEM_KEY.
  */
-noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
-					struct btrfs_root *root,
-					struct inode *inode,
-					u64 new_size, u32 min_type)
+int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
+			       struct btrfs_root *root,
+			       struct inode *inode,
+			       u64 new_size, u32 min_type)
 {
-	int ret;
 	struct btrfs_path *path;
-	struct btrfs_key key;
-	struct btrfs_key found_key;
-	u32 found_type = (u8)-1;
 	struct extent_buffer *leaf;
 	struct btrfs_file_extent_item *fi;
+	struct btrfs_key key;
+	struct btrfs_key found_key;
 	u64 extent_start = 0;
 	u64 extent_num_bytes = 0;
 	u64 extent_offset = 0;
 	u64 item_end = 0;
+	u64 mask = root->sectorsize - 1;
+	u32 found_type = (u8)-1;
 	int found_extent;
 	int del_item;
 	int pending_del_nr = 0;
 	int pending_del_slot = 0;
 	int extent_type = -1;
 	int encoding;
-	u64 mask = root->sectorsize - 1;
+	int ret;
+	int err = 0;
+
+	BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
 	if (root->ref_cows)
 		btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
+
 	path = btrfs_alloc_path();
 	BUG_ON(!path);
 	path->reada = -1;
 
-	/* FIXME, add redo link to tree so we don't leak on crash */
 	key.objectid = inode->i_ino;
 	key.offset = (u64)-1;
 	key.type = (u8)-1;
@@ -2872,17 +2938,17 @@
 search_again:
 	path->leave_spinning = 1;
 	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
-	if (ret < 0)
-		goto error;
+	if (ret < 0) {
+		err = ret;
+		goto out;
+	}
 
 	if (ret > 0) {
 		/* there are no items in the tree for us to truncate, we're
 		 * done
 		 */
-		if (path->slots[0] == 0) {
-			ret = 0;
-			goto error;
-		}
+		if (path->slots[0] == 0)
+			goto out;
 		path->slots[0]--;
 	}
 
@@ -2917,28 +2983,17 @@
 			}
 			item_end--;
 		}
-		if (item_end < new_size) {
-			if (found_type == BTRFS_DIR_ITEM_KEY)
-				found_type = BTRFS_INODE_ITEM_KEY;
-			else if (found_type == BTRFS_EXTENT_ITEM_KEY)
-				found_type = BTRFS_EXTENT_DATA_KEY;
-			else if (found_type == BTRFS_EXTENT_DATA_KEY)
-				found_type = BTRFS_XATTR_ITEM_KEY;
-			else if (found_type == BTRFS_XATTR_ITEM_KEY)
-				found_type = BTRFS_INODE_REF_KEY;
-			else if (found_type)
-				found_type--;
-			else
-				break;
-			btrfs_set_key_type(&key, found_type);
-			goto next;
-		}
-		if (found_key.offset >= new_size)
+		if (found_type > min_type) {
 			del_item = 1;
-		else
-			del_item = 0;
+		} else {
+			if (item_end < new_size)
+				break;
+			if (found_key.offset >= new_size)
+				del_item = 1;
+			else
+				del_item = 0;
+		}
 		found_extent = 0;
-
 		/* FIXME, shrink the extent if the ref count is only 1 */
 		if (found_type != BTRFS_EXTENT_DATA_KEY)
 			goto delete;
@@ -3025,42 +3080,36 @@
 						inode->i_ino, extent_offset);
 			BUG_ON(ret);
 		}
-next:
-		if (path->slots[0] == 0) {
-			if (pending_del_nr)
-				goto del_pending;
-			btrfs_release_path(root, path);
-			if (found_type == BTRFS_INODE_ITEM_KEY)
-				break;
-			goto search_again;
-		}
 
-		path->slots[0]--;
-		if (pending_del_nr &&
-		    path->slots[0] + 1 != pending_del_slot) {
-			struct btrfs_key debug;
-del_pending:
-			btrfs_item_key_to_cpu(path->nodes[0], &debug,
-					      pending_del_slot);
-			ret = btrfs_del_items(trans, root, path,
-					      pending_del_slot,
-					      pending_del_nr);
-			BUG_ON(ret);
-			pending_del_nr = 0;
+		if (found_type == BTRFS_INODE_ITEM_KEY)
+			break;
+
+		if (path->slots[0] == 0 ||
+		    path->slots[0] != pending_del_slot) {
+			if (root->ref_cows) {
+				err = -EAGAIN;
+				goto out;
+			}
+			if (pending_del_nr) {
+				ret = btrfs_del_items(trans, root, path,
+						pending_del_slot,
+						pending_del_nr);
+				BUG_ON(ret);
+				pending_del_nr = 0;
+			}
 			btrfs_release_path(root, path);
-			if (found_type == BTRFS_INODE_ITEM_KEY)
-				break;
 			goto search_again;
+		} else {
+			path->slots[0]--;
 		}
 	}
-	ret = 0;
-error:
+out:
 	if (pending_del_nr) {
 		ret = btrfs_del_items(trans, root, path, pending_del_slot,
 				      pending_del_nr);
 	}
 	btrfs_free_path(path);
-	return ret;
+	return err;
 }
 
 /*
@@ -3180,10 +3229,6 @@
 	if (size <= hole_start)
 		return 0;
 
-	err = btrfs_truncate_page(inode->i_mapping, inode->i_size);
-	if (err)
-		return err;
-
 	while (1) {
 		struct btrfs_ordered_extent *ordered;
 		btrfs_wait_ordered_range(inode, hole_start,
@@ -3196,9 +3241,6 @@
 		btrfs_put_ordered_extent(ordered);
 	}
 
-	trans = btrfs_start_transaction(root, 1);
-	btrfs_set_trans_block_group(trans, inode);
-
 	cur_offset = hole_start;
 	while (1) {
 		em = btrfs_get_extent(inode, NULL, 0, cur_offset,
@@ -3206,40 +3248,120 @@
 		BUG_ON(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), block_end);
 		last_byte = (last_byte + mask) & ~mask;
-		if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
+		if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
 			u64 hint_byte = 0;
 			hole_size = last_byte - cur_offset;
-			err = btrfs_drop_extents(trans, root, inode,
-						 cur_offset,
-						 cur_offset + hole_size,
-						 block_end,
-						 cur_offset, &hint_byte, 1);
+
+			err = btrfs_reserve_metadata_space(root, 2);
 			if (err)
 				break;
 
-			err = btrfs_reserve_metadata_space(root, 1);
-			if (err)
-				break;
+			trans = btrfs_start_transaction(root, 1);
+			btrfs_set_trans_block_group(trans, inode);
+
+			err = btrfs_drop_extents(trans, inode, cur_offset,
+						 cur_offset + hole_size,
+						 &hint_byte, 1);
+			BUG_ON(err);
 
 			err = btrfs_insert_file_extent(trans, root,
 					inode->i_ino, cur_offset, 0,
 					0, hole_size, 0, hole_size,
 					0, 0, 0);
+			BUG_ON(err);
+
 			btrfs_drop_extent_cache(inode, hole_start,
 					last_byte - 1, 0);
-			btrfs_unreserve_metadata_space(root, 1);
+
+			btrfs_end_transaction(trans, root);
+			btrfs_unreserve_metadata_space(root, 2);
 		}
 		free_extent_map(em);
 		cur_offset = last_byte;
-		if (err || cur_offset >= block_end)
+		if (cur_offset >= block_end)
 			break;
 	}
 
-	btrfs_end_transaction(trans, root);
 	unlock_extent(io_tree, hole_start, block_end - 1, GFP_NOFS);
 	return err;
 }
 
+static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
+{
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	struct btrfs_trans_handle *trans;
+	unsigned long nr;
+	int ret;
+
+	if (attr->ia_size == inode->i_size)
+		return 0;
+
+	if (attr->ia_size > inode->i_size) {
+		unsigned long limit;
+		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+		if (attr->ia_size > inode->i_sb->s_maxbytes)
+			return -EFBIG;
+		if (limit != RLIM_INFINITY && attr->ia_size > limit) {
+			send_sig(SIGXFSZ, current, 0);
+			return -EFBIG;
+		}
+	}
+
+	ret = btrfs_reserve_metadata_space(root, 1);
+	if (ret)
+		return ret;
+
+	trans = btrfs_start_transaction(root, 1);
+	btrfs_set_trans_block_group(trans, inode);
+
+	ret = btrfs_orphan_add(trans, inode);
+	BUG_ON(ret);
+
+	nr = trans->blocks_used;
+	btrfs_end_transaction(trans, root);
+	btrfs_unreserve_metadata_space(root, 1);
+	btrfs_btree_balance_dirty(root, nr);
+
+	if (attr->ia_size > inode->i_size) {
+		ret = btrfs_cont_expand(inode, attr->ia_size);
+		if (ret) {
+			btrfs_truncate(inode);
+			return ret;
+		}
+
+		i_size_write(inode, attr->ia_size);
+		btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
+
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+
+		ret = btrfs_update_inode(trans, root, inode);
+		BUG_ON(ret);
+		if (inode->i_nlink > 0) {
+			ret = btrfs_orphan_del(trans, inode);
+			BUG_ON(ret);
+		}
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		btrfs_btree_balance_dirty(root, nr);
+		return 0;
+	}
+
+	/*
+	 * We're truncating a file that used to have good data down to
+	 * zero. Make sure it gets into the ordered flush list so that
+	 * any new writes get down to disk quickly.
+	 */
+	if (attr->ia_size == 0)
+		BTRFS_I(inode)->ordered_data_close = 1;
+
+	/* we don't support swapfiles, so vmtruncate shouldn't fail */
+	ret = vmtruncate(inode, attr->ia_size);
+	BUG_ON(ret);
+
+	return 0;
+}
+
 static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
@@ -3250,23 +3372,14 @@
 		return err;
 
 	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-		if (attr->ia_size > inode->i_size) {
-			err = btrfs_cont_expand(inode, attr->ia_size);
-			if (err)
-				return err;
-		} else if (inode->i_size > 0 &&
-			   attr->ia_size == 0) {
-
-			/* we're truncating a file that used to have good
-			 * data down to zero.  Make sure it gets into
-			 * the ordered flush list so that any new writes
-			 * get down to disk quickly.
-			 */
-			BTRFS_I(inode)->ordered_data_close = 1;
-		}
+		err = btrfs_setattr_size(inode, attr);
+		if (err)
+			return err;
 	}
+	attr->ia_valid &= ~ATTR_SIZE;
 
-	err = inode_setattr(inode, attr);
+	if (attr->ia_valid)
+		err = inode_setattr(inode, attr);
 
 	if (!err && ((attr->ia_valid & ATTR_MODE)))
 		err = btrfs_acl_chmod(inode);
@@ -3287,36 +3400,43 @@
 	}
 	btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
+	if (root->fs_info->log_root_recovering) {
+		BUG_ON(!list_empty(&BTRFS_I(inode)->i_orphan));
+		goto no_delete;
+	}
+
 	if (inode->i_nlink > 0) {
 		BUG_ON(btrfs_root_refs(&root->root_item) != 0);
 		goto no_delete;
 	}
 
 	btrfs_i_size_write(inode, 0);
-	trans = btrfs_join_transaction(root, 1);
 
-	btrfs_set_trans_block_group(trans, inode);
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, 0);
-	if (ret) {
-		btrfs_orphan_del(NULL, inode);
-		goto no_delete_lock;
+	while (1) {
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+		ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
+
+		if (ret != -EAGAIN)
+			break;
+
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		trans = NULL;
+		btrfs_btree_balance_dirty(root, nr);
 	}
 
-	btrfs_orphan_del(trans, inode);
+	if (ret == 0) {
+		ret = btrfs_orphan_del(trans, inode);
+		BUG_ON(ret);
+	}
 
 	nr = trans->blocks_used;
-	clear_inode(inode);
-
-	btrfs_end_transaction(trans, root);
-	btrfs_btree_balance_dirty(root, nr);
-	return;
-
-no_delete_lock:
-	nr = trans->blocks_used;
 	btrfs_end_transaction(trans, root);
 	btrfs_btree_balance_dirty(root, nr);
 no_delete:
 	clear_inode(inode);
+	return;
 }
 
 /*
@@ -3569,7 +3689,6 @@
 	INIT_LIST_HEAD(&BTRFS_I(inode)->ordered_operations);
 	RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
 	btrfs_ordered_inode_tree_init(&BTRFS_I(inode)->ordered_tree);
-	mutex_init(&BTRFS_I(inode)->extent_mutex);
 	mutex_init(&BTRFS_I(inode)->log_mutex);
 }
 
@@ -3695,6 +3814,13 @@
 	}
 	srcu_read_unlock(&root->fs_info->subvol_srcu, index);
 
+	if (root != sub_root) {
+		down_read(&root->fs_info->cleanup_work_sem);
+		if (!(inode->i_sb->s_flags & MS_RDONLY))
+			btrfs_orphan_cleanup(sub_root);
+		up_read(&root->fs_info->cleanup_work_sem);
+	}
+
 	return inode;
 }
 
@@ -4219,7 +4345,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4290,7 +4416,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4336,6 +4462,10 @@
 	if (inode->i_nlink == 0)
 		return -ENOENT;
 
+	/* do not allow sys_link's with other subvols of the same device */
+	if (root->objectid != BTRFS_I(inode)->root->objectid)
+		return -EPERM;
+
 	/*
 	 * 1 item for inode ref
 	 * 2 items for dir items
@@ -4423,7 +4553,7 @@
 
 	drop_on_err = 1;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err)
 		goto out_fail;
 
@@ -5074,17 +5204,20 @@
 	unsigned long nr;
 	u64 mask = root->sectorsize - 1;
 
-	if (!S_ISREG(inode->i_mode))
+	if (!S_ISREG(inode->i_mode)) {
+		WARN_ON(1);
 		return;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
+	}
 
 	ret = btrfs_truncate_page(inode->i_mapping, inode->i_size);
 	if (ret)
 		return;
+
 	btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1);
+	btrfs_ordered_update_i_size(inode, inode->i_size, NULL);
 
 	trans = btrfs_start_transaction(root, 1);
+	btrfs_set_trans_block_group(trans, inode);
 
 	/*
 	 * setattr is responsible for setting the ordered_data_close flag,
@@ -5106,21 +5239,32 @@
 	if (inode->i_size == 0 && BTRFS_I(inode)->ordered_data_close)
 		btrfs_add_ordered_operation(trans, root, inode);
 
-	btrfs_set_trans_block_group(trans, inode);
-	btrfs_i_size_write(inode, inode->i_size);
+	while (1) {
+		ret = btrfs_truncate_inode_items(trans, root, inode,
+						 inode->i_size,
+						 BTRFS_EXTENT_DATA_KEY);
+		if (ret != -EAGAIN)
+			break;
 
-	ret = btrfs_orphan_add(trans, inode);
-	if (ret)
-		goto out;
-	/* FIXME, add redo link to tree so we don't leak on crash */
-	ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size,
-				      BTRFS_EXTENT_DATA_KEY);
-	btrfs_update_inode(trans, root, inode);
+		ret = btrfs_update_inode(trans, root, inode);
+		BUG_ON(ret);
 
-	ret = btrfs_orphan_del(trans, inode);
+		nr = trans->blocks_used;
+		btrfs_end_transaction(trans, root);
+		btrfs_btree_balance_dirty(root, nr);
+
+		trans = btrfs_start_transaction(root, 1);
+		btrfs_set_trans_block_group(trans, inode);
+	}
+
+	if (ret == 0 && inode->i_nlink > 0) {
+		ret = btrfs_orphan_del(trans, inode);
+		BUG_ON(ret);
+	}
+
+	ret = btrfs_update_inode(trans, root, inode);
 	BUG_ON(ret);
 
-out:
 	nr = trans->blocks_used;
 	ret = btrfs_end_transaction_throttle(trans, root);
 	BUG_ON(ret);
@@ -5217,9 +5361,9 @@
 
 	spin_lock(&root->list_lock);
 	if (!list_empty(&BTRFS_I(inode)->i_orphan)) {
-		printk(KERN_ERR "BTRFS: inode %lu: inode still on the orphan"
-		       " list\n", inode->i_ino);
-		dump_stack();
+		printk(KERN_INFO "BTRFS: inode %lu still on the orphan list\n",
+		       inode->i_ino);
+		list_del_init(&BTRFS_I(inode)->i_orphan);
 	}
 	spin_unlock(&root->list_lock);
 
@@ -5476,7 +5620,7 @@
  * some fairly slow code that needs optimization. This walks the list
  * of all the inodes with pending delalloc and forces them to disk.
  */
-int btrfs_start_delalloc_inodes(struct btrfs_root *root)
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
 	struct list_head *head = &root->fs_info->delalloc_inodes;
 	struct btrfs_inode *binode;
@@ -5495,7 +5639,10 @@
 		spin_unlock(&root->fs_info->delalloc_lock);
 		if (inode) {
 			filemap_flush(inode->i_mapping);
-			iput(inode);
+			if (delay_iput)
+				btrfs_add_delayed_iput(inode);
+			else
+				iput(inode);
 		}
 		cond_resched();
 		spin_lock(&root->fs_info->delalloc_lock);
@@ -5569,7 +5716,7 @@
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -5641,10 +5788,10 @@
 	return err;
 }
 
-static int prealloc_file_range(struct btrfs_trans_handle *trans,
-			       struct inode *inode, u64 start, u64 end,
-			       u64 locked_end, u64 alloc_hint, int mode)
+static int prealloc_file_range(struct inode *inode, u64 start, u64 end,
+			       u64 alloc_hint, int mode)
 {
+	struct btrfs_trans_handle *trans;
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_key ins;
 	u64 alloc_size;
@@ -5655,43 +5802,56 @@
 	while (num_bytes > 0) {
 		alloc_size = min(num_bytes, root->fs_info->max_extent);
 
-		ret = btrfs_reserve_metadata_space(root, 1);
-		if (ret)
-			goto out;
+		trans = btrfs_start_transaction(root, 1);
 
 		ret = btrfs_reserve_extent(trans, root, alloc_size,
 					   root->sectorsize, 0, alloc_hint,
 					   (u64)-1, &ins, 1);
 		if (ret) {
 			WARN_ON(1);
-			goto out;
+			goto stop_trans;
 		}
+
+		ret = btrfs_reserve_metadata_space(root, 3);
+		if (ret) {
+			btrfs_free_reserved_extent(root, ins.objectid,
+						   ins.offset);
+			goto stop_trans;
+		}
+
 		ret = insert_reserved_file_extent(trans, inode,
 						  cur_offset, ins.objectid,
 						  ins.offset, ins.offset,
-						  ins.offset, locked_end,
-						  0, 0, 0,
+						  ins.offset, 0, 0, 0,
 						  BTRFS_FILE_EXTENT_PREALLOC);
 		BUG_ON(ret);
 		btrfs_drop_extent_cache(inode, cur_offset,
 					cur_offset + ins.offset -1, 0);
+
 		num_bytes -= ins.offset;
 		cur_offset += ins.offset;
 		alloc_hint = ins.objectid + ins.offset;
-		btrfs_unreserve_metadata_space(root, 1);
-	}
-out:
-	if (cur_offset > start) {
+
 		inode->i_ctime = CURRENT_TIME;
 		BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC;
 		if (!(mode & FALLOC_FL_KEEP_SIZE) &&
-		    cur_offset > i_size_read(inode))
-			btrfs_i_size_write(inode, cur_offset);
+		    cur_offset > inode->i_size) {
+			i_size_write(inode, cur_offset);
+			btrfs_ordered_update_i_size(inode, cur_offset, NULL);
+		}
+
 		ret = btrfs_update_inode(trans, root, inode);
 		BUG_ON(ret);
-	}
 
+		btrfs_end_transaction(trans, root);
+		btrfs_unreserve_metadata_space(root, 3);
+	}
 	return ret;
+
+stop_trans:
+	btrfs_end_transaction(trans, root);
+	return ret;
+
 }
 
 static long btrfs_fallocate(struct inode *inode, int mode,
@@ -5705,8 +5865,6 @@
 	u64 locked_end;
 	u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
 	struct extent_map *em;
-	struct btrfs_trans_handle *trans;
-	struct btrfs_root *root;
 	int ret;
 
 	alloc_start = offset & ~mask;
@@ -5725,9 +5883,7 @@
 			goto out;
 	}
 
-	root = BTRFS_I(inode)->root;
-
-	ret = btrfs_check_data_free_space(root, inode,
+	ret = btrfs_check_data_free_space(BTRFS_I(inode)->root, inode,
 					  alloc_end - alloc_start);
 	if (ret)
 		goto out;
@@ -5736,12 +5892,6 @@
 	while (1) {
 		struct btrfs_ordered_extent *ordered;
 
-		trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
-		if (!trans) {
-			ret = -EIO;
-			goto out_free;
-		}
-
 		/* the extent lock is ordered inside the running
 		 * transaction
 		 */
@@ -5755,8 +5905,6 @@
 			btrfs_put_ordered_extent(ordered);
 			unlock_extent(&BTRFS_I(inode)->io_tree,
 				      alloc_start, locked_end, GFP_NOFS);
-			btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-
 			/*
 			 * we can't wait on the range with the transaction
 			 * running or with the extent lock held
@@ -5777,10 +5925,12 @@
 		BUG_ON(IS_ERR(em) || !em);
 		last_byte = min(extent_map_end(em), alloc_end);
 		last_byte = (last_byte + mask) & ~mask;
-		if (em->block_start == EXTENT_MAP_HOLE) {
-			ret = prealloc_file_range(trans, inode, cur_offset,
-					last_byte, locked_end + 1,
-					alloc_hint, mode);
+		if (em->block_start == EXTENT_MAP_HOLE ||
+		    (cur_offset >= inode->i_size &&
+		     !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
+			ret = prealloc_file_range(inode,
+						  cur_offset, last_byte,
+						  alloc_hint, mode);
 			if (ret < 0) {
 				free_extent_map(em);
 				break;
@@ -5799,9 +5949,8 @@
 	unlock_extent(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
 		      GFP_NOFS);
 
-	btrfs_end_transaction(trans, BTRFS_I(inode)->root);
-out_free:
-	btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
+	btrfs_free_reserved_data_space(BTRFS_I(inode)->root, inode,
+				       alloc_end - alloc_start);
 out:
 	mutex_unlock(&inode->i_mutex);
 	return ret;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index cdbb054..645a179 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -237,7 +237,6 @@
 	u64 objectid;
 	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
 	u64 index = 0;
-	unsigned long nr = 1;
 
 	/*
 	 * 1 - inode item
@@ -290,7 +289,7 @@
 	btrfs_set_root_generation(&root_item, trans->transid);
 	btrfs_set_root_level(&root_item, 0);
 	btrfs_set_root_refs(&root_item, 1);
-	btrfs_set_root_used(&root_item, 0);
+	btrfs_set_root_used(&root_item, leaf->len);
 	btrfs_set_root_last_snapshot(&root_item, 0);
 
 	memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
@@ -342,24 +341,21 @@
 
 	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
 fail:
-	nr = trans->blocks_used;
 	err = btrfs_commit_transaction(trans, root);
 	if (err && !ret)
 		ret = err;
 
 	btrfs_unreserve_metadata_space(root, 6);
-	btrfs_btree_balance_dirty(root, nr);
 	return ret;
 }
 
 static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
 			   char *name, int namelen)
 {
+	struct inode *inode;
 	struct btrfs_pending_snapshot *pending_snapshot;
 	struct btrfs_trans_handle *trans;
-	int ret = 0;
-	int err;
-	unsigned long nr = 0;
+	int ret;
 
 	if (!root->ref_cows)
 		return -EINVAL;
@@ -372,20 +368,20 @@
 	 */
 	ret = btrfs_reserve_metadata_space(root, 6);
 	if (ret)
-		goto fail_unlock;
+		goto fail;
 
 	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
 	if (!pending_snapshot) {
 		ret = -ENOMEM;
 		btrfs_unreserve_metadata_space(root, 6);
-		goto fail_unlock;
+		goto fail;
 	}
 	pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS);
 	if (!pending_snapshot->name) {
 		ret = -ENOMEM;
 		kfree(pending_snapshot);
 		btrfs_unreserve_metadata_space(root, 6);
-		goto fail_unlock;
+		goto fail;
 	}
 	memcpy(pending_snapshot->name, name, namelen);
 	pending_snapshot->name[namelen] = '\0';
@@ -395,10 +391,19 @@
 	pending_snapshot->root = root;
 	list_add(&pending_snapshot->list,
 		 &trans->transaction->pending_snapshots);
-	err = btrfs_commit_transaction(trans, root);
+	ret = btrfs_commit_transaction(trans, root);
+	BUG_ON(ret);
+	btrfs_unreserve_metadata_space(root, 6);
 
-fail_unlock:
-	btrfs_btree_balance_dirty(root, nr);
+	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
+	if (IS_ERR(inode)) {
+		ret = PTR_ERR(inode);
+		goto fail;
+	}
+	BUG_ON(!inode);
+	d_instantiate(dentry, inode);
+	ret = 0;
+fail:
 	return ret;
 }
 
@@ -1027,8 +1032,7 @@
 	BUG_ON(!trans);
 
 	/* punch hole in destination first */
-	btrfs_drop_extents(trans, root, inode, off, off + len,
-			   off + len, 0, &hint_byte, 1);
+	btrfs_drop_extents(trans, inode, off, off + len, &hint_byte, 1);
 
 	/* clone data */
 	key.objectid = src->i_ino;
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index 5799bc4..b10a49d 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -291,16 +291,16 @@
 
 /*
  * remove an ordered extent from the tree.  No references are dropped
- * but, anyone waiting on this extent is woken up.
+ * and you must wake_up entry->wait.  You must hold the tree mutex
+ * while you call this function.
  */
-int btrfs_remove_ordered_extent(struct inode *inode,
+static int __btrfs_remove_ordered_extent(struct inode *inode,
 				struct btrfs_ordered_extent *entry)
 {
 	struct btrfs_ordered_inode_tree *tree;
 	struct rb_node *node;
 
 	tree = &BTRFS_I(inode)->ordered_tree;
-	mutex_lock(&tree->mutex);
 	node = &entry->rb_node;
 	rb_erase(node, &tree->tree);
 	tree->last = NULL;
@@ -326,16 +326,34 @@
 	}
 	spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
 
+	return 0;
+}
+
+/*
+ * remove an ordered extent from the tree.  No references are dropped
+ * but any waiters are woken.
+ */
+int btrfs_remove_ordered_extent(struct inode *inode,
+				struct btrfs_ordered_extent *entry)
+{
+	struct btrfs_ordered_inode_tree *tree;
+	int ret;
+
+	tree = &BTRFS_I(inode)->ordered_tree;
+	mutex_lock(&tree->mutex);
+	ret = __btrfs_remove_ordered_extent(inode, entry);
 	mutex_unlock(&tree->mutex);
 	wake_up(&entry->wait);
-	return 0;
+
+	return ret;
 }
 
 /*
  * wait for all the ordered extents in a root.  This is done when balancing
  * space between drives.
  */
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only)
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+			       int nocow_only, int delay_iput)
 {
 	struct list_head splice;
 	struct list_head *cur;
@@ -372,7 +390,10 @@
 		if (inode) {
 			btrfs_start_ordered_extent(inode, ordered, 1);
 			btrfs_put_ordered_extent(ordered);
-			iput(inode);
+			if (delay_iput)
+				btrfs_add_delayed_iput(inode);
+			else
+				iput(inode);
 		} else {
 			btrfs_put_ordered_extent(ordered);
 		}
@@ -430,7 +451,7 @@
 				btrfs_wait_ordered_range(inode, 0, (u64)-1);
 			else
 				filemap_flush(inode->i_mapping);
-			iput(inode);
+			btrfs_add_delayed_iput(inode);
 		}
 
 		cond_resched();
@@ -589,7 +610,7 @@
  * After an extent is done, call this to conditionally update the on disk
  * i_size.  i_size is updated to cover any fully written part of the file.
  */
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 				struct btrfs_ordered_extent *ordered)
 {
 	struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
@@ -597,18 +618,30 @@
 	u64 disk_i_size;
 	u64 new_i_size;
 	u64 i_size_test;
+	u64 i_size = i_size_read(inode);
 	struct rb_node *node;
+	struct rb_node *prev = NULL;
 	struct btrfs_ordered_extent *test;
+	int ret = 1;
+
+	if (ordered)
+		offset = entry_end(ordered);
 
 	mutex_lock(&tree->mutex);
 	disk_i_size = BTRFS_I(inode)->disk_i_size;
 
+	/* truncate file */
+	if (disk_i_size > i_size) {
+		BTRFS_I(inode)->disk_i_size = i_size;
+		ret = 0;
+		goto out;
+	}
+
 	/*
 	 * if the disk i_size is already at the inode->i_size, or
 	 * this ordered extent is inside the disk i_size, we're done
 	 */
-	if (disk_i_size >= inode->i_size ||
-	    ordered->file_offset + ordered->len <= disk_i_size) {
+	if (disk_i_size == i_size || offset <= disk_i_size) {
 		goto out;
 	}
 
@@ -616,8 +649,7 @@
 	 * we can't update the disk_isize if there are delalloc bytes
 	 * between disk_i_size and  this ordered extent
 	 */
-	if (test_range_bit(io_tree, disk_i_size,
-			   ordered->file_offset + ordered->len - 1,
+	if (test_range_bit(io_tree, disk_i_size, offset - 1,
 			   EXTENT_DELALLOC, 0, NULL)) {
 		goto out;
 	}
@@ -626,20 +658,32 @@
 	 * if we find an ordered extent then we can't update disk i_size
 	 * yet
 	 */
-	node = &ordered->rb_node;
-	while (1) {
-		node = rb_prev(node);
-		if (!node)
-			break;
+	if (ordered) {
+		node = rb_prev(&ordered->rb_node);
+	} else {
+		prev = tree_search(tree, offset);
+		/*
+		 * we insert file extents without involving ordered struct,
+		 * so there should be no ordered struct cover this offset
+		 */
+		if (prev) {
+			test = rb_entry(prev, struct btrfs_ordered_extent,
+					rb_node);
+			BUG_ON(offset_in_entry(test, offset));
+		}
+		node = prev;
+	}
+	while (node) {
 		test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
 		if (test->file_offset + test->len <= disk_i_size)
 			break;
-		if (test->file_offset >= inode->i_size)
+		if (test->file_offset >= i_size)
 			break;
 		if (test->file_offset >= disk_i_size)
 			goto out;
+		node = rb_prev(node);
 	}
-	new_i_size = min_t(u64, entry_end(ordered), i_size_read(inode));
+	new_i_size = min_t(u64, offset, i_size);
 
 	/*
 	 * at this point, we know we can safely update i_size to at least
@@ -647,7 +691,14 @@
 	 * walk forward and see if ios from higher up in the file have
 	 * finished.
 	 */
-	node = rb_next(&ordered->rb_node);
+	if (ordered) {
+		node = rb_next(&ordered->rb_node);
+	} else {
+		if (prev)
+			node = rb_next(prev);
+		else
+			node = rb_first(&tree->tree);
+	}
 	i_size_test = 0;
 	if (node) {
 		/*
@@ -655,10 +706,10 @@
 		 * between our ordered extent and the next one.
 		 */
 		test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-		if (test->file_offset > entry_end(ordered))
+		if (test->file_offset > offset)
 			i_size_test = test->file_offset;
 	} else {
-		i_size_test = i_size_read(inode);
+		i_size_test = i_size;
 	}
 
 	/*
@@ -667,15 +718,25 @@
 	 * are no delalloc bytes in this area, it is safe to update
 	 * disk_i_size to the end of the region.
 	 */
-	if (i_size_test > entry_end(ordered) &&
-	    !test_range_bit(io_tree, entry_end(ordered), i_size_test - 1,
-			   EXTENT_DELALLOC, 0, NULL)) {
-		new_i_size = min_t(u64, i_size_test, i_size_read(inode));
+	if (i_size_test > offset &&
+	    !test_range_bit(io_tree, offset, i_size_test - 1,
+			    EXTENT_DELALLOC, 0, NULL)) {
+		new_i_size = min_t(u64, i_size_test, i_size);
 	}
 	BTRFS_I(inode)->disk_i_size = new_i_size;
+	ret = 0;
 out:
+	/*
+	 * we need to remove the ordered extent with the tree lock held
+	 * so that other people calling this function don't find our fully
+	 * processed ordered entry and skip updating the i_size
+	 */
+	if (ordered)
+		__btrfs_remove_ordered_extent(inode, ordered);
 	mutex_unlock(&tree->mutex);
-	return 0;
+	if (ordered)
+		wake_up(&ordered->wait);
+	return ret;
 }
 
 /*
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index f82e874..1fe1282 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -150,12 +150,13 @@
 int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len);
 struct btrfs_ordered_extent *
 btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset);
-int btrfs_ordered_update_i_size(struct inode *inode,
+int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 				struct btrfs_ordered_extent *ordered);
 int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum);
-int btrfs_wait_ordered_extents(struct btrfs_root *root, int nocow_only);
 int btrfs_run_ordered_operations(struct btrfs_root *root, int wait);
 int btrfs_add_ordered_operation(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
 				struct inode *inode);
+int btrfs_wait_ordered_extents(struct btrfs_root *root,
+			       int nocow_only, int delay_iput);
 #endif
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index cfcc93c..a972868 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1561,6 +1561,20 @@
 	return 0;
 }
 
+static void put_inodes(struct list_head *list)
+{
+	struct inodevec *ivec;
+	while (!list_empty(list)) {
+		ivec = list_entry(list->next, struct inodevec, list);
+		list_del(&ivec->list);
+		while (ivec->nr > 0) {
+			ivec->nr--;
+			iput(ivec->inode[ivec->nr]);
+		}
+		kfree(ivec);
+	}
+}
+
 static int find_next_key(struct btrfs_path *path, int level,
 			 struct btrfs_key *key)
 
@@ -1723,6 +1737,11 @@
 
 		btrfs_btree_balance_dirty(root, nr);
 
+		/*
+		 * put inodes outside transaction, otherwise we may deadlock.
+		 */
+		put_inodes(&inode_list);
+
 		if (replaced && rc->stage == UPDATE_DATA_PTRS)
 			invalidate_extent_cache(root, &key, &next_key);
 	}
@@ -1752,19 +1771,7 @@
 
 	btrfs_btree_balance_dirty(root, nr);
 
-	/*
-	 * put inodes while we aren't holding the tree locks
-	 */
-	while (!list_empty(&inode_list)) {
-		struct inodevec *ivec;
-		ivec = list_entry(inode_list.next, struct inodevec, list);
-		list_del(&ivec->list);
-		while (ivec->nr > 0) {
-			ivec->nr--;
-			iput(ivec->inode[ivec->nr]);
-		}
-		kfree(ivec);
-	}
+	put_inodes(&inode_list);
 
 	if (replaced && rc->stage == UPDATE_DATA_PTRS)
 		invalidate_extent_cache(root, &key, &next_key);
@@ -3534,8 +3541,8 @@
 	       (unsigned long long)rc->block_group->key.objectid,
 	       (unsigned long long)rc->block_group->flags);
 
-	btrfs_start_delalloc_inodes(fs_info->tree_root);
-	btrfs_wait_ordered_extents(fs_info->tree_root, 0);
+	btrfs_start_delalloc_inodes(fs_info->tree_root, 0);
+	btrfs_wait_ordered_extents(fs_info->tree_root, 0, 0);
 
 	while (1) {
 		rc->extents_found = 0;
@@ -3755,6 +3762,7 @@
 				       BTRFS_DATA_RELOC_TREE_OBJECTID);
 		if (IS_ERR(fs_root))
 			err = PTR_ERR(fs_root);
+		btrfs_orphan_cleanup(fs_root);
 	}
 	return err;
 }
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 752a546..3f9b457 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -128,6 +128,7 @@
 	substring_t args[MAX_OPT_ARGS];
 	char *p, *num;
 	int intarg;
+	int ret = 0;
 
 	if (!options)
 		return 0;
@@ -262,12 +263,18 @@
 		case Opt_discard:
 			btrfs_set_opt(info->mount_opt, DISCARD);
 			break;
+		case Opt_err:
+			printk(KERN_INFO "btrfs: unrecognized mount option "
+			       "'%s'\n", p);
+			ret = -EINVAL;
+			goto out;
 		default:
 			break;
 		}
 	}
+out:
 	kfree(options);
-	return 0;
+	return ret;
 }
 
 /*
@@ -405,8 +412,8 @@
 		return 0;
 	}
 
-	btrfs_start_delalloc_inodes(root);
-	btrfs_wait_ordered_extents(root, 0);
+	btrfs_start_delalloc_inodes(root, 0);
+	btrfs_wait_ordered_extents(root, 0, 0);
 
 	trans = btrfs_start_transaction(root, 1);
 	ret = btrfs_commit_transaction(trans, root);
@@ -450,6 +457,8 @@
 		seq_puts(seq, ",notreelog");
 	if (btrfs_test_opt(root, FLUSHONCOMMIT))
 		seq_puts(seq, ",flushoncommit");
+	if (btrfs_test_opt(root, DISCARD))
+		seq_puts(seq, ",discard");
 	if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
 		seq_puts(seq, ",noacl");
 	return 0;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index c207e8c..b2acc79 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -333,6 +333,9 @@
 	memset(trans, 0, sizeof(*trans));
 	kmem_cache_free(btrfs_trans_handle_cachep, trans);
 
+	if (throttle)
+		btrfs_run_delayed_iputs(root);
+
 	return 0;
 }
 
@@ -354,7 +357,7 @@
  * those extents are sent to disk but does not wait on them
  */
 int btrfs_write_marked_extents(struct btrfs_root *root,
-			       struct extent_io_tree *dirty_pages)
+			       struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int err = 0;
@@ -367,7 +370,7 @@
 
 	while (1) {
 		ret = find_first_extent_bit(dirty_pages, start, &start, &end,
-					    EXTENT_DIRTY);
+					    mark);
 		if (ret)
 			break;
 		while (start <= end) {
@@ -413,7 +416,7 @@
  * on all the pages and clear them from the dirty pages state tree
  */
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-			      struct extent_io_tree *dirty_pages)
+			      struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int err = 0;
@@ -425,12 +428,12 @@
 	unsigned long index;
 
 	while (1) {
-		ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
-					    EXTENT_DIRTY);
+		ret = find_first_extent_bit(dirty_pages, start, &start, &end,
+					    mark);
 		if (ret)
 			break;
 
-		clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
+		clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS);
 		while (start <= end) {
 			index = start >> PAGE_CACHE_SHIFT;
 			start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
@@ -460,13 +463,13 @@
  * those extents are on disk for transaction or log commit
  */
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages)
+				struct extent_io_tree *dirty_pages, int mark)
 {
 	int ret;
 	int ret2;
 
-	ret = btrfs_write_marked_extents(root, dirty_pages);
-	ret2 = btrfs_wait_marked_extents(root, dirty_pages);
+	ret = btrfs_write_marked_extents(root, dirty_pages, mark);
+	ret2 = btrfs_wait_marked_extents(root, dirty_pages, mark);
 	return ret || ret2;
 }
 
@@ -479,7 +482,8 @@
 		return filemap_write_and_wait(btree_inode->i_mapping);
 	}
 	return btrfs_write_and_wait_marked_extents(root,
-					   &trans->transaction->dirty_pages);
+					   &trans->transaction->dirty_pages,
+					   EXTENT_DIRTY);
 }
 
 /*
@@ -497,13 +501,16 @@
 {
 	int ret;
 	u64 old_root_bytenr;
+	u64 old_root_used;
 	struct btrfs_root *tree_root = root->fs_info->tree_root;
 
+	old_root_used = btrfs_root_used(&root->root_item);
 	btrfs_write_dirty_block_groups(trans, root);
 
 	while (1) {
 		old_root_bytenr = btrfs_root_bytenr(&root->root_item);
-		if (old_root_bytenr == root->node->start)
+		if (old_root_bytenr == root->node->start &&
+		    old_root_used == btrfs_root_used(&root->root_item))
 			break;
 
 		btrfs_set_root_node(&root->root_item, root->node);
@@ -512,6 +519,7 @@
 					&root->root_item);
 		BUG_ON(ret);
 
+		old_root_used = btrfs_root_used(&root->root_item);
 		ret = btrfs_write_dirty_block_groups(trans, root);
 		BUG_ON(ret);
 	}
@@ -795,7 +803,6 @@
 	memcpy(&pending->root_key, &key, sizeof(key));
 fail:
 	kfree(new_root_item);
-	btrfs_unreserve_metadata_space(root, 6);
 	return ret;
 }
 
@@ -807,7 +814,6 @@
 	u64 index = 0;
 	struct btrfs_trans_handle *trans;
 	struct inode *parent_inode;
-	struct inode *inode;
 	struct btrfs_root *parent_root;
 
 	parent_inode = pending->dentry->d_parent->d_inode;
@@ -839,8 +845,6 @@
 
 	BUG_ON(ret);
 
-	inode = btrfs_lookup_dentry(parent_inode, pending->dentry);
-	d_instantiate(pending->dentry, inode);
 fail:
 	btrfs_end_transaction(trans, fs_info->fs_root);
 	return ret;
@@ -994,11 +998,11 @@
 		mutex_unlock(&root->fs_info->trans_mutex);
 
 		if (flush_on_commit) {
-			btrfs_start_delalloc_inodes(root);
-			ret = btrfs_wait_ordered_extents(root, 0);
+			btrfs_start_delalloc_inodes(root, 1);
+			ret = btrfs_wait_ordered_extents(root, 0, 1);
 			BUG_ON(ret);
 		} else if (snap_pending) {
-			ret = btrfs_wait_ordered_extents(root, 1);
+			ret = btrfs_wait_ordered_extents(root, 0, 1);
 			BUG_ON(ret);
 		}
 
@@ -1116,6 +1120,10 @@
 		current->journal_info = NULL;
 
 	kmem_cache_free(btrfs_trans_handle_cachep, trans);
+
+	if (current != root->fs_info->transaction_kthread)
+		btrfs_run_delayed_iputs(root);
+
 	return ret;
 }
 
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index d4e3e7a..93c7ccb 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -107,10 +107,10 @@
 int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root);
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_write_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_wait_marked_extents(struct btrfs_root *root,
-					struct extent_io_tree *dirty_pages);
+				struct extent_io_tree *dirty_pages, int mark);
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 #endif
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 741666a..4a9434b 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -542,8 +542,8 @@
 
 	saved_nbytes = inode_get_bytes(inode);
 	/* drop any overlapping extents */
-	ret = btrfs_drop_extents(trans, root, inode,
-			 start, extent_end, extent_end, start, &alloc_hint, 1);
+	ret = btrfs_drop_extents(trans, inode, start, extent_end,
+				 &alloc_hint, 1);
 	BUG_ON(ret);
 
 	if (found_type == BTRFS_FILE_EXTENT_REG ||
@@ -930,6 +930,17 @@
 	return 0;
 }
 
+static int insert_orphan_item(struct btrfs_trans_handle *trans,
+			      struct btrfs_root *root, u64 offset)
+{
+	int ret;
+	ret = btrfs_find_orphan_item(root, offset);
+	if (ret > 0)
+		ret = btrfs_insert_orphan_item(trans, root, offset);
+	return ret;
+}
+
+
 /*
  * There are a few corners where the link count of the file can't
  * be properly maintained during replay.  So, instead of adding
@@ -997,9 +1008,13 @@
 	}
 	BTRFS_I(inode)->index_cnt = (u64)-1;
 
-	if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) {
-		ret = replay_dir_deletes(trans, root, NULL, path,
-					 inode->i_ino, 1);
+	if (inode->i_nlink == 0) {
+		if (S_ISDIR(inode->i_mode)) {
+			ret = replay_dir_deletes(trans, root, NULL, path,
+						 inode->i_ino, 1);
+			BUG_ON(ret);
+		}
+		ret = insert_orphan_item(trans, root, inode->i_ino);
 		BUG_ON(ret);
 	}
 	btrfs_free_path(path);
@@ -1587,7 +1602,6 @@
 		/* inode keys are done during the first stage */
 		if (key.type == BTRFS_INODE_ITEM_KEY &&
 		    wc->stage == LOG_WALK_REPLAY_INODES) {
-			struct inode *inode;
 			struct btrfs_inode_item *inode_item;
 			u32 mode;
 
@@ -1603,31 +1617,16 @@
 					     eb, i, &key);
 			BUG_ON(ret);
 
-			/* for regular files, truncate away
-			 * extents past the new EOF
+			/* for regular files, make sure corresponding
+			 * orhpan item exist. extents past the new EOF
+			 * will be truncated later by orphan cleanup.
 			 */
 			if (S_ISREG(mode)) {
-				inode = read_one_inode(root,
-						       key.objectid);
-				BUG_ON(!inode);
-
-				ret = btrfs_truncate_inode_items(wc->trans,
-					root, inode, inode->i_size,
-					BTRFS_EXTENT_DATA_KEY);
+				ret = insert_orphan_item(wc->trans, root,
+							 key.objectid);
 				BUG_ON(ret);
-
-				/* if the nlink count is zero here, the iput
-				 * will free the inode.  We bump it to make
-				 * sure it doesn't get freed until the link
-				 * count fixup is done
-				 */
-				if (inode->i_nlink == 0) {
-					btrfs_inc_nlink(inode);
-					btrfs_update_inode(wc->trans,
-							   root, inode);
-				}
-				iput(inode);
 			}
+
 			ret = link_to_fixup_dir(wc->trans, root,
 						path, key.objectid);
 			BUG_ON(ret);
@@ -1977,10 +1976,11 @@
 {
 	int index1;
 	int index2;
+	int mark;
 	int ret;
 	struct btrfs_root *log = root->log_root;
 	struct btrfs_root *log_root_tree = root->fs_info->log_root_tree;
-	u64 log_transid = 0;
+	unsigned long log_transid = 0;
 
 	mutex_lock(&root->log_mutex);
 	index1 = root->log_transid % 2;
@@ -2014,24 +2014,29 @@
 		goto out;
 	}
 
+	log_transid = root->log_transid;
+	if (log_transid % 2 == 0)
+		mark = EXTENT_DIRTY;
+	else
+		mark = EXTENT_NEW;
+
 	/* we start IO on  all the marked extents here, but we don't actually
 	 * wait for them until later.
 	 */
-	ret = btrfs_write_marked_extents(log, &log->dirty_log_pages);
+	ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);
 	BUG_ON(ret);
 
 	btrfs_set_root_node(&log->root_item, log->node);
 
 	root->log_batch = 0;
-	log_transid = root->log_transid;
 	root->log_transid++;
 	log->log_transid = root->log_transid;
 	root->log_start_pid = 0;
 	smp_mb();
 	/*
-	 * log tree has been flushed to disk, new modifications of
-	 * the log will be written to new positions. so it's safe to
-	 * allow log writers to go in.
+	 * IO has been started, blocks of the log tree have WRITTEN flag set
+	 * in their headers. new modifications of the log will be written to
+	 * new positions. so it's safe to allow log writers to go in.
 	 */
 	mutex_unlock(&root->log_mutex);
 
@@ -2052,7 +2057,7 @@
 
 	index2 = log_root_tree->log_transid % 2;
 	if (atomic_read(&log_root_tree->log_commit[index2])) {
-		btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 		wait_log_commit(trans, log_root_tree,
 				log_root_tree->log_transid);
 		mutex_unlock(&log_root_tree->log_mutex);
@@ -2072,16 +2077,17 @@
 	 * check the full commit flag again
 	 */
 	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
-		btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+		btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 		mutex_unlock(&log_root_tree->log_mutex);
 		ret = -EAGAIN;
 		goto out_wake_log_root;
 	}
 
 	ret = btrfs_write_and_wait_marked_extents(log_root_tree,
-				&log_root_tree->dirty_log_pages);
+				&log_root_tree->dirty_log_pages,
+				EXTENT_DIRTY | EXTENT_NEW);
 	BUG_ON(ret);
-	btrfs_wait_marked_extents(log, &log->dirty_log_pages);
+	btrfs_wait_marked_extents(log, &log->dirty_log_pages, mark);
 
 	btrfs_set_super_log_root(&root->fs_info->super_for_commit,
 				log_root_tree->node->start);
@@ -2147,12 +2153,12 @@
 
 	while (1) {
 		ret = find_first_extent_bit(&log->dirty_log_pages,
-				    0, &start, &end, EXTENT_DIRTY);
+				0, &start, &end, EXTENT_DIRTY | EXTENT_NEW);
 		if (ret)
 			break;
 
-		clear_extent_dirty(&log->dirty_log_pages,
-				   start, end, GFP_NOFS);
+		clear_extent_bits(&log->dirty_log_pages, start, end,
+				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
 	}
 
 	if (log->log_transid > 0) {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 7eda483..198cff2 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2209,7 +2209,7 @@
 		max_chunk_size = 10 * calc_size;
 		min_stripe_size = 64 * 1024 * 1024;
 	} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-		max_chunk_size = 4 * calc_size;
+		max_chunk_size = 256 * 1024 * 1024;
 		min_stripe_size = 32 * 1024 * 1024;
 	} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
 		calc_size = 8 * 1024 * 1024;
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index b6dd596..193b58f 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -85,22 +85,23 @@
 	return ret;
 }
 
-int __btrfs_setxattr(struct inode *inode, const char *name,
-			    const void *value, size_t size, int flags)
+static int do_setxattr(struct btrfs_trans_handle *trans,
+		       struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
 {
 	struct btrfs_dir_item *di;
 	struct btrfs_root *root = BTRFS_I(inode)->root;
-	struct btrfs_trans_handle *trans;
 	struct btrfs_path *path;
-	int ret = 0, mod = 0;
+	size_t name_len = strlen(name);
+	int ret = 0;
+
+	if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
+		return -ENOSPC;
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
 
-	trans = btrfs_join_transaction(root, 1);
-	btrfs_set_trans_block_group(trans, inode);
-
 	/* first lets see if we already have this xattr */
 	di = btrfs_lookup_xattr(trans, root, path, inode->i_ino, name,
 				strlen(name), -1);
@@ -118,15 +119,12 @@
 		}
 
 		ret = btrfs_delete_one_dir_name(trans, root, path, di);
-		if (ret)
-			goto out;
+		BUG_ON(ret);
 		btrfs_release_path(root, path);
 
 		/* if we don't have a value then we are removing the xattr */
-		if (!value) {
-			mod = 1;
+		if (!value)
 			goto out;
-		}
 	} else {
 		btrfs_release_path(root, path);
 
@@ -138,20 +136,45 @@
 	}
 
 	/* ok we have to create a completely new xattr */
-	ret = btrfs_insert_xattr_item(trans, root, name, strlen(name),
-				      value, size, inode->i_ino);
+	ret = btrfs_insert_xattr_item(trans, root, path, inode->i_ino,
+				      name, name_len, value, size);
+	BUG_ON(ret);
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
+int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+		     struct inode *inode, const char *name,
+		     const void *value, size_t size, int flags)
+{
+	struct btrfs_root *root = BTRFS_I(inode)->root;
+	int ret;
+
+	if (trans)
+		return do_setxattr(trans, inode, name, value, size, flags);
+
+	ret = btrfs_reserve_metadata_space(root, 2);
+	if (ret)
+		return ret;
+
+	trans = btrfs_start_transaction(root, 1);
+	if (!trans) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	btrfs_set_trans_block_group(trans, inode);
+
+	ret = do_setxattr(trans, inode, name, value, size, flags);
 	if (ret)
 		goto out;
-	mod = 1;
 
+	inode->i_ctime = CURRENT_TIME;
+	ret = btrfs_update_inode(trans, root, inode);
+	BUG_ON(ret);
 out:
-	if (mod) {
-		inode->i_ctime = CURRENT_TIME;
-		ret = btrfs_update_inode(trans, root, inode);
-	}
-
-	btrfs_end_transaction(trans, root);
-	btrfs_free_path(path);
+	btrfs_end_transaction_throttle(trans, root);
+	btrfs_unreserve_metadata_space(root, 2);
 	return ret;
 }
 
@@ -314,7 +337,9 @@
 
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
-	return __btrfs_setxattr(dentry->d_inode, name, value, size, flags);
+
+	return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
+				flags);
 }
 
 int btrfs_removexattr(struct dentry *dentry, const char *name)
@@ -329,10 +354,13 @@
 
 	if (!btrfs_is_valid_xattr(name))
 		return -EOPNOTSUPP;
-	return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
+
+	return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
+				XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct inode *inode, struct inode *dir)
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+			      struct inode *inode, struct inode *dir)
 {
 	int err;
 	size_t len;
@@ -354,7 +382,7 @@
 	} else {
 		strcpy(name, XATTR_SECURITY_PREFIX);
 		strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-		err = __btrfs_setxattr(inode, name, value, len, 0);
+		err = __btrfs_setxattr(trans, inode, name, value, len, 0);
 		kfree(name);
 	}
 
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index c71e9c3..721efa0 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -27,15 +27,16 @@
 
 extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
 		void *buffer, size_t size);
-extern int __btrfs_setxattr(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags);
-
+extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
+			    struct inode *inode, const char *name,
+			    const void *value, size_t size, int flags);
 extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
 		void *buffer, size_t size);
 extern int btrfs_setxattr(struct dentry *dentry, const char *name,
 		const void *value, size_t size, int flags);
 extern int btrfs_removexattr(struct dentry *dentry, const char *name);
 
-extern int btrfs_xattr_security_init(struct inode *inode, struct inode *dir);
+extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+				     struct inode *inode, struct inode *dir);
 
 #endif /* __XATTR__ */
diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 3797e00..2906077 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -84,7 +84,7 @@
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 {
 	struct cachefiles_object *fsdef;
-	struct nameidata nd;
+	struct path path;
 	struct kstatfs stats;
 	struct dentry *graveyard, *cachedir, *root;
 	const struct cred *saved_cred;
@@ -114,15 +114,12 @@
 	_debug("- fsdef %p", fsdef);
 
 	/* look up the directory at the root of the cache */
-	memset(&nd, 0, sizeof(nd));
-
-	ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd);
+	ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path);
 	if (ret < 0)
 		goto error_open_root;
 
-	cache->mnt = mntget(nd.path.mnt);
-	root = dget(nd.path.dentry);
-	path_put(&nd.path);
+	cache->mnt = path.mnt;
+	root = path.dentry;
 
 	/* check parameters */
 	ret = -EOPNOTSUPP;
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c
index a6c8c6f..1d83325 100644
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -11,7 +11,6 @@
 
 #include <linux/mount.h>
 #include <linux/file.h>
-#include <linux/ima.h>
 #include "internal.h"
 
 /*
@@ -923,7 +922,6 @@
 	if (IS_ERR(file)) {
 		ret = PTR_ERR(file);
 	} else {
-		ima_counts_get(file);
 		ret = -EIO;
 		if (file->f_op->write) {
 			pos = (loff_t) page->index << PAGE_SHIFT;
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
index 75949d6..6177f7c 100644
--- a/fs/cifs/export.c
+++ b/fs/cifs/export.c
@@ -24,7 +24,7 @@
  */
 
  /*
-  * See Documentation/filesystems/Exporting
+  * See Documentation/filesystems/nfs/Exporting
   * and examples in fs/exportfs
   *
   * Since cifs is a network file system, an "fsid" must be included for
diff --git a/fs/compat.c b/fs/compat.c
index 6c19040..00d90c2 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -38,8 +38,6 @@
 #include <linux/dirent.h>
 #include <linux/fsnotify.h>
 #include <linux/highuid.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
 #include <linux/rwsem.h>
diff --git a/fs/dcache.c b/fs/dcache.c
index a100fa3..953173a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -978,6 +978,7 @@
 	q.hash = full_name_hash(q.name, q.len);
 	return d_alloc(parent, &q);
 }
+EXPORT_SYMBOL(d_alloc_name);
 
 /* the caller must hold dcache_lock */
 static void __d_instantiate(struct dentry *dentry, struct inode *inode)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b912270..e82adc2 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -53,13 +53,6 @@
  *
  * If blkfactor is zero then the user's request was aligned to the filesystem's
  * blocksize.
- *
- * lock_type is DIO_LOCKING for regular files on direct-IO-naive filesystems.
- * This determines whether we need to do the fancy locking which prevents
- * direct-IO from being able to read uninitialised disk blocks.  If its zero
- * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_mutex is
- * not held for the entire direct write (taken briefly, initially, during a
- * direct read though, but its never held for the duration of a direct-IO).
  */
 
 struct dio {
@@ -68,7 +61,7 @@
 	struct inode *inode;
 	int rw;
 	loff_t i_size;			/* i_size when submitted */
-	int lock_type;			/* doesn't change */
+	int flags;			/* doesn't change */
 	unsigned blkbits;		/* doesn't change */
 	unsigned blkfactor;		/* When we're using an alignment which
 					   is finer than the filesystem's soft
@@ -104,22 +97,6 @@
 	unsigned cur_page_len;		/* Nr of bytes at cur_page_offset */
 	sector_t cur_page_block;	/* Where it starts */
 
-	/*
-	 * Page fetching state. These variables belong to dio_refill_pages().
-	 */
-	int curr_page;			/* changes */
-	int total_pages;		/* doesn't change */
-	unsigned long curr_user_address;/* changes */
-
-	/*
-	 * Page queue.  These variables belong to dio_refill_pages() and
-	 * dio_get_page().
-	 */
-	struct page *pages[DIO_PAGES];	/* page buffer */
-	unsigned head;			/* next page to process */
-	unsigned tail;			/* last valid page + 1 */
-	int page_errors;		/* errno from get_user_pages() */
-
 	/* BIO completion state */
 	spinlock_t bio_lock;		/* protects BIO fields below */
 	unsigned long refcount;		/* direct_io_worker() and bios */
@@ -131,6 +108,28 @@
 	int is_async;			/* is IO async ? */
 	int io_error;			/* IO error in completion path */
 	ssize_t result;                 /* IO result */
+
+	/*
+	 * Page fetching state. These variables belong to dio_refill_pages().
+	 */
+	int curr_page;			/* changes */
+	int total_pages;		/* doesn't change */
+	unsigned long curr_user_address;/* changes */
+
+	/*
+	 * Page queue.  These variables belong to dio_refill_pages() and
+	 * dio_get_page().
+	 */
+	unsigned head;			/* next page to process */
+	unsigned tail;			/* last valid page + 1 */
+	int page_errors;		/* errno from get_user_pages() */
+
+	/*
+	 * pages[] (and any fields placed after it) are not zeroed out at
+	 * allocation time.  Don't add new fields after pages[] unless you
+	 * wish that they not be zeroed.
+	 */
+	struct page *pages[DIO_PAGES];	/* page buffer */
 };
 
 /*
@@ -240,7 +239,8 @@
 	if (dio->end_io && dio->result)
 		dio->end_io(dio->iocb, offset, transferred,
 			    dio->map_bh.b_private);
-	if (dio->lock_type == DIO_LOCKING)
+
+	if (dio->flags & DIO_LOCKING)
 		/* lockdep: non-owner release */
 		up_read_non_owner(&dio->inode->i_alloc_sem);
 
@@ -515,21 +515,24 @@
 		map_bh->b_state = 0;
 		map_bh->b_size = fs_count << dio->inode->i_blkbits;
 
+		/*
+		 * For writes inside i_size on a DIO_SKIP_HOLES filesystem we
+		 * forbid block creations: only overwrites are permitted.
+		 * We will return early to the caller once we see an
+		 * unmapped buffer head returned, and the caller will fall
+		 * back to buffered I/O.
+		 *
+		 * Otherwise the decision is left to the get_blocks method,
+		 * which may decide to handle it or also return an unmapped
+		 * buffer head.
+		 */
 		create = dio->rw & WRITE;
-		if (dio->lock_type == DIO_LOCKING) {
+		if (dio->flags & DIO_SKIP_HOLES) {
 			if (dio->block_in_file < (i_size_read(dio->inode) >>
 							dio->blkbits))
 				create = 0;
-		} else if (dio->lock_type == DIO_NO_LOCKING) {
-			create = 0;
 		}
 
-		/*
-		 * For writes inside i_size we forbid block creations: only
-		 * overwrites are permitted.  We fall back to buffered writes
-		 * at a higher level for inside-i_size block-instantiating
-		 * writes.
-		 */
 		ret = (*dio->get_block)(dio->inode, fs_startblk,
 						map_bh, create);
 	}
@@ -1039,7 +1042,7 @@
 	 * we can let i_mutex go now that its achieved its purpose
 	 * of protecting us from looking up uninitialized blocks.
 	 */
-	if ((rw == READ) && (dio->lock_type == DIO_LOCKING))
+	if (rw == READ && (dio->flags & DIO_LOCKING))
 		mutex_unlock(&dio->inode->i_mutex);
 
 	/*
@@ -1086,30 +1089,28 @@
 
 /*
  * This is a library function for use by filesystem drivers.
- * The locking rules are governed by the dio_lock_type parameter.
  *
- * DIO_NO_LOCKING (no locking, for raw block device access)
- * For writes, i_mutex is not held on entry; it is never taken.
+ * The locking rules are governed by the flags parameter:
+ *  - if the flags value contains DIO_LOCKING we use a fancy locking
+ *    scheme for dumb filesystems.
+ *    For writes this function is called under i_mutex and returns with
+ *    i_mutex held, for reads, i_mutex is not held on entry, but it is
+ *    taken and dropped again before returning.
+ *    For reads and writes i_alloc_sem is taken in shared mode and released
+ *    on I/O completion (which may happen asynchronously after returning to
+ *    the caller).
  *
- * DIO_LOCKING (simple locking for regular files)
- * For writes we are called under i_mutex and return with i_mutex held, even
- * though it is internally dropped.
- * For reads, i_mutex is not held on entry, but it is taken and dropped before
- * returning.
- *
- * DIO_OWN_LOCKING (filesystem provides synchronisation and handling of
- *	uninitialised data, allowing parallel direct readers and writers)
- * For writes we are called without i_mutex, return without it, never touch it.
- * For reads we are called under i_mutex and return with i_mutex held, even
- * though it may be internally dropped.
- *
- * Additional i_alloc_sem locking requirements described inline below.
+ *  - if the flags value does NOT contain DIO_LOCKING we don't use any
+ *    internal locking but rather rely on the filesystem to synchronize
+ *    direct I/O reads/writes versus each other and truncate.
+ *    For reads and writes both i_mutex and i_alloc_sem are not held on
+ *    entry and are never taken.
  */
 ssize_t
 __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
 	unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
-	int dio_lock_type)
+	int flags)
 {
 	int seg;
 	size_t size;
@@ -1120,8 +1121,6 @@
 	ssize_t retval = -EINVAL;
 	loff_t end = offset;
 	struct dio *dio;
-	int release_i_mutex = 0;
-	int acquire_i_mutex = 0;
 
 	if (rw & WRITE)
 		rw = WRITE_ODIRECT_PLUG;
@@ -1151,48 +1150,41 @@
 		}
 	}
 
-	dio = kzalloc(sizeof(*dio), GFP_KERNEL);
+	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
 	retval = -ENOMEM;
 	if (!dio)
 		goto out;
-
 	/*
-	 * For block device access DIO_NO_LOCKING is used,
-	 *	neither readers nor writers do any locking at all
-	 * For regular files using DIO_LOCKING,
-	 *	readers need to grab i_mutex and i_alloc_sem
-	 *	writers need to grab i_alloc_sem only (i_mutex is already held)
-	 * For regular files using DIO_OWN_LOCKING,
-	 *	neither readers nor writers take any locks here
+	 * Believe it or not, zeroing out the page array caused a .5%
+	 * performance regression in a database benchmark.  So, we take
+	 * care to only zero out what's needed.
 	 */
-	dio->lock_type = dio_lock_type;
-	if (dio_lock_type != DIO_NO_LOCKING) {
+	memset(dio, 0, offsetof(struct dio, pages));
+
+	dio->flags = flags;
+	if (dio->flags & DIO_LOCKING) {
 		/* watch out for a 0 len io from a tricksy fs */
 		if (rw == READ && end > offset) {
-			struct address_space *mapping;
+			struct address_space *mapping =
+					iocb->ki_filp->f_mapping;
 
-			mapping = iocb->ki_filp->f_mapping;
-			if (dio_lock_type != DIO_OWN_LOCKING) {
-				mutex_lock(&inode->i_mutex);
-				release_i_mutex = 1;
-			}
+			/* will be released by direct_io_worker */
+			mutex_lock(&inode->i_mutex);
 
 			retval = filemap_write_and_wait_range(mapping, offset,
 							      end - 1);
 			if (retval) {
+				mutex_unlock(&inode->i_mutex);
 				kfree(dio);
 				goto out;
 			}
-
-			if (dio_lock_type == DIO_OWN_LOCKING) {
-				mutex_unlock(&inode->i_mutex);
-				acquire_i_mutex = 1;
-			}
 		}
 
-		if (dio_lock_type == DIO_LOCKING)
-			/* lockdep: not the owner will release it */
-			down_read_non_owner(&inode->i_alloc_sem);
+		/*
+		 * Will be released at I/O completion, possibly in a
+		 * different thread.
+		 */
+		down_read_non_owner(&inode->i_alloc_sem);
 	}
 
 	/*
@@ -1210,24 +1202,19 @@
 	/*
 	 * In case of error extending write may have instantiated a few
 	 * blocks outside i_size. Trim these off again for DIO_LOCKING.
-	 * NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this by
-	 * it's own meaner.
+	 *
+	 * NOTE: filesystems with their own locking have to handle this
+	 * on their own.
 	 */
-	if (unlikely(retval < 0 && (rw & WRITE))) {
-		loff_t isize = i_size_read(inode);
-
-		if (end > isize && dio_lock_type == DIO_LOCKING)
-			vmtruncate(inode, isize);
+	if (flags & DIO_LOCKING) {
+		if (unlikely((rw & WRITE) && retval < 0)) {
+			loff_t isize = i_size_read(inode);
+			if (end > isize)
+				vmtruncate(inode, isize);
+		}
 	}
 
-	if (rw == READ && dio_lock_type == DIO_LOCKING)
-		release_i_mutex = 0;
-
 out:
-	if (release_i_mutex)
-		mutex_unlock(&inode->i_mutex);
-	else if (acquire_i_mutex)
-		mutex_lock(&inode->i_mutex);
 	return retval;
 }
 EXPORT_SYMBOL(__blockdev_direct_IO);
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c
index 2dda5ad..8f006a0 100644
--- a/fs/ecryptfs/dentry.c
+++ b/fs/ecryptfs/dentry.c
@@ -62,7 +62,7 @@
 		struct inode *lower_inode =
 			ecryptfs_inode_to_lower(dentry->d_inode);
 
-		fsstack_copy_attr_all(dentry->d_inode, lower_inode, NULL);
+		fsstack_copy_attr_all(dentry->d_inode, lower_inode);
 	}
 out:
 	return rc;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 056fed62..429ca0b 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -626,9 +626,9 @@
 			lower_new_dir_dentry->d_inode, lower_new_dentry);
 	if (rc)
 		goto out_lock;
-	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
+	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
 	if (new_dir != old_dir)
-		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode, NULL);
+		fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 out_lock:
 	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
 	dput(lower_new_dentry->d_parent);
@@ -967,7 +967,7 @@
 	rc = notify_change(lower_dentry, ia);
 	mutex_unlock(&lower_dentry->d_inode->i_mutex);
 out:
-	fsstack_copy_attr_all(inode, lower_inode, NULL);
+	fsstack_copy_attr_all(inode, lower_inode);
 	return rc;
 }
 
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index c6ac85d..567bc4b 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -35,7 +35,6 @@
 #include <linux/key.h>
 #include <linux/parser.h>
 #include <linux/fs_stack.h>
-#include <linux/ima.h>
 #include "ecryptfs_kernel.h"
 
 /**
@@ -119,7 +118,6 @@
 	const struct cred *cred = current_cred();
 	struct ecryptfs_inode_info *inode_info =
 		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-	int opened_lower_file = 0;
 	int rc = 0;
 
 	mutex_lock(&inode_info->lower_file_mutex);
@@ -136,12 +134,9 @@
 			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
 			       "rc = [%d]\n", lower_dentry, lower_mnt, rc);
 			inode_info->lower_file = NULL;
-		} else
-			opened_lower_file = 1;
+		}
 	}
 	mutex_unlock(&inode_info->lower_file_mutex);
-	if (opened_lower_file)
-		ima_counts_get(inode_info->lower_file);
 	return rc;
 }
 
@@ -194,7 +189,7 @@
 		init_special_inode(inode, lower_inode->i_mode,
 				   lower_inode->i_rdev);
 	dentry->d_op = &ecryptfs_dops;
-	fsstack_copy_attr_all(inode, lower_inode, NULL);
+	fsstack_copy_attr_all(inode, lower_inode);
 	/* This size will be overwritten for real files w/ headers and
 	 * other metadata */
 	fsstack_copy_inode_size(inode, lower_inode);
diff --git a/fs/exec.c b/fs/exec.c
index 623a5cc..632b02e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -826,7 +826,9 @@
 		attach_pid(tsk, PIDTYPE_PID,  task_pid(leader));
 		transfer_pid(leader, tsk, PIDTYPE_PGID);
 		transfer_pid(leader, tsk, PIDTYPE_SID);
+
 		list_replace_rcu(&leader->tasks, &tsk->tasks);
+		list_replace_init(&leader->sibling, &tsk->sibling);
 
 		tsk->group_leader = tsk;
 		leader->group_leader = tsk;
@@ -1761,17 +1763,20 @@
 	struct mm_struct *mm = current->mm;
 	struct linux_binfmt * binfmt;
 	struct inode * inode;
-	struct file * file;
 	const struct cred *old_cred;
 	struct cred *cred;
 	int retval = 0;
 	int flag = 0;
 	int ispipe = 0;
-	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
 	char **helper_argv = NULL;
 	int helper_argc = 0;
 	int dump_count = 0;
 	static atomic_t core_dump_count = ATOMIC_INIT(0);
+	struct coredump_params cprm = {
+		.signr = signr,
+		.regs = regs,
+		.limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+	};
 
 	audit_core_dumps(signr);
 
@@ -1827,15 +1832,15 @@
 	ispipe = format_corename(corename, signr);
 	unlock_kernel();
 
-	if ((!ispipe) && (core_limit < binfmt->min_coredump))
+	if ((!ispipe) && (cprm.limit < binfmt->min_coredump))
 		goto fail_unlock;
 
  	if (ispipe) {
-		if (core_limit == 0) {
+		if (cprm.limit == 0) {
 			/*
 			 * Normally core limits are irrelevant to pipes, since
 			 * we're not writing to the file system, but we use
-			 * core_limit of 0 here as a speacial value. Any
+			 * cprm.limit of 0 here as a speacial value. Any
 			 * non-zero limit gets set to RLIM_INFINITY below, but
 			 * a limit of 0 skips the dump.  This is a consistent
 			 * way to catch recursive crashes.  We can still crash
@@ -1868,25 +1873,25 @@
 			goto fail_dropcount;
 		}
 
-		core_limit = RLIM_INFINITY;
+		cprm.limit = RLIM_INFINITY;
 
 		/* SIGPIPE can happen, but it's just never processed */
 		if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL,
-				&file)) {
+				&cprm.file)) {
  			printk(KERN_INFO "Core dump to %s pipe failed\n",
 			       corename);
 			goto fail_dropcount;
  		}
  	} else
- 		file = filp_open(corename,
+		cprm.file = filp_open(corename,
 				 O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
 				 0600);
-	if (IS_ERR(file))
+	if (IS_ERR(cprm.file))
 		goto fail_dropcount;
-	inode = file->f_path.dentry->d_inode;
+	inode = cprm.file->f_path.dentry->d_inode;
 	if (inode->i_nlink > 1)
 		goto close_fail;	/* multiple links - don't dump */
-	if (!ispipe && d_unhashed(file->f_path.dentry))
+	if (!ispipe && d_unhashed(cprm.file->f_path.dentry))
 		goto close_fail;
 
 	/* AK: actually i see no reason to not allow this for named pipes etc.,
@@ -1899,21 +1904,22 @@
 	 */
 	if (inode->i_uid != current_fsuid())
 		goto close_fail;
-	if (!file->f_op)
+	if (!cprm.file->f_op)
 		goto close_fail;
-	if (!file->f_op->write)
+	if (!cprm.file->f_op->write)
 		goto close_fail;
-	if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
+	if (!ispipe &&
+	    do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0)
 		goto close_fail;
 
-	retval = binfmt->core_dump(signr, regs, file, core_limit);
+	retval = binfmt->core_dump(&cprm);
 
 	if (retval)
 		current->signal->group_exit_code |= 0x80;
 close_fail:
 	if (ispipe && core_pipe_limit)
-		wait_for_dump_helpers(file);
-	filp_close(file, NULL);
+		wait_for_dump_helpers(cprm.file);
+	filp_close(cprm.file, NULL);
 fail_dropcount:
 	if (dump_count)
 		atomic_dec(&core_dump_count);
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 197c7db..e9e1759 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -6,7 +6,7 @@
  * and for mapping back from file handles to dentries.
  *
  * For details on why we do all the strange and hairy things in here
- * take a look at Documentation/filesystems/Exporting.
+ * take a look at Documentation/filesystems/nfs/Exporting.
  */
 #include <linux/exportfs.h>
 #include <linux/fs.h>
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index a63d442..a99e543 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -339,12 +339,12 @@
  * Extended attribut handlers
  */
 static size_t
-ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
-			   const char *name, size_t name_len)
+ext2_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_size,
+			   const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_size)
 		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -352,12 +352,12 @@
 }
 
 static size_t
-ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
-			    const char *name, size_t name_len)
+ext2_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_size,
+			    const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_size)
 		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -365,15 +365,18 @@
 }
 
 static int
-ext2_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext2_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+		   size_t size, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
 
-	acl = ext2_get_acl(inode, type);
+	acl = ext2_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -385,33 +388,17 @@
 }
 
 static int
-ext2_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext2_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext2_xattr_set_acl(struct inode *inode, int type, const void *value,
-		   size_t size)
+ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+		   size_t size, int flags, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
-	if (!is_owner_or_cap(inode))
+	if (!is_owner_or_cap(dentry->d_inode))
 		return -EPERM;
 
 	if (value) {
@@ -426,41 +413,25 @@
 	} else
 		acl = NULL;
 
-	error = ext2_set_acl(inode, type, acl);
+	error = ext2_set_acl(dentry->d_inode, type, acl);
 
 release_and_out:
 	posix_acl_release(acl);
 	return error;
 }
 
-static int
-ext2_xattr_set_acl_access(struct inode *inode, const char *name,
-			  const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext2_xattr_set_acl_default(struct inode *inode, const char *name,
-			   const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext2_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
 	.list	= ext2_xattr_list_acl_access,
-	.get	= ext2_xattr_get_acl_access,
-	.set	= ext2_xattr_set_acl_access,
+	.get	= ext2_xattr_get_acl,
+	.set	= ext2_xattr_set_acl,
 };
 
 struct xattr_handler ext2_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= ext2_xattr_list_acl_default,
-	.get	= ext2_xattr_get_acl_default,
-	.set	= ext2_xattr_set_acl_default,
+	.get	= ext2_xattr_get_acl,
+	.set	= ext2_xattr_set_acl,
 };
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index fc2bd05..7516957 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -721,5 +721,5 @@
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
-	.fsync		= simple_fsync,
+	.fsync		= ext2_fsync,
 };
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index da318b0..061914a 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -155,6 +155,7 @@
 extern const struct file_operations ext2_dir_operations;
 
 /* file.c */
+extern int ext2_fsync(struct file *file, struct dentry *dentry, int datasync);
 extern const struct inode_operations ext2_file_inode_operations;
 extern const struct file_operations ext2_file_operations;
 extern const struct file_operations ext2_xip_file_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index a2f3afd..586e358 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/time.h>
+#include <linux/pagemap.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -38,6 +39,22 @@
 	return 0;
 }
 
+int ext2_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	int ret;
+	struct super_block *sb = dentry->d_inode->i_sb;
+	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+
+	ret = simple_fsync(file, dentry, datasync);
+	if (ret == -EIO || test_and_clear_bit(AS_EIO, &mapping->flags)) {
+		/* We don't really know where the IO error happened... */
+		ext2_error(sb, __func__,
+			   "detected IO error when writing metadata buffers");
+		ret = -EIO;
+	}
+	return ret;
+}
+
 /*
  * We have mostly NULL's here: the current defaults are ok for
  * the ext2 filesystem.
@@ -55,7 +72,7 @@
 	.mmap		= generic_file_mmap,
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
-	.fsync		= simple_fsync,
+	.fsync		= ext2_fsync,
 	.splice_read	= generic_file_splice_read,
 	.splice_write	= generic_file_splice_write,
 };
@@ -72,7 +89,7 @@
 	.mmap		= xip_file_mmap,
 	.open		= generic_file_open,
 	.release	= ext2_release_file,
-	.fsync		= simple_fsync,
+	.fsync		= ext2_fsync,
 };
 #endif
 
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 1388802..f9cb54a 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1105,9 +1105,30 @@
 	return ret;
 }
 
+static void ext2_clear_super_error(struct super_block *sb)
+{
+	struct buffer_head *sbh = EXT2_SB(sb)->s_sbh;
+
+	if (buffer_write_io_error(sbh)) {
+		/*
+		 * Oh, dear.  A previous attempt to write the
+		 * superblock failed.  This could happen because the
+		 * USB device was yanked out.  Or it could happen to
+		 * be a transient write error and maybe the block will
+		 * be remapped.  Nothing we can do but to retry the
+		 * write and hope for the best.
+		 */
+		printk(KERN_ERR "EXT2-fs: %s previous I/O error to "
+		       "superblock detected", sb->s_id);
+		clear_buffer_write_io_error(sbh);
+		set_buffer_uptodate(sbh);
+	}
+}
+
 static void ext2_commit_super (struct super_block * sb,
 			       struct ext2_super_block * es)
 {
+	ext2_clear_super_error(sb);
 	es->s_wtime = cpu_to_le32(get_seconds());
 	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
 	sb->s_dirt = 0;
@@ -1115,6 +1136,7 @@
 
 static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
 {
+	ext2_clear_super_error(sb);
 	es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb));
 	es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb));
 	es->s_wtime = cpu_to_le32(get_seconds());
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 7913531..904f006 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -60,6 +60,7 @@
 #include <linux/mbcache.h>
 #include <linux/quotaops.h>
 #include <linux/rwsem.h>
+#include <linux/security.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
@@ -249,8 +250,9 @@
  * used / required on success.
  */
 static int
-ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct inode *inode = dentry->d_inode;
 	struct buffer_head *bh = NULL;
 	struct ext2_xattr_entry *entry;
 	char *end;
@@ -300,9 +302,10 @@
 			ext2_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(inode, buffer, rest,
+			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
-						    entry->e_name_len);
+						    entry->e_name_len,
+						    handler->flags);
 			if (buffer) {
 				if (size > rest) {
 					error = -ERANGE;
@@ -330,7 +333,7 @@
 ssize_t
 ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-	return ext2_xattr_list(dentry->d_inode, buffer, size);
+	return ext2_xattr_list(dentry, buffer, size);
 }
 
 /*
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 70c0dbd..c815584 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -11,8 +11,8 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-			 const char *name, size_t name_len)
+ext2_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+			 const char *name, size_t name_len, int type)
 {
 	const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -26,22 +26,22 @@
 }
 
 static int
-ext2_xattr_security_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext2_xattr_security_get(struct dentry *dentry, const char *name,
+		       void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_security_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext2_xattr_security_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
+	return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_SECURITY, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index e8219f8..2a26d71 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -13,8 +13,8 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-			const char *name, size_t name_len)
+ext2_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -31,22 +31,22 @@
 }
 
 static int
-ext2_xattr_trusted_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext2_xattr_trusted_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      buffer, size);
 }
 
 static int
-ext2_xattr_trusted_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext2_xattr_trusted_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+	return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index 92495d2..3f6caf3 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -12,13 +12,13 @@
 #include "xattr.h"
 
 static size_t
-ext2_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-		     const char *name, size_t name_len)
+ext2_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -30,27 +30,28 @@
 }
 
 static int
-ext2_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+ext2_xattr_user_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size);
+	return ext2_xattr_get(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+			      name, buffer, size);
 }
 
 static int
-ext2_xattr_user_set(struct inode *inode, const char *name,
-		    const void *value, size_t size, int flags)
+ext2_xattr_user_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
 
-	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
-			      value, size, flags);
+	return ext2_xattr_set(dentry->d_inode, EXT2_XATTR_INDEX_USER,
+			      name, value, size, flags);
 }
 
 struct xattr_handler ext2_xattr_user_handler = {
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index c9b0df3..82ba341 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -366,12 +366,12 @@
  * Extended attribute handlers
  */
 static size_t
-ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-			   const char *name, size_t name_len)
+ext3_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
+			   const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
 		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -379,12 +379,12 @@
 }
 
 static size_t
-ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-			    const char *name, size_t name_len)
+ext3_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
+			    const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
 		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -392,15 +392,18 @@
 }
 
 static int
-ext3_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext3_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+		   size_t size, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
 
-	acl = ext3_get_acl(inode, type);
+	acl = ext3_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -412,31 +415,16 @@
 }
 
 static int
-ext3_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
+ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+		   size_t size, int flags, int type)
 {
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext3_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext3_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext3_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
-		   size_t size)
-{
+	struct inode *inode = dentry->d_inode;
 	handle_t *handle;
 	struct posix_acl *acl;
 	int error, retries = 0;
 
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
 	if (!is_owner_or_cap(inode))
@@ -468,34 +456,18 @@
 	return error;
 }
 
-static int
-ext3_xattr_set_acl_access(struct inode *inode, const char *name,
-			  const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext3_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext3_xattr_set_acl_default(struct inode *inode, const char *name,
-			   const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext3_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext3_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
 	.list	= ext3_xattr_list_acl_access,
-	.get	= ext3_xattr_get_acl_access,
-	.set	= ext3_xattr_set_acl_access,
+	.get	= ext3_xattr_get_acl,
+	.set	= ext3_xattr_set_acl,
 };
 
 struct xattr_handler ext3_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= ext3_xattr_list_acl_default,
-	.get	= ext3_xattr_get_acl_default,
-	.set	= ext3_xattr_set_acl_default,
+	.get	= ext3_xattr_get_acl,
+	.set	= ext3_xattr_set_acl,
 };
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 387d92d..66895cc 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -99,7 +99,7 @@
 						 struct mb_cache_entry **);
 static void ext3_xattr_rehash(struct ext3_xattr_header *,
 			      struct ext3_xattr_entry *);
-static int ext3_xattr_list(struct inode *inode, char *buffer,
+static int ext3_xattr_list(struct dentry *dentry, char *buffer,
 			   size_t buffer_size);
 
 static struct mb_cache *ext3_xattr_cache;
@@ -147,7 +147,7 @@
 ssize_t
 ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-	return ext3_xattr_list(dentry->d_inode, buffer, size);
+	return ext3_xattr_list(dentry, buffer, size);
 }
 
 static int
@@ -332,7 +332,7 @@
 }
 
 static int
-ext3_xattr_list_entries(struct inode *inode, struct ext3_xattr_entry *entry,
+ext3_xattr_list_entries(struct dentry *dentry, struct ext3_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
 	size_t rest = buffer_size;
@@ -342,9 +342,10 @@
 			ext3_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(inode, buffer, rest,
+			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
-						    entry->e_name_len);
+						    entry->e_name_len,
+						    handler->flags);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
@@ -357,8 +358,9 @@
 }
 
 static int
-ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct inode *inode = dentry->d_inode;
 	struct buffer_head *bh = NULL;
 	int error;
 
@@ -383,7 +385,7 @@
 		goto cleanup;
 	}
 	ext3_xattr_cache_insert(bh);
-	error = ext3_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+	error = ext3_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
 
 cleanup:
 	brelse(bh);
@@ -392,8 +394,9 @@
 }
 
 static int
-ext3_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct inode *inode = dentry->d_inode;
 	struct ext3_xattr_ibody_header *header;
 	struct ext3_inode *raw_inode;
 	struct ext3_iloc iloc;
@@ -411,7 +414,7 @@
 	error = ext3_xattr_check_names(IFIRST(header), end);
 	if (error)
 		goto cleanup;
-	error = ext3_xattr_list_entries(inode, IFIRST(header),
+	error = ext3_xattr_list_entries(dentry, IFIRST(header),
 					buffer, buffer_size);
 
 cleanup:
@@ -430,12 +433,12 @@
  * used / required on success.
  */
 static int
-ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext3_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	int i_error, b_error;
 
-	down_read(&EXT3_I(inode)->xattr_sem);
-	i_error = ext3_xattr_ibody_list(inode, buffer, buffer_size);
+	down_read(&EXT3_I(dentry->d_inode)->xattr_sem);
+	i_error = ext3_xattr_ibody_list(dentry, buffer, buffer_size);
 	if (i_error < 0) {
 		b_error = 0;
 	} else {
@@ -443,11 +446,11 @@
 			buffer += i_error;
 			buffer_size -= i_error;
 		}
-		b_error = ext3_xattr_block_list(inode, buffer, buffer_size);
+		b_error = ext3_xattr_block_list(dentry, buffer, buffer_size);
 		if (b_error < 0)
 			i_error = 0;
 	}
-	up_read(&EXT3_I(inode)->xattr_sem);
+	up_read(&EXT3_I(dentry->d_inode)->xattr_sem);
 	return i_error + b_error;
 }
 
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 37b8109..4743487 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -12,8 +12,8 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-			 const char *name, size_t name_len)
+ext3_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+			 const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,23 +28,23 @@
 }
 
 static int
-ext3_xattr_security_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext3_xattr_security_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name,
-			      buffer, size);
+	return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+			      name, buffer, size);
 }
 
 static int
-ext3_xattr_security_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext3_xattr_security_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name,
-			      value, size, flags);
+	return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_SECURITY,
+			      name, value, size, flags);
 }
 
 int
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index c7c41a4..e556284 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -14,8 +14,8 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-			const char *name, size_t name_len)
+ext3_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -32,22 +32,22 @@
 }
 
 static int
-ext3_xattr_trusted_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext3_xattr_trusted_get(struct dentry *dentry, const char *name,
+		       void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
-			      buffer, size);
+	return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED,
+			      name, buffer, size);
 }
 
 static int
-ext3_xattr_trusted_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext3_xattr_trusted_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+	return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_TRUSTED, name,
 			      value, size, flags);
 }
 
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index 430fe63..3bcfe9e 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -13,13 +13,13 @@
 #include "xattr.h"
 
 static size_t
-ext3_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-		     const char *name, size_t name_len)
+ext3_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -31,26 +31,27 @@
 }
 
 static int
-ext3_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+ext3_xattr_user_get(struct dentry *dentry, const char *name, void *buffer,
+		size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size);
+	return ext3_xattr_get(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+			      name, buffer, size);
 }
 
 static int
-ext3_xattr_user_set(struct inode *inode, const char *name,
-		    const void *value, size_t size, int flags)
+ext3_xattr_user_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
-			      value, size, flags);
+	return ext3_xattr_set(dentry->d_inode, EXT3_XATTR_INDEX_USER,
+			      name, value, size, flags);
 }
 
 struct xattr_handler ext3_xattr_user_handler = {
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index e5f6774..9acf7e8 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -2,7 +2,6 @@
 	tristate "The Extended 4 (ext4) filesystem"
 	select JBD2
 	select CRC16
-	select FS_JOURNAL_INFO
 	help
 	  This is the next generation of the ext3 filesystem.
 
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
index 0df88b2..8a2a29d 100644
--- a/fs/ext4/acl.c
+++ b/fs/ext4/acl.c
@@ -364,12 +364,12 @@
  * Extended attribute handlers
  */
 static size_t
-ext4_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-			   const char *name, size_t name_len)
+ext4_xattr_list_acl_access(struct dentry *dentry, char *list, size_t list_len,
+			   const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
 		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -377,12 +377,12 @@
 }
 
 static size_t
-ext4_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-			    const char *name, size_t name_len)
+ext4_xattr_list_acl_default(struct dentry *dentry, char *list, size_t list_len,
+			    const char *name, size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
 		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -390,15 +390,18 @@
 }
 
 static int
-ext4_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+ext4_xattr_get_acl(struct dentry *dentry, const char *name, void *buffer,
+		   size_t size, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!test_opt(inode->i_sb, POSIX_ACL))
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	if (!test_opt(dentry->d_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
 
-	acl = ext4_get_acl(inode, type);
+	acl = ext4_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -410,31 +413,16 @@
 }
 
 static int
-ext4_xattr_get_acl_access(struct inode *inode, const char *name,
-			  void *buffer, size_t size)
+ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
+		   size_t size, int flags, int type)
 {
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext4_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-ext4_xattr_get_acl_default(struct inode *inode, const char *name,
-			   void *buffer, size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext4_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-ext4_xattr_set_acl(struct inode *inode, int type, const void *value,
-		   size_t size)
-{
+	struct inode *inode = dentry->d_inode;
 	handle_t *handle;
 	struct posix_acl *acl;
 	int error, retries = 0;
 
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return -EOPNOTSUPP;
 	if (!is_owner_or_cap(inode))
@@ -466,34 +454,18 @@
 	return error;
 }
 
-static int
-ext4_xattr_set_acl_access(struct inode *inode, const char *name,
-			  const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext4_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int
-ext4_xattr_set_acl_default(struct inode *inode, const char *name,
-			   const void *value, size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ext4_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ext4_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
 	.list	= ext4_xattr_list_acl_access,
-	.get	= ext4_xattr_get_acl_access,
-	.set	= ext4_xattr_set_acl_access,
+	.get	= ext4_xattr_get_acl,
+	.set	= ext4_xattr_set_acl,
 };
 
 struct xattr_handler ext4_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= ext4_xattr_list_acl_default,
-	.get	= ext4_xattr_get_acl_default,
-	.set	= ext4_xattr_set_acl_default,
+	.get	= ext4_xattr_get_acl,
+	.set	= ext4_xattr_set_acl,
 };
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 910bf9a..83218be 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -92,7 +92,7 @@
 						 struct mb_cache_entry **);
 static void ext4_xattr_rehash(struct ext4_xattr_header *,
 			      struct ext4_xattr_entry *);
-static int ext4_xattr_list(struct inode *inode, char *buffer,
+static int ext4_xattr_list(struct dentry *dentry, char *buffer,
 			   size_t buffer_size);
 
 static struct mb_cache *ext4_xattr_cache;
@@ -140,7 +140,7 @@
 ssize_t
 ext4_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
-	return ext4_xattr_list(dentry->d_inode, buffer, size);
+	return ext4_xattr_list(dentry, buffer, size);
 }
 
 static int
@@ -325,7 +325,7 @@
 }
 
 static int
-ext4_xattr_list_entries(struct inode *inode, struct ext4_xattr_entry *entry,
+ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
 			char *buffer, size_t buffer_size)
 {
 	size_t rest = buffer_size;
@@ -335,9 +335,10 @@
 			ext4_xattr_handler(entry->e_name_index);
 
 		if (handler) {
-			size_t size = handler->list(inode, buffer, rest,
+			size_t size = handler->list(dentry, buffer, rest,
 						    entry->e_name,
-						    entry->e_name_len);
+						    entry->e_name_len,
+						    handler->flags);
 			if (buffer) {
 				if (size > rest)
 					return -ERANGE;
@@ -350,8 +351,9 @@
 }
 
 static int
-ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_block_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct inode *inode = dentry->d_inode;
 	struct buffer_head *bh = NULL;
 	int error;
 
@@ -376,7 +378,7 @@
 		goto cleanup;
 	}
 	ext4_xattr_cache_insert(bh);
-	error = ext4_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
+	error = ext4_xattr_list_entries(dentry, BFIRST(bh), buffer, buffer_size);
 
 cleanup:
 	brelse(bh);
@@ -385,8 +387,9 @@
 }
 
 static int
-ext4_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
+	struct inode *inode = dentry->d_inode;
 	struct ext4_xattr_ibody_header *header;
 	struct ext4_inode *raw_inode;
 	struct ext4_iloc iloc;
@@ -404,7 +407,7 @@
 	error = ext4_xattr_check_names(IFIRST(header), end);
 	if (error)
 		goto cleanup;
-	error = ext4_xattr_list_entries(inode, IFIRST(header),
+	error = ext4_xattr_list_entries(dentry, IFIRST(header),
 					buffer, buffer_size);
 
 cleanup:
@@ -423,12 +426,12 @@
  * used / required on success.
  */
 static int
-ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
+ext4_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
 	int i_error, b_error;
 
-	down_read(&EXT4_I(inode)->xattr_sem);
-	i_error = ext4_xattr_ibody_list(inode, buffer, buffer_size);
+	down_read(&EXT4_I(dentry->d_inode)->xattr_sem);
+	i_error = ext4_xattr_ibody_list(dentry, buffer, buffer_size);
 	if (i_error < 0) {
 		b_error = 0;
 	} else {
@@ -436,11 +439,11 @@
 			buffer += i_error;
 			buffer_size -= i_error;
 		}
-		b_error = ext4_xattr_block_list(inode, buffer, buffer_size);
+		b_error = ext4_xattr_block_list(dentry, buffer, buffer_size);
 		if (b_error < 0)
 			i_error = 0;
 	}
-	up_read(&EXT4_I(inode)->xattr_sem);
+	up_read(&EXT4_I(dentry->d_inode)->xattr_sem);
 	return i_error + b_error;
 }
 
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index ca5f89f..983c253 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -12,8 +12,8 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-			 const char *name, size_t name_len)
+ext4_xattr_security_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -28,23 +28,23 @@
 }
 
 static int
-ext4_xattr_security_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext4_xattr_security_get(struct dentry *dentry, const char *name,
+		       void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY, name,
-			      buffer, size);
+	return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+			      name, buffer, size);
 }
 
 static int
-ext4_xattr_security_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext4_xattr_security_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY, name,
-			      value, size, flags);
+	return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_SECURITY,
+			      name, value, size, flags);
 }
 
 int
diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
index ac1a52c..15b50ed 100644
--- a/fs/ext4/xattr_trusted.c
+++ b/fs/ext4/xattr_trusted.c
@@ -14,8 +14,8 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-			const char *name, size_t name_len)
+ext4_xattr_trusted_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -32,23 +32,23 @@
 }
 
 static int
-ext4_xattr_trusted_get(struct inode *inode, const char *name,
-		       void *buffer, size_t size)
+ext4_xattr_trusted_get(struct dentry *dentry, const char *name, void *buffer,
+		size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED, name,
-			      buffer, size);
+	return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+			      name, buffer, size);
 }
 
 static int
-ext4_xattr_trusted_set(struct inode *inode, const char *name,
-		       const void *value, size_t size, int flags)
+ext4_xattr_trusted_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED, name,
-			      value, size, flags);
+	return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_TRUSTED,
+			      name, value, size, flags);
 }
 
 struct xattr_handler ext4_xattr_trusted_handler = {
diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
index d91aa61..c4ce057 100644
--- a/fs/ext4/xattr_user.c
+++ b/fs/ext4/xattr_user.c
@@ -13,13 +13,13 @@
 #include "xattr.h"
 
 static size_t
-ext4_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-		     const char *name, size_t name_len)
+ext4_xattr_user_list(struct dentry *dentry, char *list, size_t list_size,
+		     const char *name, size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
 
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return 0;
 
 	if (list && total_len <= list_size) {
@@ -31,26 +31,27 @@
 }
 
 static int
-ext4_xattr_user_get(struct inode *inode, const char *name,
-		    void *buffer, size_t size)
+ext4_xattr_user_get(struct dentry *dentry, const char *name,
+		    void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER, name, buffer, size);
+	return ext4_xattr_get(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+			      name, buffer, size);
 }
 
 static int
-ext4_xattr_user_set(struct inode *inode, const char *name,
-		    const void *value, size_t size, int flags)
+ext4_xattr_user_set(struct dentry *dentry, const char *name,
+		    const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	if (!test_opt(inode->i_sb, XATTR_USER))
+	if (!test_opt(dentry->d_sb, XATTR_USER))
 		return -EOPNOTSUPP;
-	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER, name,
-			      value, size, flags);
+	return ext4_xattr_set(dentry->d_inode, EXT4_XATTR_INDEX_USER,
+			      name, value, size, flags);
 }
 
 struct xattr_handler ext4_xattr_user_handler = {
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 7db0979..e6efdfa 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -44,7 +44,8 @@
 		 nocase:1,	  /* Does this need case conversion? 0=need case conversion*/
 		 usefree:1,	  /* Use free_clusters for FAT32 */
 		 tz_utc:1,	  /* Filesystem timestamps are in UTC */
-		 rodir:1;	  /* allow ATTR_RO for directory */
+		 rodir:1,	  /* allow ATTR_RO for directory */
+		 discard:1;	  /* Issue discard requests on deletions */
 };
 
 #define FAT_HASH_BITS	8
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index a810377..81184d3 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -566,16 +566,21 @@
 			goto error;
 		}
 
-		/* 
-		 * Issue discard for the sectors we no longer care about,
-		 * batching contiguous clusters into one request
-		 */
-		if (cluster != fatent.entry + 1) {
-			int nr_clus = fatent.entry - first_cl + 1;
+		if (sbi->options.discard) {
+			/*
+			 * Issue discard for the sectors we no longer
+			 * care about, batching contiguous clusters
+			 * into one request
+			 */
+			if (cluster != fatent.entry + 1) {
+				int nr_clus = fatent.entry - first_cl + 1;
 
-			sb_issue_discard(sb, fat_clus_to_blknr(sbi, first_cl),
-					 nr_clus * sbi->sec_per_clus);
-			first_cl = cluster;
+				sb_issue_discard(sb,
+					fat_clus_to_blknr(sbi, first_cl),
+					nr_clus * sbi->sec_per_clus);
+
+				first_cl = cluster;
+			}
 		}
 
 		ops->ent_put(&fatent, FAT_ENT_FREE);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 76b7961..14da530 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -858,6 +858,8 @@
 		seq_puts(m, ",errors=panic");
 	else
 		seq_puts(m, ",errors=remount-ro");
+	if (opts->discard)
+		seq_puts(m, ",discard");
 
 	return 0;
 }
@@ -871,7 +873,7 @@
 	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
 	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
 	Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
-	Opt_err_panic, Opt_err_ro, Opt_err,
+	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -899,6 +901,7 @@
 	{Opt_err_cont, "errors=continue"},
 	{Opt_err_panic, "errors=panic"},
 	{Opt_err_ro, "errors=remount-ro"},
+	{Opt_discard, "discard"},
 	{Opt_obsolate, "conv=binary"},
 	{Opt_obsolate, "conv=text"},
 	{Opt_obsolate, "conv=auto"},
@@ -1136,6 +1139,9 @@
 		case Opt_rodir:
 			opts->rodir = 1;
 			break;
+		case Opt_discard:
+			opts->discard = 1;
+			break;
 
 		/* obsolete mount options */
 		case Opt_obsolate:
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 0f55f5c..d3da05f 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/time.h>
 #include "fat.h"
 
 /*
@@ -157,10 +158,6 @@
 #define SECS_PER_MIN	60
 #define SECS_PER_HOUR	(60 * 60)
 #define SECS_PER_DAY	(SECS_PER_HOUR * 24)
-#define UNIX_SECS_1980	315532800L
-#if BITS_PER_LONG == 64
-#define UNIX_SECS_2108	4354819200L
-#endif
 /* days between 1.1.70 and 1.1.80 (2 leap days) */
 #define DAYS_DELTA	(365 * 10 + 2)
 /* 120 (2100 - 1980) isn't leap year */
@@ -213,58 +210,35 @@
 void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
 		       __le16 *time, __le16 *date, u8 *time_cs)
 {
-	time_t second = ts->tv_sec;
-	time_t day, leap_day, month, year;
+	struct tm tm;
+	time_to_tm(ts->tv_sec, sbi->options.tz_utc ? 0 :
+		   -sys_tz.tz_minuteswest * 60, &tm);
 
-	if (!sbi->options.tz_utc)
-		second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
-
-	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
-	if (second < UNIX_SECS_1980) {
+	/*  FAT can only support year between 1980 to 2107 */
+	if (tm.tm_year < 1980 - 1900) {
 		*time = 0;
 		*date = cpu_to_le16((0 << 9) | (1 << 5) | 1);
 		if (time_cs)
 			*time_cs = 0;
 		return;
 	}
-#if BITS_PER_LONG == 64
-	if (second >= UNIX_SECS_2108) {
+	if (tm.tm_year > 2107 - 1900) {
 		*time = cpu_to_le16((23 << 11) | (59 << 5) | 29);
 		*date = cpu_to_le16((127 << 9) | (12 << 5) | 31);
 		if (time_cs)
 			*time_cs = 199;
 		return;
 	}
-#endif
 
-	day = second / SECS_PER_DAY - DAYS_DELTA;
-	year = day / 365;
-	leap_day = (year + 3) / 4;
-	if (year > YEAR_2100)		/* 2100 isn't leap year */
-		leap_day--;
-	if (year * 365 + leap_day > day)
-		year--;
-	leap_day = (year + 3) / 4;
-	if (year > YEAR_2100)		/* 2100 isn't leap year */
-		leap_day--;
-	day -= year * 365 + leap_day;
+	/* from 1900 -> from 1980 */
+	tm.tm_year -= 80;
+	/* 0~11 -> 1~12 */
+	tm.tm_mon++;
+	/* 0~59 -> 0~29(2sec counts) */
+	tm.tm_sec >>= 1;
 
-	if (IS_LEAP_YEAR(year) && day == days_in_year[3]) {
-		month = 2;
-	} else {
-		if (IS_LEAP_YEAR(year) && day > days_in_year[3])
-			day--;
-		for (month = 1; month < 12; month++) {
-			if (days_in_year[month + 1] > day)
-				break;
-		}
-	}
-	day -= days_in_year[month];
-
-	*time = cpu_to_le16(((second / SECS_PER_HOUR) % 24) << 11
-			    | ((second / SECS_PER_MIN) % 60) << 5
-			    | (second % SECS_PER_MIN) >> 1);
-	*date = cpu_to_le16((year << 9) | (month << 5) | (day + 1));
+	*time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec);
+	*date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday);
 	if (time_cs)
 		*time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000;
 }
@@ -285,4 +259,3 @@
 	}
 	return err;
 }
-
diff --git a/fs/file_table.c b/fs/file_table.c
index 4bef4c0..0afacf6 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -21,9 +21,12 @@
 #include <linux/fsnotify.h>
 #include <linux/sysctl.h>
 #include <linux/percpu_counter.h>
+#include <linux/ima.h>
 
 #include <asm/atomic.h>
 
+#include "internal.h"
+
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {
 	.max_files = NR_FILE
@@ -147,8 +150,6 @@
 	return NULL;
 }
 
-EXPORT_SYMBOL(get_empty_filp);
-
 /**
  * alloc_file - allocate and initialize a 'struct file'
  * @mnt: the vfsmount on which the file will reside
@@ -164,8 +165,8 @@
  * If all the callers of init_file() are eliminated, its
  * code should be moved into this function.
  */
-struct file *alloc_file(struct vfsmount *mnt, struct dentry *dentry,
-		fmode_t mode, const struct file_operations *fop)
+struct file *alloc_file(struct path *path, fmode_t mode,
+		const struct file_operations *fop)
 {
 	struct file *file;
 
@@ -173,35 +174,8 @@
 	if (!file)
 		return NULL;
 
-	init_file(file, mnt, dentry, mode, fop);
-	return file;
-}
-EXPORT_SYMBOL(alloc_file);
-
-/**
- * init_file - initialize a 'struct file'
- * @file: the already allocated 'struct file' to initialized
- * @mnt: the vfsmount on which the file resides
- * @dentry: the dentry representing this file
- * @mode: the mode the file is opened with
- * @fop: the 'struct file_operations' for this file
- *
- * Use this instead of setting the members directly.  Doing so
- * avoids making mistakes like forgetting the mntget() or
- * forgetting to take a write on the mnt.
- *
- * Note: This is a crappy interface.  It is here to make
- * merging with the existing users of get_empty_filp()
- * who have complex failure logic easier.  All users
- * of this should be moving to alloc_file().
- */
-int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
-	   fmode_t mode, const struct file_operations *fop)
-{
-	int error = 0;
-	file->f_path.dentry = dentry;
-	file->f_path.mnt = mntget(mnt);
-	file->f_mapping = dentry->d_inode->i_mapping;
+	file->f_path = *path;
+	file->f_mapping = path->dentry->d_inode->i_mapping;
 	file->f_mode = mode;
 	file->f_op = fop;
 
@@ -211,14 +185,16 @@
 	 * visible.  We do this for consistency, and so
 	 * that we can do debugging checks at __fput()
 	 */
-	if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
+	if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
+		int error = 0;
 		file_take_write(file);
-		error = mnt_clone_write(mnt);
+		error = mnt_clone_write(path->mnt);
 		WARN_ON(error);
 	}
-	return error;
+	ima_counts_get(file);
+	return file;
 }
-EXPORT_SYMBOL(init_file);
+EXPORT_SYMBOL(alloc_file);
 
 void fput(struct file *file)
 {
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index e590242..3221a0c 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -91,7 +91,7 @@
  */
 static struct fscache_object *fscache_objlist_lookup(loff_t *_pos)
 {
-	struct fscache_object *pobj, *obj, *minobj = NULL;
+	struct fscache_object *pobj, *obj = NULL, *minobj = NULL;
 	struct rb_node *p;
 	unsigned long pos;
 
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index e0b53aa..5545803 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -1,62 +1,58 @@
 /*
- * fs/generic_acl.c
- *
  * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
  *
  * This file is released under the GPL.
+ *
+ * Generic ACL support for in-memory filesystems.
  */
 
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/generic_acl.h>
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
 
-/**
- * generic_acl_list  -  Generic xattr_handler->list() operation
- * @ops:	Filesystem specific getacl and setacl callbacks
- */
-size_t
-generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
-		 int type, char *list, size_t list_size)
+
+static size_t
+generic_acl_list(struct dentry *dentry, char *list, size_t list_size,
+		const char *name, size_t name_len, int type)
 {
 	struct posix_acl *acl;
-	const char *name;
+	const char *xname;
 	size_t size;
 
-	acl = ops->getacl(inode, type);
+	acl = get_cached_acl(dentry->d_inode, type);
 	if (!acl)
 		return 0;
 	posix_acl_release(acl);
 
-	switch(type) {
-		case ACL_TYPE_ACCESS:
-			name = POSIX_ACL_XATTR_ACCESS;
-			break;
-
-		case ACL_TYPE_DEFAULT:
-			name = POSIX_ACL_XATTR_DEFAULT;
-			break;
-
-		default:
-			return 0;
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		xname = POSIX_ACL_XATTR_ACCESS;
+		break;
+	case ACL_TYPE_DEFAULT:
+		xname = POSIX_ACL_XATTR_DEFAULT;
+		break;
+	default:
+		return 0;
 	}
-	size = strlen(name) + 1;
+	size = strlen(xname) + 1;
 	if (list && size <= list_size)
-		memcpy(list, name, size);
+		memcpy(list, xname, size);
 	return size;
 }
 
-/**
- * generic_acl_get  -  Generic xattr_handler->get() operation
- * @ops:	Filesystem specific getacl and setacl callbacks
- */
-int
-generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
-		int type, void *buffer, size_t size)
+static int
+generic_acl_get(struct dentry *dentry, const char *name, void *buffer,
+		     size_t size, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	acl = ops->getacl(inode, type);
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+
+	acl = get_cached_acl(dentry->d_inode, type);
 	if (!acl)
 		return -ENODATA;
 	error = posix_acl_to_xattr(acl, buffer, size);
@@ -65,17 +61,16 @@
 	return error;
 }
 
-/**
- * generic_acl_set  -  Generic xattr_handler->set() operation
- * @ops:	Filesystem specific getacl and setacl callbacks
- */
-int
-generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
-		int type, const void *value, size_t size)
+static int
+generic_acl_set(struct dentry *dentry, const char *name, const void *value,
+		     size_t size, int flags, int type)
 {
+	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl = NULL;
 	int error;
 
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
 	if (!is_owner_or_cap(inode))
@@ -91,28 +86,27 @@
 		error = posix_acl_valid(acl);
 		if (error)
 			goto failed;
-		switch(type) {
-			case ACL_TYPE_ACCESS:
-				mode = inode->i_mode;
-				error = posix_acl_equiv_mode(acl, &mode);
-				if (error < 0)
-					goto failed;
-				inode->i_mode = mode;
-				if (error == 0) {
-					posix_acl_release(acl);
-					acl = NULL;
-				}
-				break;
-
-			case ACL_TYPE_DEFAULT:
-				if (!S_ISDIR(inode->i_mode)) {
-					error = -EINVAL;
-					goto failed;
-				}
-				break;
+		switch (type) {
+		case ACL_TYPE_ACCESS:
+			mode = inode->i_mode;
+			error = posix_acl_equiv_mode(acl, &mode);
+			if (error < 0)
+				goto failed;
+			inode->i_mode = mode;
+			if (error == 0) {
+				posix_acl_release(acl);
+				acl = NULL;
+			}
+			break;
+		case ACL_TYPE_DEFAULT:
+			if (!S_ISDIR(inode->i_mode)) {
+				error = -EINVAL;
+				goto failed;
+			}
+			break;
 		}
 	}
-	ops->setacl(inode, type, acl);
+	set_cached_acl(inode, type, acl);
 	error = 0;
 failed:
 	posix_acl_release(acl);
@@ -121,14 +115,12 @@
 
 /**
  * generic_acl_init  -  Take care of acl inheritance at @inode create time
- * @ops:	Filesystem specific getacl and setacl callbacks
  *
  * Files created inside a directory with a default ACL inherit the
  * directory's default ACL.
  */
 int
-generic_acl_init(struct inode *inode, struct inode *dir,
-		 struct generic_acl_operations *ops)
+generic_acl_init(struct inode *inode, struct inode *dir)
 {
 	struct posix_acl *acl = NULL;
 	mode_t mode = inode->i_mode;
@@ -136,7 +128,7 @@
 
 	inode->i_mode = mode & ~current_umask();
 	if (!S_ISLNK(inode->i_mode))
-		acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
+		acl = get_cached_acl(dir, ACL_TYPE_DEFAULT);
 	if (acl) {
 		struct posix_acl *clone;
 
@@ -145,7 +137,7 @@
 			error = -ENOMEM;
 			if (!clone)
 				goto cleanup;
-			ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
+			set_cached_acl(inode, ACL_TYPE_DEFAULT, clone);
 			posix_acl_release(clone);
 		}
 		clone = posix_acl_clone(acl, GFP_KERNEL);
@@ -156,7 +148,7 @@
 		if (error >= 0) {
 			inode->i_mode = mode;
 			if (error > 0)
-				ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+				set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
 		}
 		posix_acl_release(clone);
 	}
@@ -169,20 +161,19 @@
 
 /**
  * generic_acl_chmod  -  change the access acl of @inode upon chmod()
- * @ops:	FIlesystem specific getacl and setacl callbacks
  *
  * A chmod also changes the permissions of the owner, group/mask, and
  * other ACL entries.
  */
 int
-generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
+generic_acl_chmod(struct inode *inode)
 {
 	struct posix_acl *acl, *clone;
 	int error = 0;
 
 	if (S_ISLNK(inode->i_mode))
 		return -EOPNOTSUPP;
-	acl = ops->getacl(inode, ACL_TYPE_ACCESS);
+	acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
 	if (acl) {
 		clone = posix_acl_clone(acl, GFP_KERNEL);
 		posix_acl_release(acl);
@@ -190,8 +181,37 @@
 			return -ENOMEM;
 		error = posix_acl_chmod_masq(clone, inode->i_mode);
 		if (!error)
-			ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+			set_cached_acl(inode, ACL_TYPE_ACCESS, clone);
 		posix_acl_release(clone);
 	}
 	return error;
 }
+
+int
+generic_check_acl(struct inode *inode, int mask)
+{
+	struct posix_acl *acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
+
+	if (acl) {
+		int error = posix_acl_permission(inode, acl, mask);
+		posix_acl_release(acl);
+		return error;
+	}
+	return -EAGAIN;
+}
+
+struct xattr_handler generic_acl_access_handler = {
+	.prefix = POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
+	.list	= generic_acl_list,
+	.get	= generic_acl_get,
+	.set	= generic_acl_set,
+};
+
+struct xattr_handler generic_acl_default_handler = {
+	.prefix = POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
+	.list	= generic_acl_list,
+	.get	= generic_acl_get,
+	.set	= generic_acl_set,
+};
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index b192c66..4dcddf8 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -10,7 +10,6 @@
 	select SLOW_WORK
 	select QUOTA
 	select QUOTACTL
-	select FS_JOURNAL_INFO
 	help
 	  A cluster filesystem.
 
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 3eb1ea8..87ee309 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -126,7 +126,7 @@
 	error = posix_acl_to_xattr(acl, data, len);
 	if (error < 0)
 		goto out;
-	error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, data, len, 0);
+	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
 	if (!error)
 		set_cached_acl(inode, type, acl);
 out:
@@ -232,9 +232,10 @@
 	return -EINVAL;
 }
 
-static int gfs2_xattr_system_get(struct inode *inode, const char *name,
-				 void *buffer, size_t size)
+static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
+				 void *buffer, size_t size, int xtype)
 {
+	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int type;
 	int error;
@@ -255,9 +256,11 @@
 	return error;
 }
 
-static int gfs2_xattr_system_set(struct inode *inode, const char *name,
-				 const void *value, size_t size, int flags)
+static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
+				 const void *value, size_t size, int flags,
+				 int xtype)
 {
+	struct inode *inode = dentry->d_inode;
 	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct posix_acl *acl = NULL;
 	int error = 0, type;
@@ -319,7 +322,7 @@
 	}
 
 set_acl:
-	error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0);
+	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
 	if (!error) {
 		if (acl)
 			set_cached_acl(inode, type, acl);
@@ -334,6 +337,7 @@
 
 struct xattr_handler gfs2_xattr_system_handler = {
 	.prefix = XATTR_SYSTEM_PREFIX,
+	.flags  = GFS2_EATYPE_SYS,
 	.get    = gfs2_xattr_system_get,
 	.set    = gfs2_xattr_system_set,
 };
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 26ba2a4..6e220f4 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -125,7 +125,7 @@
  * directory entry when gfs2_inode_lookup() is invoked. Part of the code
  * segment inside gfs2_inode_lookup code needs to get moved around.
  *
- * Clean up I_LOCK and I_NEW as well.
+ * Clears I_NEW as well.
  **/
 
 void gfs2_set_iop(struct inode *inode)
@@ -801,7 +801,8 @@
 		return err;
 	}
 
-	err = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SECURITY, name, value, len, 0);
+	err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
+			       GFS2_EATYPE_SECURITY);
 	kfree(value);
 	kfree(name);
 
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 912f5cb..8a04108 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -567,18 +567,17 @@
 /**
  * gfs2_xattr_get - Get a GFS2 extended attribute
  * @inode: The inode
- * @type: The type of extended attribute
  * @name: The name of the extended attribute
  * @buffer: The buffer to write the result into
  * @size: The size of the buffer
+ * @type: The type of extended attribute
  *
  * Returns: actual size of data on success, -errno on error
  */
-
-int gfs2_xattr_get(struct inode *inode, int type, const char *name,
-		   void *buffer, size_t size)
+static int gfs2_xattr_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
-	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
 	struct gfs2_ea_location el;
 	int error;
 
@@ -1119,7 +1118,7 @@
 
 /**
  * gfs2_xattr_remove - Remove a GFS2 extended attribute
- * @inode: The inode
+ * @ip: The inode
  * @type: The type of the extended attribute
  * @name: The name of the extended attribute
  *
@@ -1130,9 +1129,8 @@
  * Returns: 0, or errno on failure
  */
 
-static int gfs2_xattr_remove(struct inode *inode, int type, const char *name)
+static int gfs2_xattr_remove(struct gfs2_inode *ip, int type, const char *name)
 {
-	struct gfs2_inode *ip = GFS2_I(inode);
 	struct gfs2_ea_location el;
 	int error;
 
@@ -1156,24 +1154,24 @@
 }
 
 /**
- * gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
- * @inode: The inode
- * @type: The type of the extended attribute
+ * __gfs2_xattr_set - Set (or remove) a GFS2 extended attribute
+ * @ip: The inode
  * @name: The name of the extended attribute
  * @value: The value of the extended attribute (NULL for remove)
  * @size: The size of the @value argument
  * @flags: Create or Replace
+ * @type: The type of the extended attribute
  *
  * See gfs2_xattr_remove() for details of the removal of xattrs.
  *
  * Returns: 0 or errno on failure
  */
 
-int gfs2_xattr_set(struct inode *inode, int type, const char *name,
-		   const void *value, size_t size, int flags)
+int __gfs2_xattr_set(struct inode *inode, const char *name,
+		   const void *value, size_t size, int flags, int type)
 {
-	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_inode *ip = GFS2_I(inode);
+	struct gfs2_sbd *sdp = GFS2_SB(inode);
 	struct gfs2_ea_location el;
 	unsigned int namel = strlen(name);
 	int error;
@@ -1184,7 +1182,7 @@
 		return -ERANGE;
 
 	if (value == NULL)
-		return gfs2_xattr_remove(inode, type, name);
+		return gfs2_xattr_remove(ip, type, name);
 
 	if (ea_check_size(sdp, namel, size))
 		return -ERANGE;
@@ -1224,6 +1222,13 @@
 	return error;
 }
 
+static int gfs2_xattr_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
+{
+	return __gfs2_xattr_set(dentry->d_inode, name, value,
+				size, flags, type);
+}
+
 static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
 				  struct gfs2_ea_header *ea, char *data)
 {
@@ -1529,40 +1534,18 @@
 	return error;
 }
 
-static int gfs2_xattr_user_get(struct inode *inode, const char *name,
-			       void *buffer, size_t size)
-{
-	return gfs2_xattr_get(inode, GFS2_EATYPE_USR, name, buffer, size);
-}
-
-static int gfs2_xattr_user_set(struct inode *inode, const char *name,
-			       const void *value, size_t size, int flags)
-{
-	return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);
-}
-
-static int gfs2_xattr_security_get(struct inode *inode, const char *name,
-				   void *buffer, size_t size)
-{
-	return gfs2_xattr_get(inode, GFS2_EATYPE_SECURITY, name, buffer, size);
-}
-
-static int gfs2_xattr_security_set(struct inode *inode, const char *name,
-				   const void *value, size_t size, int flags)
-{
-	return gfs2_xattr_set(inode, GFS2_EATYPE_SECURITY, name, value, size, flags);
-}
-
 static struct xattr_handler gfs2_xattr_user_handler = {
 	.prefix = XATTR_USER_PREFIX,
-	.get    = gfs2_xattr_user_get,
-	.set    = gfs2_xattr_user_set,
+	.flags  = GFS2_EATYPE_USR,
+	.get    = gfs2_xattr_get,
+	.set    = gfs2_xattr_set,
 };
 
 static struct xattr_handler gfs2_xattr_security_handler = {
 	.prefix = XATTR_SECURITY_PREFIX,
-	.get    = gfs2_xattr_security_get,
-	.set    = gfs2_xattr_security_set,
+	.flags  = GFS2_EATYPE_SECURITY,
+	.get    = gfs2_xattr_get,
+	.set    = gfs2_xattr_set,
 };
 
 struct xattr_handler *gfs2_xattr_handlers[] = {
diff --git a/fs/gfs2/xattr.h b/fs/gfs2/xattr.h
index 8d6ae58..d392f83 100644
--- a/fs/gfs2/xattr.h
+++ b/fs/gfs2/xattr.h
@@ -53,10 +53,9 @@
 	struct gfs2_ea_header *el_prev;
 };
 
-extern int gfs2_xattr_get(struct inode *inode, int type, const char *name,
-			  void *buffer, size_t size);
-extern int gfs2_xattr_set(struct inode *inode, int type, const char *name,
-			  const void *value, size_t size, int flags);
+extern int __gfs2_xattr_set(struct inode *inode, const char *name,
+			    const void *value, size_t size,
+			    int flags, int type);
 extern ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size);
 extern int gfs2_ea_dealloc(struct gfs2_inode *ip);
 
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index f2feaa0..cadc4ce 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -14,6 +14,7 @@
 #include <linux/magic.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
+#include <linux/bitmap.h>
 
 /* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
 
@@ -115,15 +116,13 @@
 unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
 {
 	struct quad_buffer_head qbh;
-	unsigned *bits;
-	unsigned i, count;
-	if (!(bits = hpfs_map_4sectors(s, secno, &qbh, 4))) return 0;
-	count = 0;
-	for (i = 0; i < 2048 / sizeof(unsigned); i++) {
-		unsigned b; 
-		if (!bits[i]) continue;
-		for (b = bits[i]; b; b>>=1) count += b & 1;
-	}
+	unsigned long *bits;
+	unsigned count;
+
+	bits = hpfs_map_4sectors(s, secno, &qbh, 4);
+	if (!bits)
+		return 0;
+	count = bitmap_weight(bits, 2048 * BITS_PER_BYTE);
 	hpfs_brelse4(&qbh);
 	return count;
 }
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 87a1258..a0bbd3d 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -30,7 +30,6 @@
 #include <linux/dnotify.h>
 #include <linux/statfs.h>
 #include <linux/security.h>
-#include <linux/ima.h>
 #include <linux/magic.h>
 
 #include <asm/uaccess.h>
@@ -922,7 +921,8 @@
 	int error = -ENOMEM;
 	struct file *file;
 	struct inode *inode;
-	struct dentry *dentry, *root;
+	struct path path;
+	struct dentry *root;
 	struct qstr quick_string;
 
 	*user = NULL;
@@ -944,10 +944,11 @@
 	quick_string.name = name;
 	quick_string.len = strlen(quick_string.name);
 	quick_string.hash = 0;
-	dentry = d_alloc(root, &quick_string);
-	if (!dentry)
+	path.dentry = d_alloc(root, &quick_string);
+	if (!path.dentry)
 		goto out_shm_unlock;
 
+	path.mnt = mntget(hugetlbfs_vfsmount);
 	error = -ENOSPC;
 	inode = hugetlbfs_get_inode(root->d_sb, current_fsuid(),
 				current_fsgid(), S_IFREG | S_IRWXUGO, 0);
@@ -960,24 +961,22 @@
 			acctflag))
 		goto out_inode;
 
-	d_instantiate(dentry, inode);
+	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
 	inode->i_nlink = 0;
 
 	error = -ENFILE;
-	file = alloc_file(hugetlbfs_vfsmount, dentry,
-			FMODE_WRITE | FMODE_READ,
+	file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
 			&hugetlbfs_file_operations);
 	if (!file)
 		goto out_dentry; /* inode is already attached */
-	ima_counts_get(file);
 
 	return file;
 
 out_inode:
 	iput(inode);
 out_dentry:
-	dput(dentry);
+	path_put(&path);
 out_shm_unlock:
 	if (*user) {
 		user_shm_unlock(size, *user);
diff --git a/fs/inode.c b/fs/inode.c
index 06c1f02..03dfeb2 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -113,7 +113,7 @@
 	 * Prevent speculative execution through spin_unlock(&inode_lock);
 	 */
 	smp_mb();
-	wake_up_bit(&inode->i_state, __I_LOCK);
+	wake_up_bit(&inode->i_state, __I_NEW);
 }
 
 /**
@@ -690,17 +690,17 @@
 	}
 #endif
 	/*
-	 * This is special!  We do not need the spinlock when clearing I_LOCK,
+	 * This is special!  We do not need the spinlock when clearing I_NEW,
 	 * because we're guaranteed that nobody else tries to do anything about
 	 * the state of the inode when it is locked, as we just created it (so
-	 * there can be no old holders that haven't tested I_LOCK).
+	 * there can be no old holders that haven't tested I_NEW).
 	 * However we must emit the memory barrier so that other CPUs reliably
-	 * see the clearing of I_LOCK after the other inode initialisation has
+	 * see the clearing of I_NEW after the other inode initialisation has
 	 * completed.
 	 */
 	smp_mb();
-	WARN_ON((inode->i_state & (I_LOCK|I_NEW)) != (I_LOCK|I_NEW));
-	inode->i_state &= ~(I_LOCK|I_NEW);
+	WARN_ON(!(inode->i_state & I_NEW));
+	inode->i_state &= ~I_NEW;
 	wake_up_inode(inode);
 }
 EXPORT_SYMBOL(unlock_new_inode);
@@ -731,7 +731,7 @@
 				goto set_failed;
 
 			__inode_add_to_lists(sb, head, inode);
-			inode->i_state = I_LOCK|I_NEW;
+			inode->i_state = I_NEW;
 			spin_unlock(&inode_lock);
 
 			/* Return the locked inode with I_NEW set, the
@@ -778,7 +778,7 @@
 		if (!old) {
 			inode->i_ino = ino;
 			__inode_add_to_lists(sb, head, inode);
-			inode->i_state = I_LOCK|I_NEW;
+			inode->i_state = I_NEW;
 			spin_unlock(&inode_lock);
 
 			/* Return the locked inode with I_NEW set, the
@@ -1083,7 +1083,7 @@
 	ino_t ino = inode->i_ino;
 	struct hlist_head *head = inode_hashtable + hash(sb, ino);
 
-	inode->i_state |= I_LOCK|I_NEW;
+	inode->i_state |= I_NEW;
 	while (1) {
 		struct hlist_node *node;
 		struct inode *old = NULL;
@@ -1120,7 +1120,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
 
-	inode->i_state |= I_LOCK|I_NEW;
+	inode->i_state |= I_NEW;
 
 	while (1) {
 		struct hlist_node *node;
@@ -1510,7 +1510,7 @@
  * until the deletion _might_ have completed.  Callers are responsible
  * to recheck inode state.
  *
- * It doesn't matter if I_LOCK is not set initially, a call to
+ * It doesn't matter if I_NEW is not set initially, a call to
  * wake_up_inode() after removing from the hash list will DTRT.
  *
  * This is called with inode_lock held.
@@ -1518,8 +1518,8 @@
 static void __wait_on_freeing_inode(struct inode *inode)
 {
 	wait_queue_head_t *wq;
-	DEFINE_WAIT_BIT(wait, &inode->i_state, __I_LOCK);
-	wq = bit_waitqueue(&inode->i_state, __I_LOCK);
+	DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW);
+	wq = bit_waitqueue(&inode->i_state, __I_NEW);
 	prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE);
 	spin_unlock(&inode_lock);
 	schedule();
diff --git a/fs/internal.h b/fs/internal.h
index 515175b..f67cd14 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -79,6 +79,7 @@
  * file_table.c
  */
 extern void mark_files_ro(struct super_block *);
+extern struct file *get_empty_filp(void);
 
 /*
  * super.c
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index e81a305..ed752cb 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -9,7 +9,7 @@
  *
  * The following files are helpful:
  *
- *     Documentation/filesystems/Exporting
+ *     Documentation/filesystems/nfs/Exporting
  *     fs/exportfs/expfs.c.
  */
 
diff --git a/fs/jbd/Kconfig b/fs/jbd/Kconfig
index a840898..4e28bee 100644
--- a/fs/jbd/Kconfig
+++ b/fs/jbd/Kconfig
@@ -1,6 +1,5 @@
 config JBD
 	tristate
-	select FS_JOURNAL_INFO
 	help
 	  This is a generic journalling layer for block devices.  It is
 	  currently used by the ext3 file system, but it could also be
diff --git a/fs/jbd2/Kconfig b/fs/jbd2/Kconfig
index 0f7d1ce..f32f346 100644
--- a/fs/jbd2/Kconfig
+++ b/fs/jbd2/Kconfig
@@ -1,7 +1,6 @@
 config JBD2
 	tristate
 	select CRC32
-	select FS_JOURNAL_INFO
 	help
 	  This is a generic journaling layer for block devices that support
 	  both 32-bit and 64-bit block numbers.  It is currently used by
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 7edb62e..7cdc319 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -350,8 +350,8 @@
 	return rc;
 }
 
-static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
-					 const char *name, size_t name_len)
+static size_t jffs2_acl_access_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
 {
 	const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
 
@@ -360,8 +360,8 @@
 	return retlen;
 }
 
-static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
-					  const char *name, size_t name_len)
+static size_t jffs2_acl_default_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
 {
 	const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
@@ -370,12 +370,16 @@
 	return retlen;
 }
 
-static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
+static int jffs2_acl_getxattr(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	struct posix_acl *acl;
 	int rc;
 
-	acl = jffs2_get_acl(inode, type);
+	if (name[0] != '\0')
+		return -EINVAL;
+
+	acl = jffs2_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (!acl)
@@ -386,26 +390,15 @@
 	return rc;
 }
 
-static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
-{
-	if (name[0] != '\0')
-		return -EINVAL;
-	return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
-{
-	if (name[0] != '\0')
-		return -EINVAL;
-	return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
+static int jffs2_acl_setxattr(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	struct posix_acl *acl;
 	int rc;
 
-	if (!is_owner_or_cap(inode))
+	if (name[0] != '\0')
+		return -EINVAL;
+	if (!is_owner_or_cap(dentry->d_inode))
 		return -EPERM;
 
 	if (value) {
@@ -420,38 +413,24 @@
 	} else {
 		acl = NULL;
 	}
-	rc = jffs2_set_acl(inode, type, acl);
+	rc = jffs2_set_acl(dentry->d_inode, type, acl);
  out:
 	posix_acl_release(acl);
 	return rc;
 }
 
-static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
-				     const void *buffer, size_t size, int flags)
-{
-	if (name[0] != '\0')
-		return -EINVAL;
-	return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
-				      const void *buffer, size_t size, int flags)
-{
-	if (name[0] != '\0')
-		return -EINVAL;
-	return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
 struct xattr_handler jffs2_acl_access_xattr_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= jffs2_acl_access_listxattr,
-	.get	= jffs2_acl_access_getxattr,
-	.set	= jffs2_acl_access_setxattr,
+	.get	= jffs2_acl_getxattr,
+	.set	= jffs2_acl_setxattr,
 };
 
 struct xattr_handler jffs2_acl_default_xattr_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= jffs2_acl_default_listxattr,
-	.get	= jffs2_acl_default_getxattr,
-	.set	= jffs2_acl_default_setxattr,
+	.get	= jffs2_acl_getxattr,
+	.set	= jffs2_acl_setxattr,
 };
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 090c556..3b6f2fa 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -700,7 +700,8 @@
 	struct jffs2_raw_inode ri;
 	struct jffs2_node_frag *last_frag;
 	union jffs2_device_node dev;
-	char *mdata = NULL, mdatalen = 0;
+	char *mdata = NULL;
+	int mdatalen = 0;
 	uint32_t alloclen, ilen;
 	int ret;
 
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 378991c..e22de83 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1284,7 +1284,7 @@
 				f->target = NULL;
 				mutex_unlock(&f->sem);
 				jffs2_do_clear_inode(c, f);
-				return -ret;
+				return ret;
 			}
 
 			f->target[je32_to_cpu(latest_node->csize)] = '\0';
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 02c39c6..eaccee0 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -44,26 +44,28 @@
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
-static int jffs2_security_getxattr(struct inode *inode, const char *name,
-				   void *buffer, size_t size)
+static int jffs2_security_getxattr(struct dentry *dentry, const char *name,
+				   void *buffer, size_t size, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
+	return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+				 name, buffer, size);
 }
 
-static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
-				   size_t size, int flags)
+static int jffs2_security_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
 
-	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
+	return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_SECURITY,
+				 name, buffer, size, flags);
 }
 
-static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
-				       const char *name, size_t name_len)
+static size_t jffs2_security_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
 {
 	size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 6caf1e1e..800171d 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -23,7 +23,7 @@
 
 int jffs2_sum_init(struct jffs2_sb_info *c)
 {
-	uint32_t sum_size = max_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
+	uint32_t sum_size = min_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
 
 	c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 4b10788..9e75c62c 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -990,9 +990,11 @@
 		if (!xhandle)
 			continue;
 		if (buffer) {
-			rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
+			rc = xhandle->list(dentry, buffer+len, size-len,
+					   xd->xname, xd->name_len, xd->flags);
 		} else {
-			rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
+			rc = xhandle->list(dentry, NULL, 0, xd->xname,
+					   xd->name_len, xd->flags);
 		}
 		if (rc < 0)
 			goto out;
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
index 8ec5765..3e5a5e3 100644
--- a/fs/jffs2/xattr_trusted.c
+++ b/fs/jffs2/xattr_trusted.c
@@ -16,24 +16,26 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
-				  void *buffer, size_t size)
+static int jffs2_trusted_getxattr(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
+	return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+				 name, buffer, size);
 }
 
-static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
-				  size_t size, int flags)
+static int jffs2_trusted_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
+	return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_TRUSTED,
+				 name, buffer, size, flags);
 }
 
-static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
-				      const char *name, size_t name_len)
+static size_t jffs2_trusted_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
 {
 	size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
index 8bbeab9..8544af6 100644
--- a/fs/jffs2/xattr_user.c
+++ b/fs/jffs2/xattr_user.c
@@ -16,24 +16,26 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-static int jffs2_user_getxattr(struct inode *inode, const char *name,
-			       void *buffer, size_t size)
+static int jffs2_user_getxattr(struct dentry *dentry, const char *name,
+			       void *buffer, size_t size, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
+	return do_jffs2_getxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+				 name, buffer, size);
 }
 
-static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
-			       size_t size, int flags)
+static int jffs2_user_setxattr(struct dentry *dentry, const char *name,
+		const void *buffer, size_t size, int flags, int type)
 {
 	if (!strcmp(name, ""))
 		return -EINVAL;
-	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
+	return do_jffs2_setxattr(dentry->d_inode, JFFS2_XPREFIX_USER,
+				 name, buffer, size, flags);
 }
 
-static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
-				   const char *name, size_t name_len)
+static size_t jffs2_user_listxattr(struct dentry *dentry, char *list,
+		size_t list_size, const char *name, size_t name_len, int type)
 {
 	size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
 
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f26e4d0..d945ea7 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1292,7 +1292,7 @@
 		 */
 		/*
 		 * I believe this code is no longer needed.  Splitting I_LOCK
-		 * into two bits, I_LOCK and I_SYNC should prevent this
+		 * into two bits, I_NEW and I_SYNC should prevent this
 		 * deadlock as well.  But since I don't have a JFS testload
 		 * to verify this, only a trivial s/I_LOCK/I_SYNC/ was done.
 		 * Joern
diff --git a/fs/libfs.c b/fs/libfs.c
index 219576c..6e8d17e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -848,7 +848,6 @@
 EXPORT_SYMBOL(simple_dir_inode_operations);
 EXPORT_SYMBOL(simple_dir_operations);
 EXPORT_SYMBOL(simple_empty);
-EXPORT_SYMBOL(d_alloc_name);
 EXPORT_SYMBOL(simple_fill_super);
 EXPORT_SYMBOL(simple_getattr);
 EXPORT_SYMBOL(simple_link);
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index bd173a6..a7966ee 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -11,10 +11,6 @@
 #include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
-#include <linux/in.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/lockd/lockd.h>
 #include <linux/lockd/share.h>
 
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index e1d28dd..56c9519 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -11,10 +11,6 @@
 #include <linux/time.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
-#include <linux/in.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/lockd/lockd.h>
 #include <linux/lockd/share.h>
 
diff --git a/fs/namei.c b/fs/namei.c
index 87f97ba..dad4b80 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -35,6 +35,8 @@
 #include <linux/fs_struct.h>
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /* [Feb-1997 T. Schoebel-Theuer]
@@ -108,8 +110,6 @@
  * any extra contention...
  */
 
-static int __link_path_walk(const char *name, struct nameidata *nd);
-
 /* In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
@@ -414,36 +414,55 @@
 }
 
 /*
- * Internal lookup() using the new generic dcache.
- * SMP-safe
+ * force_reval_path - force revalidation of a dentry
+ *
+ * In some situations the path walking code will trust dentries without
+ * revalidating them. This causes problems for filesystems that depend on
+ * d_revalidate to handle file opens (e.g. NFSv4). When FS_REVAL_DOT is set
+ * (which indicates that it's possible for the dentry to go stale), force
+ * a d_revalidate call before proceeding.
+ *
+ * Returns 0 if the revalidation was successful. If the revalidation fails,
+ * either return the error returned by d_revalidate or -ESTALE if the
+ * revalidation it just returned 0. If d_revalidate returns 0, we attempt to
+ * invalidate the dentry. It's up to the caller to handle putting references
+ * to the path if necessary.
  */
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
+static int
+force_reval_path(struct path *path, struct nameidata *nd)
 {
-	struct dentry * dentry = __d_lookup(parent, name);
+	int status;
+	struct dentry *dentry = path->dentry;
 
-	/* lockess __d_lookup may fail due to concurrent d_move() 
-	 * in some unrelated directory, so try with d_lookup
+	/*
+	 * only check on filesystems where it's possible for the dentry to
+	 * become stale. It's assumed that if this flag is set then the
+	 * d_revalidate op will also be defined.
 	 */
-	if (!dentry)
-		dentry = d_lookup(parent, name);
+	if (!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))
+		return 0;
 
-	if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
-		dentry = do_revalidate(dentry, nd);
+	status = dentry->d_op->d_revalidate(dentry, nd);
+	if (status > 0)
+		return 0;
 
-	return dentry;
+	if (!status) {
+		d_invalidate(dentry);
+		status = -ESTALE;
+	}
+	return status;
 }
 
 /*
- * Short-cut version of permission(), for calling by
- * path_walk(), when dcache lock is held.  Combines parts
- * of permission() and generic_permission(), and tests ONLY for
- * MAY_EXEC permission.
+ * Short-cut version of permission(), for calling on directories
+ * during pathname resolution.  Combines parts of permission()
+ * and generic_permission(), and tests ONLY for MAY_EXEC permission.
  *
  * If appropriate, check DAC only.  If not appropriate, or
- * short-cut DAC fails, then call permission() to do more
+ * short-cut DAC fails, then call ->permission() to do more
  * complete permission check.
  */
-static int exec_permission_lite(struct inode *inode)
+static int exec_permission(struct inode *inode)
 {
 	int ret;
 
@@ -465,99 +484,6 @@
 	return security_inode_permission(inode, MAY_EXEC);
 }
 
-/*
- * This is called when everything else fails, and we actually have
- * to go to the low-level filesystem to find out what we should do..
- *
- * We get the directory semaphore, and after getting that we also
- * make sure that nobody added the entry to the dcache in the meantime..
- * SMP-safe
- */
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
-{
-	struct dentry * result;
-	struct inode *dir = parent->d_inode;
-
-	mutex_lock(&dir->i_mutex);
-	/*
-	 * First re-do the cached lookup just in case it was created
-	 * while we waited for the directory semaphore..
-	 *
-	 * FIXME! This could use version numbering or similar to
-	 * avoid unnecessary cache lookups.
-	 *
-	 * The "dcache_lock" is purely to protect the RCU list walker
-	 * from concurrent renames at this point (we mustn't get false
-	 * negatives from the RCU list walk here, unlike the optimistic
-	 * fast walk).
-	 *
-	 * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
-	 */
-	result = d_lookup(parent, name);
-	if (!result) {
-		struct dentry *dentry;
-
-		/* Don't create child dentry for a dead directory. */
-		result = ERR_PTR(-ENOENT);
-		if (IS_DEADDIR(dir))
-			goto out_unlock;
-
-		dentry = d_alloc(parent, name);
-		result = ERR_PTR(-ENOMEM);
-		if (dentry) {
-			result = dir->i_op->lookup(dir, dentry, nd);
-			if (result)
-				dput(dentry);
-			else
-				result = dentry;
-		}
-out_unlock:
-		mutex_unlock(&dir->i_mutex);
-		return result;
-	}
-
-	/*
-	 * Uhhuh! Nasty case: the cache was re-populated while
-	 * we waited on the semaphore. Need to revalidate.
-	 */
-	mutex_unlock(&dir->i_mutex);
-	if (result->d_op && result->d_op->d_revalidate) {
-		result = do_revalidate(result, nd);
-		if (!result)
-			result = ERR_PTR(-ENOENT);
-	}
-	return result;
-}
-
-/*
- * Wrapper to retry pathname resolution whenever the underlying
- * file system returns an ESTALE.
- *
- * Retry the whole path once, forcing real lookup requests
- * instead of relying on the dcache.
- */
-static __always_inline int link_path_walk(const char *name, struct nameidata *nd)
-{
-	struct path save = nd->path;
-	int result;
-
-	/* make sure the stuff we saved doesn't go away */
-	path_get(&save);
-
-	result = __link_path_walk(name, nd);
-	if (result == -ESTALE) {
-		/* nd->path had been dropped */
-		nd->path = save;
-		path_get(&nd->path);
-		nd->flags |= LOOKUP_REVAL;
-		result = __link_path_walk(name, nd);
-	}
-
-	path_put(&save);
-
-	return result;
-}
-
 static __always_inline void set_root(struct nameidata *nd)
 {
 	if (!nd->root.mnt) {
@@ -569,6 +495,8 @@
 	}
 }
 
+static int link_path_walk(const char *, struct nameidata *);
+
 static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
 {
 	int res = 0;
@@ -641,11 +569,14 @@
 		error = 0;
 		if (s)
 			error = __vfs_follow_link(nd, s);
+		else if (nd->last_type == LAST_BIND) {
+			error = force_reval_path(&nd->path, nd);
+			if (error)
+				path_put(&nd->path);
+		}
 		if (dentry->d_inode->i_op->put_link)
 			dentry->d_inode->i_op->put_link(dentry, nd, cookie);
 	}
-	path_put(path);
-
 	return error;
 }
 
@@ -672,6 +603,7 @@
 	current->total_link_count++;
 	nd->depth++;
 	err = __do_follow_link(path, nd);
+	path_put(path);
 	current->link_count--;
 	nd->depth--;
 	return err;
@@ -797,8 +729,19 @@
 		     struct path *path)
 {
 	struct vfsmount *mnt = nd->path.mnt;
-	struct dentry *dentry = __d_lookup(nd->path.dentry, name);
+	struct dentry *dentry, *parent;
+	struct inode *dir;
+	/*
+	 * See if the low-level filesystem might want
+	 * to use its own hash..
+	 */
+	if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
+		int err = nd->path.dentry->d_op->d_hash(nd->path.dentry, name);
+		if (err < 0)
+			return err;
+	}
 
+	dentry = __d_lookup(nd->path.dentry, name);
 	if (!dentry)
 		goto need_lookup;
 	if (dentry->d_op && dentry->d_op->d_revalidate)
@@ -810,7 +753,59 @@
 	return 0;
 
 need_lookup:
-	dentry = real_lookup(nd->path.dentry, name, nd);
+	parent = nd->path.dentry;
+	dir = parent->d_inode;
+
+	mutex_lock(&dir->i_mutex);
+	/*
+	 * First re-do the cached lookup just in case it was created
+	 * while we waited for the directory semaphore..
+	 *
+	 * FIXME! This could use version numbering or similar to
+	 * avoid unnecessary cache lookups.
+	 *
+	 * The "dcache_lock" is purely to protect the RCU list walker
+	 * from concurrent renames at this point (we mustn't get false
+	 * negatives from the RCU list walk here, unlike the optimistic
+	 * fast walk).
+	 *
+	 * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup
+	 */
+	dentry = d_lookup(parent, name);
+	if (!dentry) {
+		struct dentry *new;
+
+		/* Don't create child dentry for a dead directory. */
+		dentry = ERR_PTR(-ENOENT);
+		if (IS_DEADDIR(dir))
+			goto out_unlock;
+
+		new = d_alloc(parent, name);
+		dentry = ERR_PTR(-ENOMEM);
+		if (new) {
+			dentry = dir->i_op->lookup(dir, new, nd);
+			if (dentry)
+				dput(new);
+			else
+				dentry = new;
+		}
+out_unlock:
+		mutex_unlock(&dir->i_mutex);
+		if (IS_ERR(dentry))
+			goto fail;
+		goto done;
+	}
+
+	/*
+	 * Uhhuh! Nasty case: the cache was re-populated while
+	 * we waited on the semaphore. Need to revalidate.
+	 */
+	mutex_unlock(&dir->i_mutex);
+	if (dentry->d_op && dentry->d_op->d_revalidate) {
+		dentry = do_revalidate(dentry, nd);
+		if (!dentry)
+			dentry = ERR_PTR(-ENOENT);
+	}
 	if (IS_ERR(dentry))
 		goto fail;
 	goto done;
@@ -835,7 +830,7 @@
  * Returns 0 and nd will have valid dentry and mnt on success.
  * Returns error and drops reference to input namei data on failure.
  */
-static int __link_path_walk(const char *name, struct nameidata *nd)
+static int link_path_walk(const char *name, struct nameidata *nd)
 {
 	struct path next;
 	struct inode *inode;
@@ -858,7 +853,7 @@
 		unsigned int c;
 
 		nd->flags |= LOOKUP_CONTINUE;
-		err = exec_permission_lite(inode);
+		err = exec_permission(inode);
  		if (err)
 			break;
 
@@ -898,16 +893,6 @@
 			case 1:
 				continue;
 		}
-		/*
-		 * See if the low-level filesystem might want
-		 * to use its own hash..
-		 */
-		if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-			err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
-							    &this);
-			if (err < 0)
-				break;
-		}
 		/* This does the actual lookups.. */
 		err = do_lookup(nd, &this, &next);
 		if (err)
@@ -953,12 +938,6 @@
 			case 1:
 				goto return_reval;
 		}
-		if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
-			err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
-							    &this);
-			if (err < 0)
-				break;
-		}
 		err = do_lookup(nd, &this, &next);
 		if (err)
 			break;
@@ -1017,8 +996,27 @@
 
 static int path_walk(const char *name, struct nameidata *nd)
 {
+	struct path save = nd->path;
+	int result;
+
 	current->total_link_count = 0;
-	return link_path_walk(name, nd);
+
+	/* make sure the stuff we saved doesn't go away */
+	path_get(&save);
+
+	result = link_path_walk(name, nd);
+	if (result == -ESTALE) {
+		/* nd->path had been dropped */
+		current->total_link_count = 0;
+		nd->path = save;
+		path_get(&nd->path);
+		nd->flags |= LOOKUP_REVAL;
+		result = link_path_walk(name, nd);
+	}
+
+	path_put(&save);
+
+	return result;
 }
 
 static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
@@ -1141,36 +1139,6 @@
 	return retval;
 }
 
-/**
- * path_lookup_open - lookup a file path with open intent
- * @dfd: the directory to use as base, or AT_FDCWD
- * @name: pointer to file name
- * @lookup_flags: lookup intent flags
- * @nd: pointer to nameidata
- * @open_flags: open intent flags
- */
-static int path_lookup_open(int dfd, const char *name,
-		unsigned int lookup_flags, struct nameidata *nd, int open_flags)
-{
-	struct file *filp = get_empty_filp();
-	int err;
-
-	if (filp == NULL)
-		return -ENFILE;
-	nd->intent.open.file = filp;
-	nd->intent.open.flags = open_flags;
-	nd->intent.open.create_mode = 0;
-	err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
-	if (IS_ERR(nd->intent.open.file)) {
-		if (err == 0) {
-			err = PTR_ERR(nd->intent.open.file);
-			path_put(&nd->path);
-		}
-	} else if (err != 0)
-		release_open_intent(nd);
-	return err;
-}
-
 static struct dentry *__lookup_hash(struct qstr *name,
 		struct dentry *base, struct nameidata *nd)
 {
@@ -1191,7 +1159,17 @@
 			goto out;
 	}
 
-	dentry = cached_lookup(base, name, nd);
+	dentry = __d_lookup(base, name);
+
+	/* lockess __d_lookup may fail due to concurrent d_move()
+	 * in some unrelated directory, so try with d_lookup
+	 */
+	if (!dentry)
+		dentry = d_lookup(base, name);
+
+	if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+		dentry = do_revalidate(dentry, nd);
+
 	if (!dentry) {
 		struct dentry *new;
 
@@ -1223,7 +1201,7 @@
 {
 	int err;
 
-	err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
+	err = exec_permission(nd->path.dentry->d_inode);
 	if (err)
 		return ERR_PTR(err);
 	return __lookup_hash(&nd->last, nd->path.dentry, nd);
@@ -1273,7 +1251,7 @@
 	if (err)
 		return ERR_PTR(err);
 
-	err = inode_permission(base->d_inode, MAY_EXEC);
+	err = exec_permission(base->d_inode);
 	if (err)
 		return ERR_PTR(err);
 	return __lookup_hash(&this, base, NULL);
@@ -1511,69 +1489,45 @@
 	if (error)
 		return error;
 
-	error = ima_path_check(path, acc_mode ?
-			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
-			       ACC_MODE(flag) & (MAY_READ | MAY_WRITE),
-			       IMA_COUNT_UPDATE);
-
-	if (error)
-		return error;
 	/*
 	 * An append-only file must be opened in append mode for writing.
 	 */
 	if (IS_APPEND(inode)) {
-		error = -EPERM;
 		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
-			goto err_out;
+			return -EPERM;
 		if (flag & O_TRUNC)
-			goto err_out;
+			return -EPERM;
 	}
 
 	/* O_NOATIME can only be set by the owner or superuser */
-	if (flag & O_NOATIME)
-		if (!is_owner_or_cap(inode)) {
-			error = -EPERM;
-			goto err_out;
-		}
+	if (flag & O_NOATIME && !is_owner_or_cap(inode))
+		return -EPERM;
 
 	/*
 	 * Ensure there are no outstanding leases on the file.
 	 */
-	error = break_lease(inode, flag);
+	return break_lease(inode, flag);
+}
+
+static int handle_truncate(struct path *path)
+{
+	struct inode *inode = path->dentry->d_inode;
+	int error = get_write_access(inode);
 	if (error)
-		goto err_out;
-
-	if (flag & O_TRUNC) {
-		error = get_write_access(inode);
-		if (error)
-			goto err_out;
-
-		/*
-		 * Refuse to truncate files with mandatory locks held on them.
-		 */
-		error = locks_verify_locked(inode);
-		if (!error)
-			error = security_path_truncate(path, 0,
-					       ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
-		if (!error) {
-			vfs_dq_init(inode);
-
-			error = do_truncate(dentry, 0,
-					    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
-					    NULL);
-		}
-		put_write_access(inode);
-		if (error)
-			goto err_out;
-	} else
-		if (flag & FMODE_WRITE)
-			vfs_dq_init(inode);
-
-	return 0;
-err_out:
-	ima_counts_put(path, acc_mode ?
-		       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
-		       ACC_MODE(flag) & (MAY_READ | MAY_WRITE));
+		return error;
+	/*
+	 * Refuse to truncate files with mandatory locks held on them.
+	 */
+	error = locks_verify_locked(inode);
+	if (!error)
+		error = security_path_truncate(path, 0,
+				       ATTR_MTIME|ATTR_CTIME|ATTR_OPEN);
+	if (!error) {
+		error = do_truncate(path->dentry, 0,
+				    ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
+				    NULL);
+	}
+	put_write_access(inode);
 	return error;
 }
 
@@ -1628,7 +1582,7 @@
 	return flag;
 }
 
-static int open_will_write_to_fs(int flag, struct inode *inode)
+static int open_will_truncate(int flag, struct inode *inode)
 {
 	/*
 	 * We'll never write to the fs underlying
@@ -1650,10 +1604,10 @@
 	struct file *filp;
 	struct nameidata nd;
 	int error;
-	struct path path;
+	struct path path, save;
 	struct dentry *dir;
 	int count = 0;
-	int will_write;
+	int will_truncate;
 	int flag = open_to_namei_flags(open_flag);
 
 	/*
@@ -1681,8 +1635,22 @@
 	 * The simplest case - just a plain lookup.
 	 */
 	if (!(flag & O_CREAT)) {
-		error = path_lookup_open(dfd, pathname, lookup_flags(flag),
-					 &nd, flag);
+		filp = get_empty_filp();
+
+		if (filp == NULL)
+			return ERR_PTR(-ENFILE);
+		nd.intent.open.file = filp;
+		nd.intent.open.flags = flag;
+		nd.intent.open.create_mode = 0;
+		error = do_path_lookup(dfd, pathname,
+					lookup_flags(flag)|LOOKUP_OPEN, &nd);
+		if (IS_ERR(nd.intent.open.file)) {
+			if (error == 0) {
+				error = PTR_ERR(nd.intent.open.file);
+				path_put(&nd.path);
+			}
+		} else if (error)
+			release_open_intent(&nd);
 		if (error)
 			return ERR_PTR(error);
 		goto ok;
@@ -1758,13 +1726,17 @@
 			goto exit;
 		}
 		filp = nameidata_to_filp(&nd, open_flag);
-		if (IS_ERR(filp))
-			ima_counts_put(&nd.path,
-				       acc_mode & (MAY_READ | MAY_WRITE |
-						   MAY_EXEC));
 		mnt_drop_write(nd.path.mnt);
 		if (nd.root.mnt)
 			path_put(&nd.root);
+		if (!IS_ERR(filp)) {
+			error = ima_path_check(&filp->f_path, filp->f_mode &
+				       (MAY_READ | MAY_WRITE | MAY_EXEC));
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
+		}
 		return filp;
 	}
 
@@ -1792,7 +1764,7 @@
 
 	path_to_nameidata(&path, &nd);
 	error = -EISDIR;
-	if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
+	if (S_ISDIR(path.dentry->d_inode->i_mode))
 		goto exit;
 ok:
 	/*
@@ -1805,28 +1777,45 @@
 	 * be avoided. Taking this mnt write here
 	 * ensures that (2) can not occur.
 	 */
-	will_write = open_will_write_to_fs(flag, nd.path.dentry->d_inode);
-	if (will_write) {
+	will_truncate = open_will_truncate(flag, nd.path.dentry->d_inode);
+	if (will_truncate) {
 		error = mnt_want_write(nd.path.mnt);
 		if (error)
 			goto exit;
 	}
 	error = may_open(&nd.path, acc_mode, flag);
 	if (error) {
-		if (will_write)
+		if (will_truncate)
 			mnt_drop_write(nd.path.mnt);
 		goto exit;
 	}
 	filp = nameidata_to_filp(&nd, open_flag);
-	if (IS_ERR(filp))
-		ima_counts_put(&nd.path,
-			       acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+	if (!IS_ERR(filp)) {
+		error = ima_path_check(&filp->f_path, filp->f_mode &
+			       (MAY_READ | MAY_WRITE | MAY_EXEC));
+		if (error) {
+			fput(filp);
+			filp = ERR_PTR(error);
+		}
+	}
+	if (!IS_ERR(filp)) {
+		if (acc_mode & MAY_WRITE)
+			vfs_dq_init(nd.path.dentry->d_inode);
+
+		if (will_truncate) {
+			error = handle_truncate(&nd.path);
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
+		}
+	}
 	/*
 	 * It is now safe to drop the mnt write
 	 * because the filp has had a write taken
 	 * on its behalf.
 	 */
-	if (will_write)
+	if (will_truncate)
 		mnt_drop_write(nd.path.mnt);
 	if (nd.root.mnt)
 		path_put(&nd.root);
@@ -1863,7 +1852,18 @@
 	error = security_inode_follow_link(path.dentry, &nd);
 	if (error)
 		goto exit_dput;
+	save = nd.path;
+	path_get(&save);
 	error = __do_follow_link(&path, &nd);
+	if (error == -ESTALE) {
+		/* nd.path had been dropped */
+		nd.path = save;
+		path_get(&nd.path);
+		nd.flags |= LOOKUP_REVAL;
+		error = __do_follow_link(&path, &nd);
+	}
+	path_put(&save);
+	path_put(&path);
 	if (error) {
 		/* Does someone understand code flow here? Or it is only
 		 * me so stupid? Anathema to whoever designed this non-sense
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 2a77bc2..59e5673 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -90,7 +90,7 @@
 	  If you want your system to mount its root file system via NFS,
 	  choose Y here.  This is common practice for managing systems
 	  without local permanent storage.  For details, read
-	  <file:Documentation/filesystems/nfsroot.txt>.
+	  <file:Documentation/filesystems/nfs/nfsroot.txt>.
 
 	  Most people say N here.
 
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 7e57b04..865265b 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -108,6 +108,10 @@
 	NFS_OWNER_RECLAIM_NOGRACE
 };
 
+#define NFS_LOCK_NEW		0
+#define NFS_LOCK_RECLAIM	1
+#define NFS_LOCK_EXPIRED	2
+
 /*
  * struct nfs4_state maintains the client-side state for a given
  * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
@@ -282,6 +286,7 @@
 extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
 extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid);
 extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid);
+extern void nfs_release_seqid(struct nfs_seqid *seqid);
 extern void nfs_free_seqid(struct nfs_seqid *seqid);
 
 extern const nfs4_stateid zero_stateid;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9f5f11e..198d51d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -64,6 +64,7 @@
 
 struct nfs4_opendata;
 static int _nfs4_proc_open(struct nfs4_opendata *data);
+static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
 static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
@@ -341,6 +342,27 @@
 		free_slotid, tbl->highest_used_slotid);
 }
 
+/*
+ * Signal state manager thread if session is drained
+ */
+static void nfs41_check_drain_session_complete(struct nfs4_session *ses)
+{
+	struct rpc_task *task;
+
+	if (!test_bit(NFS4CLNT_SESSION_DRAINING, &ses->clp->cl_state)) {
+		task = rpc_wake_up_next(&ses->fc_slot_table.slot_tbl_waitq);
+		if (task)
+			rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
+		return;
+	}
+
+	if (ses->fc_slot_table.highest_used_slotid != -1)
+		return;
+
+	dprintk("%s COMPLETE: Session Drained\n", __func__);
+	complete(&ses->complete);
+}
+
 static void nfs41_sequence_free_slot(const struct nfs_client *clp,
 			      struct nfs4_sequence_res *res)
 {
@@ -356,15 +378,7 @@
 
 	spin_lock(&tbl->slot_tbl_lock);
 	nfs4_free_slot(tbl, res->sr_slotid);
-
-	/* Signal state manager thread if session is drained */
-	if (test_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) {
-		if (tbl->highest_used_slotid == -1) {
-			dprintk("%s COMPLETE: Session Drained\n", __func__);
-			complete(&clp->cl_session->complete);
-		}
-	} else
-		rpc_wake_up_next(&tbl->slot_tbl_waitq);
+	nfs41_check_drain_session_complete(clp->cl_session);
 	spin_unlock(&tbl->slot_tbl_lock);
 	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
@@ -421,7 +435,7 @@
  * Note: must be called with under the slot_tbl_lock.
  */
 static u8
-nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
+nfs4_find_slot(struct nfs4_slot_table *tbl)
 {
 	int slotid;
 	u8 ret_id = NFS4_MAX_SLOT_TABLE;
@@ -463,7 +477,8 @@
 	tbl = &session->fc_slot_table;
 
 	spin_lock(&tbl->slot_tbl_lock);
-	if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state)) {
+	if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state) &&
+	    !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
 		/*
 		 * The state manager will wait until the slot table is empty.
 		 * Schedule the reset thread
@@ -474,7 +489,15 @@
 		return -EAGAIN;
 	}
 
-	slotid = nfs4_find_slot(tbl, task);
+	if (!rpc_queue_empty(&tbl->slot_tbl_waitq) &&
+	    !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) {
+		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+		spin_unlock(&tbl->slot_tbl_lock);
+		dprintk("%s enforce FIFO order\n", __func__);
+		return -EAGAIN;
+	}
+
+	slotid = nfs4_find_slot(tbl);
 	if (slotid == NFS4_MAX_SLOT_TABLE) {
 		rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
 		spin_unlock(&tbl->slot_tbl_lock);
@@ -483,6 +506,7 @@
 	}
 	spin_unlock(&tbl->slot_tbl_lock);
 
+	rpc_task_set_priority(task, RPC_PRIORITY_NORMAL);
 	slot = tbl->slots + slotid;
 	args->sa_session = session;
 	args->sa_slotid = slotid;
@@ -545,6 +569,12 @@
 	rpc_call_start(task);
 }
 
+static void nfs41_call_priv_sync_prepare(struct rpc_task *task, void *calldata)
+{
+	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
+	nfs41_call_sync_prepare(task, calldata);
+}
+
 static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs41_call_sync_data *data = calldata;
@@ -557,12 +587,18 @@
 	.rpc_call_done = nfs41_call_sync_done,
 };
 
+struct rpc_call_ops nfs41_call_priv_sync_ops = {
+	.rpc_call_prepare = nfs41_call_priv_sync_prepare,
+	.rpc_call_done = nfs41_call_sync_done,
+};
+
 static int nfs4_call_sync_sequence(struct nfs_client *clp,
 				   struct rpc_clnt *clnt,
 				   struct rpc_message *msg,
 				   struct nfs4_sequence_args *args,
 				   struct nfs4_sequence_res *res,
-				   int cache_reply)
+				   int cache_reply,
+				   int privileged)
 {
 	int ret;
 	struct rpc_task *task;
@@ -580,6 +616,8 @@
 	};
 
 	res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+	if (privileged)
+		task_setup.callback_ops = &nfs41_call_priv_sync_ops;
 	task = rpc_run_task(&task_setup);
 	if (IS_ERR(task))
 		ret = PTR_ERR(task);
@@ -597,7 +635,7 @@
 			    int cache_reply)
 {
 	return nfs4_call_sync_sequence(server->nfs_client, server->client,
-				       msg, args, res, cache_reply);
+				       msg, args, res, cache_reply, 0);
 }
 
 #endif /* CONFIG_NFS_V4_1 */
@@ -1035,7 +1073,7 @@
 	memset(&opendata->o_res, 0, sizeof(opendata->o_res));
 	memset(&opendata->c_res, 0, sizeof(opendata->c_res));
 	nfs4_init_opendata_res(opendata);
-	ret = _nfs4_proc_open(opendata);
+	ret = _nfs4_recover_proc_open(opendata);
 	if (ret != 0)
 		return ret; 
 	newstate = nfs4_opendata_to_nfs4_state(opendata);
@@ -1326,6 +1364,12 @@
 
 }
 
+static void nfs4_recover_open_prepare(struct rpc_task *task, void *calldata)
+{
+	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
+	nfs4_open_prepare(task, calldata);
+}
+
 static void nfs4_open_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_opendata *data = calldata;
@@ -1384,10 +1428,13 @@
 	.rpc_release = nfs4_open_release,
 };
 
-/*
- * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
- */
-static int _nfs4_proc_open(struct nfs4_opendata *data)
+static const struct rpc_call_ops nfs4_recover_open_ops = {
+	.rpc_call_prepare = nfs4_recover_open_prepare,
+	.rpc_call_done = nfs4_open_done,
+	.rpc_release = nfs4_open_release,
+};
+
+static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
 {
 	struct inode *dir = data->dir->d_inode;
 	struct nfs_server *server = NFS_SERVER(dir);
@@ -1414,21 +1461,57 @@
 	data->rpc_done = 0;
 	data->rpc_status = 0;
 	data->cancelled = 0;
+	if (isrecover)
+		task_setup_data.callback_ops = &nfs4_recover_open_ops;
 	task = rpc_run_task(&task_setup_data);
-	if (IS_ERR(task))
-		return PTR_ERR(task);
-	status = nfs4_wait_for_completion_rpc_task(task);
-	if (status != 0) {
-		data->cancelled = 1;
-		smp_wmb();
-	} else
-		status = data->rpc_status;
-	rpc_put_task(task);
+        if (IS_ERR(task))
+                return PTR_ERR(task);
+        status = nfs4_wait_for_completion_rpc_task(task);
+        if (status != 0) {
+                data->cancelled = 1;
+                smp_wmb();
+        } else
+                status = data->rpc_status;
+        rpc_put_task(task);
+
+	return status;
+}
+
+static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
+{
+	struct inode *dir = data->dir->d_inode;
+	struct nfs_openres *o_res = &data->o_res;
+        int status;
+
+	status = nfs4_run_open_task(data, 1);
 	if (status != 0 || !data->rpc_done)
 		return status;
 
-	if (o_res->fh.size == 0)
-		_nfs4_proc_lookup(dir, o_arg->name, &o_res->fh, o_res->f_attr);
+	nfs_refresh_inode(dir, o_res->dir_attr);
+
+	if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
+		status = _nfs4_proc_open_confirm(data);
+		if (status != 0)
+			return status;
+	}
+
+	return status;
+}
+
+/*
+ * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
+ */
+static int _nfs4_proc_open(struct nfs4_opendata *data)
+{
+	struct inode *dir = data->dir->d_inode;
+	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_openargs *o_arg = &data->o_arg;
+	struct nfs_openres *o_res = &data->o_res;
+	int status;
+
+	status = nfs4_run_open_task(data, 0);
+	if (status != 0 || !data->rpc_done)
+		return status;
 
 	if (o_arg->open_flags & O_CREAT) {
 		update_changeattr(dir, &o_res->cinfo);
@@ -1752,11 +1835,10 @@
 			if (calldata->arg.fmode == 0)
 				break;
 		default:
-			if (nfs4_async_handle_error(task, server, state) == -EAGAIN) {
-				nfs_restart_rpc(task, server->nfs_client);
-				return;
-			}
+			if (nfs4_async_handle_error(task, server, state) == -EAGAIN)
+				rpc_restart_call_prepare(task);
 	}
+	nfs_release_seqid(calldata->arg.seqid);
 	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
 }
 
@@ -1848,8 +1930,6 @@
 	calldata->state = state;
 	calldata->arg.fh = NFS_FH(state->inode);
 	calldata->arg.stateid = &state->open_stateid;
-	if (nfs4_has_session(server->nfs_client))
-		memset(calldata->arg.stateid->data, 0, 4);    /* clear seqid */
 	/* Serialization for the sequence id */
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	if (calldata->arg.seqid == NULL)
@@ -3941,6 +4021,12 @@
 	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
 }
 
+static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
+{
+	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
+	nfs4_lock_prepare(task, calldata);
+}
+
 static void nfs4_lock_done(struct rpc_task *task, void *calldata)
 {
 	struct nfs4_lockdata *data = calldata;
@@ -3996,7 +4082,13 @@
 	.rpc_release = nfs4_lock_release,
 };
 
-static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim)
+static const struct rpc_call_ops nfs4_recover_lock_ops = {
+	.rpc_call_prepare = nfs4_recover_lock_prepare,
+	.rpc_call_done = nfs4_lock_done,
+	.rpc_release = nfs4_lock_release,
+};
+
+static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int recovery_type)
 {
 	struct nfs4_lockdata *data;
 	struct rpc_task *task;
@@ -4020,8 +4112,11 @@
 		return -ENOMEM;
 	if (IS_SETLKW(cmd))
 		data->arg.block = 1;
-	if (reclaim != 0)
-		data->arg.reclaim = 1;
+	if (recovery_type > NFS_LOCK_NEW) {
+		if (recovery_type == NFS_LOCK_RECLAIM)
+			data->arg.reclaim = NFS_LOCK_RECLAIM;
+		task_setup_data.callback_ops = &nfs4_recover_lock_ops;
+	}
 	msg.rpc_argp = &data->arg,
 	msg.rpc_resp = &data->res,
 	task_setup_data.callback_data = data;
@@ -4048,7 +4143,7 @@
 		/* Cache the lock if possible... */
 		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
 			return 0;
-		err = _nfs4_do_setlk(state, F_SETLK, request, 1);
+		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
 		if (err != -NFS4ERR_DELAY)
 			break;
 		nfs4_handle_exception(server, err, &exception);
@@ -4068,7 +4163,7 @@
 	do {
 		if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
 			return 0;
-		err = _nfs4_do_setlk(state, F_SETLK, request, 0);
+		err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_EXPIRED);
 		switch (err) {
 		default:
 			goto out;
@@ -4104,7 +4199,7 @@
 		status = do_vfs_lock(request->fl_file, request);
 		goto out_unlock;
 	}
-	status = _nfs4_do_setlk(state, cmd, request, 0);
+	status = _nfs4_do_setlk(state, cmd, request, NFS_LOCK_NEW);
 	if (status != 0)
 		goto out_unlock;
 	/* Note: we always want to sleep here! */
@@ -4187,7 +4282,7 @@
 	if (err != 0)
 		goto out;
 	do {
-		err = _nfs4_do_setlk(state, F_SETLK, fl, 0);
+		err = _nfs4_do_setlk(state, F_SETLK, fl, NFS_LOCK_NEW);
 		switch (err) {
 			default:
 				printk(KERN_ERR "%s: unhandled error %d.\n",
@@ -4395,11 +4490,12 @@
 			(struct nfs4_get_lease_time_data *)calldata;
 
 	dprintk("--> %s\n", __func__);
+	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 	/* just setup sequence, do not trigger session recovery
 	   since we're invoked within one */
 	ret = nfs41_setup_sequence(data->clp->cl_session,
-					&data->args->la_seq_args,
-					&data->res->lr_seq_res, 0, task);
+				   &data->args->la_seq_args,
+				   &data->res->lr_seq_res, 0, task);
 
 	BUG_ON(ret == -EAGAIN);
 	rpc_call_start(task);
@@ -4619,7 +4715,7 @@
 	tbl = &session->fc_slot_table;
 	tbl->highest_used_slotid = -1;
 	spin_lock_init(&tbl->slot_tbl_lock);
-	rpc_init_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
+	rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
 
 	tbl = &session->bc_slot_table;
 	tbl->highest_used_slotid = -1;
@@ -4838,14 +4934,22 @@
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_session *session;
+	unsigned int rsize, wsize;
 	int ret;
 
 	if (!nfs4_has_session(clp))
 		return 0;
 
+	rsize = server->rsize;
+	if (rsize == 0)
+		rsize = NFS_MAX_FILE_IO_SIZE;
+	wsize = server->wsize;
+	if (wsize == 0)
+		wsize = NFS_MAX_FILE_IO_SIZE;
+
 	session = clp->cl_session;
-	session->fc_attrs.max_rqst_sz = server->wsize + nfs41_maxwrite_overhead;
-	session->fc_attrs.max_resp_sz = server->rsize + nfs41_maxread_overhead;
+	session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead;
+	session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead;
 
 	ret = nfs4_recover_expired_lease(server);
 	if (!ret)
@@ -4871,7 +4975,7 @@
 	args.sa_cache_this = 0;
 
 	return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args,
-				       &res, 0);
+				       &res, args.sa_cache_this, 1);
 }
 
 void nfs41_sequence_call_done(struct rpc_task *task, void *data)
@@ -4953,6 +5057,7 @@
 {
 	struct nfs4_reclaim_complete_data *calldata = data;
 
+	rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
 	if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args,
 				&calldata->res.seq_res, 0, task))
 		return;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e76427e..6d263ed 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -135,16 +135,30 @@
 	return status;
 }
 
-static void nfs41_end_drain_session(struct nfs_client *clp,
-		struct nfs4_session *ses)
+static void nfs4_end_drain_session(struct nfs_client *clp)
 {
-	if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state))
-		rpc_wake_up(&ses->fc_slot_table.slot_tbl_waitq);
+	struct nfs4_session *ses = clp->cl_session;
+	int max_slots;
+
+	if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) {
+		spin_lock(&ses->fc_slot_table.slot_tbl_lock);
+		max_slots = ses->fc_slot_table.max_slots;
+		while (max_slots--) {
+			struct rpc_task *task;
+
+			task = rpc_wake_up_next(&ses->fc_slot_table.
+						slot_tbl_waitq);
+			if (!task)
+				break;
+			rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
+		}
+		spin_unlock(&ses->fc_slot_table.slot_tbl_lock);
+	}
 }
 
-static int nfs41_begin_drain_session(struct nfs_client *clp,
-		struct nfs4_session *ses)
+static int nfs4_begin_drain_session(struct nfs_client *clp)
 {
+	struct nfs4_session *ses = clp->cl_session;
 	struct nfs4_slot_table *tbl = &ses->fc_slot_table;
 
 	spin_lock(&tbl->slot_tbl_lock);
@@ -162,16 +176,13 @@
 {
 	int status;
 
-	status = nfs41_begin_drain_session(clp, clp->cl_session);
-	if (status != 0)
-		goto out;
+	nfs4_begin_drain_session(clp);
 	status = nfs4_proc_exchange_id(clp, cred);
 	if (status != 0)
 		goto out;
 	status = nfs4_proc_create_session(clp);
 	if (status != 0)
 		goto out;
-	nfs41_end_drain_session(clp, clp->cl_session);
 	nfs41_setup_state_renewal(clp);
 	nfs_mark_client_ready(clp, NFS_CS_READY);
 out:
@@ -755,16 +766,21 @@
 	return new;
 }
 
-void nfs_free_seqid(struct nfs_seqid *seqid)
+void nfs_release_seqid(struct nfs_seqid *seqid)
 {
 	if (!list_empty(&seqid->list)) {
 		struct rpc_sequence *sequence = seqid->sequence->sequence;
 
 		spin_lock(&sequence->lock);
-		list_del(&seqid->list);
+		list_del_init(&seqid->list);
 		spin_unlock(&sequence->lock);
 		rpc_wake_up(&sequence->wait);
 	}
+}
+
+void nfs_free_seqid(struct nfs_seqid *seqid)
+{
+	nfs_release_seqid(seqid);
 	kfree(seqid);
 }
 
@@ -1257,13 +1273,9 @@
 
 static int nfs4_reset_session(struct nfs_client *clp)
 {
-	struct nfs4_session *ses = clp->cl_session;
 	int status;
 
-	status = nfs41_begin_drain_session(clp, ses);
-	if (status != 0)
-		return status;
-
+	nfs4_begin_drain_session(clp);
 	status = nfs4_proc_destroy_session(clp->cl_session);
 	if (status && status != -NFS4ERR_BADSESSION &&
 	    status != -NFS4ERR_DEADSESSION) {
@@ -1279,19 +1291,17 @@
 out:
 	/*
 	 * Let the state manager reestablish state
-	 * without waking other tasks yet.
 	 */
-	if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
-		/* Wake up the next rpc task */
-		nfs41_end_drain_session(clp, ses);
-		if (status == 0)
-			nfs41_setup_state_renewal(clp);
-	}
+	if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
+	    status == 0)
+		nfs41_setup_state_renewal(clp);
+
 	return status;
 }
 
 #else /* CONFIG_NFS_V4_1 */
 static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
+static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
 #endif /* CONFIG_NFS_V4_1 */
 
 /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
@@ -1382,6 +1392,7 @@
 				goto out_error;
 		}
 
+		nfs4_end_drain_session(clp);
 		if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
 			nfs_client_return_marked_delegations(clp);
 			continue;
@@ -1398,6 +1409,7 @@
 out_error:
 	printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
 			" with error %d\n", clp->cl_hostname, -status);
+	nfs4_end_drain_session(clp);
 	nfs4_clear_state_manager_bit(clp);
 }
 
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 8f9a205..d3854d9 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -7,8 +7,6 @@
 #include <linux/types.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/cred.h>
 #include <linux/sched.h>
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 36fcabbf..79717a4 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -1,15 +1,7 @@
-/*
- * linux/fs/nfsd/auth.c
- *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
- */
+/* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */
 
-#include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/svcauth.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/export.h>
+#include "nfsd.h"
 #include "auth.h"
 
 int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
diff --git a/include/linux/nfsd/cache.h b/fs/nfsd/cache.h
similarity index 95%
rename from include/linux/nfsd/cache.h
rename to fs/nfsd/cache.h
index 3a3f589..d892be6 100644
--- a/include/linux/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -1,6 +1,4 @@
 /*
- * include/linux/nfsd/cache.h
- *
  * Request reply cache. This was heavily inspired by the
  * implementation in 4.3BSD/4.4BSD.
  *
@@ -10,8 +8,7 @@
 #ifndef NFSCACHE_H
 #define NFSCACHE_H
 
-#include <linux/in.h>
-#include <linux/uio.h>
+#include <linux/sunrpc/svc.h>
 
 /*
  * Representation of a reply cache entry.
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c1c9e03..c487810 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1,7 +1,5 @@
 #define MSNFS	/* HACK HACK */
 /*
- * linux/fs/nfsd/export.c
- *
  * NFS exporting and validation.
  *
  * We maintain a list of clients, each of which has a list of
@@ -14,29 +12,16 @@
  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
  */
 
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/in.h>
-#include <linux/seq_file.h>
-#include <linux/syscalls.h>
-#include <linux/rwsem.h>
-#include <linux/dcache.h>
 #include <linux/namei.h>
-#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>
 #include <net/ipv6.h>
 
+#include "nfsd.h"
+#include "nfsfh.h"
+
 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
 
 typedef struct auth_domain	svc_client;
@@ -369,16 +354,25 @@
 					    struct svc_export *old);
 static struct svc_export *svc_export_lookup(struct svc_export *);
 
-static int check_export(struct inode *inode, int flags, unsigned char *uuid)
+static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
 {
 
-	/* We currently export only dirs and regular files.
-	 * This is what umountd does.
+	/*
+	 * We currently export only dirs, regular files, and (for v4
+	 * pseudoroot) symlinks.
 	 */
 	if (!S_ISDIR(inode->i_mode) &&
+	    !S_ISLNK(inode->i_mode) &&
 	    !S_ISREG(inode->i_mode))
 		return -ENOTDIR;
 
+	/*
+	 * Mountd should never pass down a writeable V4ROOT export, but,
+	 * just to make sure:
+	 */
+	if (*flags & NFSEXP_V4ROOT)
+		*flags |= NFSEXP_READONLY;
+
 	/* There are two requirements on a filesystem to be exportable.
 	 * 1:  We must be able to identify the filesystem from a number.
 	 *       either a device number (so FS_REQUIRES_DEV needed)
@@ -387,7 +381,7 @@
 	 *       This means that s_export_op must be set.
 	 */
 	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
-	    !(flags & NFSEXP_FSID) &&
+	    !(*flags & NFSEXP_FSID) &&
 	    uuid == NULL) {
 		dprintk("exp_export: export of non-dev fs without fsid\n");
 		return -EINVAL;
@@ -602,7 +596,7 @@
 				goto out4;
 		}
 
-		err = check_export(exp.ex_path.dentry->d_inode, exp.ex_flags,
+		err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
 				   exp.ex_uuid);
 		if (err)
 			goto out4;
@@ -1041,7 +1035,7 @@
 		goto finish;
 	}
 
-	err = check_export(path.dentry->d_inode, nxp->ex_flags, NULL);
+	err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
 	if (err) goto finish;
 
 	err = -ENOMEM;
@@ -1320,6 +1314,23 @@
 	return exp;
 }
 
+static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp)
+{
+	struct svc_export *exp;
+	u32 fsidv[2];
+
+	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
+
+	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+	/*
+	 * We shouldn't have accepting an nfsv4 request at all if we
+	 * don't have a pseudoexport!:
+	 */
+	if (IS_ERR(exp) && PTR_ERR(exp) == -ENOENT)
+		exp = ERR_PTR(-ESERVERFAULT);
+	return exp;
+}
+
 /*
  * Called when we need the filehandle for the root of the pseudofs,
  * for a given NFSv4 client.   The root is defined to be the
@@ -1330,11 +1341,8 @@
 {
 	struct svc_export *exp;
 	__be32 rv;
-	u32 fsidv[2];
 
-	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
-
-	exp = rqst_exp_find(rqstp, FSID_NUM, fsidv);
+	exp = find_fsidzero_export(rqstp);
 	if (IS_ERR(exp))
 		return nfserrno(PTR_ERR(exp));
 	rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
@@ -1425,6 +1433,7 @@
 	{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
+	{ NFSEXP_V4ROOT, {"v4root", ""}},
 #ifdef MSNFS
 	{ NFSEXP_MSNFS, {"msnfs", ""}},
 #endif
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index b2786a5..0c6d816 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/lockd.c
- *
  * This file contains all the stubs needed when communicating with lockd.
  * This level of indirection is necessary so we can run nfsd+lockd without
  * requiring the nfs client to be compiled in/loaded, and vice versa.
@@ -8,14 +6,10 @@
  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/types.h>
-#include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/lockd/bind.h>
+#include "nfsd.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_LOCKD
 
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 4e3219e..f20589d 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -1,19 +1,15 @@
 /*
- * linux/fs/nfsd/nfs2acl.c
- *
  * Process version 2 NFSACL requests.
  *
  * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
  */
 
-#include <linux/sunrpc/svc.h>
-#include <linux/nfs.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/nfsd/xdr3.h>
-#include <linux/posix_acl.h>
+#include "nfsd.h"
+/* FIXME: nfsacl.h is a broken header */
 #include <linux/nfsacl.h>
+#include "cache.h"
+#include "xdr3.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 #define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
@@ -217,6 +213,16 @@
  * XDR encode functions
  */
 
+/*
+ * There must be an encoding function for void results so svc_process
+ * will work properly.
+ */
+int
+nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
+{
+	return xdr_ressize_check(rqstp, p);
+}
+
 /* GETACL */
 static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
 		struct nfsd3_getaclres *resp)
@@ -308,7 +314,6 @@
 }
 
 #define nfsaclsvc_decode_voidargs	NULL
-#define nfsaclsvc_encode_voidres	NULL
 #define nfsaclsvc_release_void		NULL
 #define nfsd3_fhandleargs	nfsd_fhandle
 #define nfsd3_attrstatres	nfsd_attrstat
@@ -346,5 +351,5 @@
 		.vs_proc	= nfsd_acl_procedures2,
 		.vs_dispatch	= nfsd_dispatch,
 		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
-		.vs_hidden	= 1,
+		.vs_hidden	= 0,
 };
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 9981dbb..e0c4846 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -1,18 +1,15 @@
 /*
- * linux/fs/nfsd/nfs3acl.c
- *
  * Process version 3 NFSACL requests.
  *
  * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
  */
 
-#include <linux/sunrpc/svc.h>
-#include <linux/nfs3.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr3.h>
-#include <linux/posix_acl.h>
+#include "nfsd.h"
+/* FIXME: nfsacl.h is a broken header */
 #include <linux/nfsacl.h>
+#include "cache.h"
+#include "xdr3.h"
+#include "vfs.h"
 
 #define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
 
@@ -264,6 +261,6 @@
 		.vs_proc	= nfsd_acl_procedures3,
 		.vs_dispatch	= nfsd_dispatch,
 		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
-		.vs_hidden	= 1,
+		.vs_hidden	= 0,
 };
 
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index a713c41..3d68f45 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -1,30 +1,16 @@
 /*
- * linux/fs/nfsd/nfs3proc.c
- *
  * Process version 3 NFS requests.
  *
  * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/linkage.h>
-#include <linux/time.h>
-#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ext2_fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/net.h>
-#include <linux/in.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/major.h>
 #include <linux/magic.h>
 
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr3.h>
-#include <linux/nfs3.h>
+#include "cache.h"
+#include "xdr3.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index d0a2ce1..2a533a0 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/nfs3xdr.c
- *
  * XDR support for nfsd/protocol version 3.
  *
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
@@ -8,19 +6,8 @@
  * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
  */
 
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/nfs3.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/dcache.h>
 #include <linux/namei.h>
-#include <linux/mm.h>
-#include <linux/vfs.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/xdr3.h>
+#include "xdr3.h"
 #include "auth.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 725d02f..8815068 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -1,6 +1,4 @@
 /*
- *  fs/nfs4acl/acl.c
- *
  *  Common NFSv4 ACL handling code.
  *
  *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
@@ -36,15 +34,7 @@
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/module.h>
 #include <linux/nfs_fs.h>
-#include <linux/posix_acl.h>
-#include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
 
 
@@ -389,7 +379,7 @@
 	sort_pacl_range(pacl, 1, i-1);
 
 	BUG_ON(pacl->a_entries[i].e_tag != ACL_GROUP_OBJ);
-	j = i++;
+	j = ++i;
 	while (pacl->a_entries[j].e_tag == ACL_GROUP)
 		j++;
 	sort_pacl_range(pacl, i, j-1);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 24e8d78..c6eed2a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1,6 +1,4 @@
 /*
- *  linux/fs/nfsd/nfs4callback.c
- *
  *  Copyright (c) 2001 The Regents of the University of Michigan.
  *  All rights reserved.
  *
@@ -33,22 +31,9 @@
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/inet.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/svcsock.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/state.h>
-#include <linux/sunrpc/sched.h>
-#include <linux/nfs4.h>
-#include <linux/sunrpc/xprtsock.h>
+#include "nfsd.h"
+#include "state.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index ba2c199..6e2983b 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -1,6 +1,4 @@
 /*
- *  fs/nfsd/nfs4idmap.c
- *
  *  Mapping of UID/GIDs to name and vice versa.
  *
  *  Copyright (c) 2002, 2003 The Regents of the University of
@@ -35,22 +33,9 @@
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/nfs.h>
-#include <linux/nfs4.h>
-#include <linux/nfs_fs.h>
-#include <linux/nfs_page.h>
-#include <linux/sunrpc/cache.h>
 #include <linux/nfsd_idmap.h>
-#include <linux/list.h>
-#include <linux/time.h>
 #include <linux/seq_file.h>
-#include <linux/sunrpc/svcauth.h>
+#include <linux/sched.h>
 
 /*
  * Cache entry
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index bebc0c2..37514c4 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1,6 +1,4 @@
 /*
- *  fs/nfsd/nfs4proc.c
- *
  *  Server-side procedures for NFSv4.
  *
  *  Copyright (c) 2002 The Regents of the University of Michigan.
@@ -34,20 +32,11 @@
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
-#include <linux/param.h>
-#include <linux/major.h>
-#include <linux/slab.h>
 #include <linux/file.h>
 
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfs4.h>
-#include <linux/nfsd/state.h>
-#include <linux/nfsd/xdr4.h>
-#include <linux/nfs4_acl.h>
-#include <linux/sunrpc/gss_api.h>
+#include "cache.h"
+#include "xdr4.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -170,7 +159,7 @@
 		accmode |= NFSD_MAY_READ;
 	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
 		accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
-	if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
+	if (open->op_share_deny & NFS4_SHARE_DENY_READ)
 		accmode |= NFSD_MAY_WRITE;
 
 	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index b534840..5a754f7 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1,6 +1,4 @@
 /*
-*  linux/fs/nfsd/nfs4recover.c
-*
 *  Copyright (c) 2004 The Regents of the University of Michigan.
 *  All rights reserved.
 *
@@ -33,20 +31,14 @@
 *
 */
 
-#include <linux/err.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfs4.h>
-#include <linux/nfsd/state.h>
-#include <linux/nfsd/xdr4.h>
-#include <linux/param.h>
 #include <linux/file.h>
 #include <linux/namei.h>
-#include <asm/uaccess.h>
-#include <linux/scatterlist.h>
 #include <linux/crypto.h>
 #include <linux/sched.h>
-#include <linux/mount.h>
+
+#include "nfsd.h"
+#include "state.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 2153f9bd..f19ed86 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1,6 +1,4 @@
 /*
-*  linux/fs/nfsd/nfs4state.c
-*
 *  Copyright (c) 2001 The Regents of the University of Michigan.
 *  All rights reserved.
 *
@@ -34,28 +32,14 @@
 *
 */
 
-#include <linux/param.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
 #include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/workqueue.h>
 #include <linux/smp_lock.h>
-#include <linux/kthread.h>
-#include <linux/nfs4.h>
-#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>
 #include <linux/sunrpc/svcauth_gss.h>
 #include <linux/sunrpc/clnt.h>
+#include "xdr4.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
@@ -477,13 +461,14 @@
 
 /*
  * fchan holds the client values on input, and the server values on output
+ * sv_max_mesg is the maximum payload plus one page for overhead.
  */
 static int init_forechannel_attrs(struct svc_rqst *rqstp,
 				  struct nfsd4_channel_attrs *session_fchan,
 				  struct nfsd4_channel_attrs *fchan)
 {
 	int status = 0;
-	__u32   maxcount = svc_max_payload(rqstp);
+	__u32   maxcount = nfsd_serv->sv_max_mesg;
 
 	/* headerpadsz set to zero in encode routine */
 
@@ -523,6 +508,15 @@
 		kfree(ses->se_slots[i]);
 }
 
+/*
+ * We don't actually need to cache the rpc and session headers, so we
+ * can allocate a little less for each slot:
+ */
+static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
+{
+	return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
+}
+
 static int
 alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
 		   struct nfsd4_create_session *cses)
@@ -554,7 +548,7 @@
 	memcpy(new, &tmp, sizeof(*new));
 
 	/* allocate each struct nfsd4_slot and data cache in one piece */
-	cachesize = new->se_fchannel.maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
+	cachesize = slot_bytes(&new->se_fchannel);
 	for (i = 0; i < new->se_fchannel.maxreqs; i++) {
 		sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
 		if (!sp)
@@ -628,10 +622,12 @@
 free_session(struct kref *kref)
 {
 	struct nfsd4_session *ses;
+	int mem;
 
 	ses = container_of(kref, struct nfsd4_session, se_ref);
 	spin_lock(&nfsd_drc_lock);
-	nfsd_drc_mem_used -= ses->se_fchannel.maxreqs * NFSD_SLOT_CACHE_SIZE;
+	mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+	nfsd_drc_mem_used -= mem;
 	spin_unlock(&nfsd_drc_lock);
 	free_session_slots(ses);
 	kfree(ses);
@@ -2404,11 +2400,8 @@
 
 	memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
 
-	dprintk("NFSD: delegation stateid=(%08x/%08x/%08x/%08x)\n\n",
-	             dp->dl_stateid.si_boot,
-	             dp->dl_stateid.si_stateownerid,
-	             dp->dl_stateid.si_fileid,
-	             dp->dl_stateid.si_generation);
+	dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
+		STATEID_VAL(&dp->dl_stateid));
 out:
 	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
 			&& flag == NFS4_OPEN_DELEGATE_NONE
@@ -2498,9 +2491,8 @@
 
 	status = nfs_ok;
 
-	dprintk("nfs4_process_open2: stateid=(%08x/%08x/%08x/%08x)\n",
-	            stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
-	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
+	dprintk("%s: stateid=" STATEID_FMT "\n", __func__,
+		STATEID_VAL(&stp->st_stateid));
 out:
 	if (fp)
 		put_nfs4_file(fp);
@@ -2666,9 +2658,8 @@
 {
 	if (time_after((unsigned long)boot_time,
 			(unsigned long)stateid->si_boot)) {
-		dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
-			stateid->si_boot, stateid->si_stateownerid,
-			stateid->si_fileid, stateid->si_generation);
+		dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
+			STATEID_VAL(stateid));
 		return 1;
 	}
 	return 0;
@@ -2680,9 +2671,8 @@
 	if (time_before((unsigned long)boot_time,
 			((unsigned long)stateid->si_boot)) &&
 	    time_before((unsigned long)(stateid->si_boot + lease_time), get_seconds())) {
-		dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
-			stateid->si_boot, stateid->si_stateownerid,
-			stateid->si_fileid, stateid->si_generation);
+		dprintk("NFSD: expired stateid " STATEID_FMT "!\n",
+			STATEID_VAL(stateid));
 		return 1;
 	}
 	return 0;
@@ -2696,9 +2686,8 @@
 	if (EXPIRED_STATEID(stateid))
 		return nfserr_expired;
 
-	dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n",
-		stateid->si_boot, stateid->si_stateownerid,
-		stateid->si_fileid, stateid->si_generation);
+	dprintk("NFSD: bad stateid " STATEID_FMT "!\n",
+		STATEID_VAL(stateid));
 	return nfserr_bad_stateid;
 }
 
@@ -2884,10 +2873,8 @@
 	struct svc_fh *current_fh = &cstate->current_fh;
 	__be32 status;
 
-	dprintk("NFSD: preprocess_seqid_op: seqid=%d " 
-			"stateid = (%08x/%08x/%08x/%08x)\n", seqid,
-		stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
-		stateid->si_generation);
+	dprintk("NFSD: %s: seqid=%d stateid = " STATEID_FMT "\n", __func__,
+		seqid, STATEID_VAL(stateid));
 
 	*stpp = NULL;
 	*sopp = NULL;
@@ -3019,12 +3006,8 @@
 	sop->so_confirmed = 1;
 	update_stateid(&stp->st_stateid);
 	memcpy(&oc->oc_resp_stateid, &stp->st_stateid, sizeof(stateid_t));
-	dprintk("NFSD: nfsd4_open_confirm: success, seqid=%d " 
-		"stateid=(%08x/%08x/%08x/%08x)\n", oc->oc_seqid,
-		         stp->st_stateid.si_boot,
-		         stp->st_stateid.si_stateownerid,
-		         stp->st_stateid.si_fileid,
-		         stp->st_stateid.si_generation);
+	dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
+		__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stateid));
 
 	nfsd4_create_clid_dir(sop->so_client);
 out:
@@ -3283,9 +3266,8 @@
 	struct nfs4_file *fp;
 	struct nfs4_delegation *dl;
 
-	dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
-                    stid->si_boot, stid->si_stateownerid,
-                    stid->si_fileid, stid->si_generation);
+	dprintk("NFSD: %s: stateid=" STATEID_FMT "\n", __func__,
+		STATEID_VAL(stid));
 
 	fp = find_file(ino);
 	if (!fp)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0fbd50c..a8587e9 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -40,24 +40,16 @@
  * at the end of nfs4svc_decode_compoundargs.
  */
 
-#include <linux/param.h>
-#include <linux/smp.h>
-#include <linux/fs.h>
 #include <linux/namei.h>
-#include <linux/vfs.h>
+#include <linux/statfs.h>
 #include <linux/utsname.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/state.h>
-#include <linux/nfsd/xdr4.h>
 #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>
 
+#include "xdr4.h"
+#include "vfs.h"
+
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
 /*
@@ -2204,11 +2196,14 @@
 	 * we will not follow the cross mount and will fill the attribtutes
 	 * directly from the mountpoint dentry.
 	 */
-	if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
-		ignore_crossmnt = 1;
-	else if (d_mountpoint(dentry)) {
+	if (nfsd_mountpoint(dentry, exp)) {
 		int err;
 
+		if (!(exp->ex_flags & NFSEXP_V4ROOT)
+				&& !attributes_need_mount(cd->rd_bmval)) {
+			ignore_crossmnt = 1;
+			goto out_encode;
+		}
 		/*
 		 * Why the heck aren't we just using nfsd_lookup??
 		 * Different "."/".." handling?  Something else?
@@ -2224,6 +2219,7 @@
 			goto out_put;
 
 	}
+out_encode:
 	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
 					cd->rd_rqstp, ignore_crossmnt);
 out_put:
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 4638635..da08560 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/nfscache.c
- *
  * Request reply cache. This is currently a global cache, but this may
  * change in the future and be a per-client cache.
  *
@@ -10,16 +8,8 @@
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
+#include "nfsd.h"
+#include "cache.h"
 
 /* Size of reply cache. Common values are:
  * 4.3BSD:	128
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 5c01fc1..2604c3e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1,46 +1,20 @@
 /*
- * linux/fs/nfsd/nfsctl.c
- *
  * Syscall interface to knfsd.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/module.h>
-
-#include <linux/linkage.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
 #include <linux/namei.h>
-#include <linux/fcntl.h>
-#include <linux/net.h>
-#include <linux/in.h>
-#include <linux/syscalls.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/pagemap.h>
-#include <linux/init.h>
-#include <linux/inet.h>
-#include <linux/string.h>
 #include <linux/ctype.h>
 
-#include <linux/nfs.h>
 #include <linux/nfsd_idmap.h>
-#include <linux/lockd/bind.h>
-#include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcsock.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/lockd/lockd.h>
 #include <linux/sunrpc/clnt.h>
 
-#include <asm/uaccess.h>
-#include <net/ipv6.h>
+#include "nfsd.h"
+#include "cache.h"
 
 /*
  *	We have a single directory with 9 nodes in it.
@@ -55,6 +29,7 @@
 	NFSD_Getfd,
 	NFSD_Getfs,
 	NFSD_List,
+	NFSD_Export_features,
 	NFSD_Fh,
 	NFSD_FO_UnlockIP,
 	NFSD_FO_UnlockFS,
@@ -173,6 +148,24 @@
 	.owner		= THIS_MODULE,
 };
 
+static int export_features_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "0x%x 0x%x\n", NFSEXP_ALLFLAGS, NFSEXP_SECINFO_FLAGS);
+	return 0;
+}
+
+static int export_features_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, export_features_show, NULL);
+}
+
+static struct file_operations export_features_operations = {
+	.open		= export_features_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
 
@@ -1330,6 +1323,8 @@
 		[NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
+		[NFSD_Export_features] = {"export_features",
+					&export_features_operations, S_IRUGO},
 		[NFSD_FO_UnlockIP] = {"unlock_ip",
 					&transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_FO_UnlockFS] = {"unlock_filesystem",
diff --git a/include/linux/nfsd/nfsd.h b/fs/nfsd/nfsd.h
similarity index 78%
rename from include/linux/nfsd/nfsd.h
rename to fs/nfsd/nfsd.h
index 510ffdd..e942a1a 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -1,6 +1,4 @@
 /*
- * linux/include/linux/nfsd/nfsd.h
- *
  * Hodge-podge collection of knfsd-related stuff.
  * I will sort this out later.
  *
@@ -11,13 +9,9 @@
 #define LINUX_NFSD_NFSD_H
 
 #include <linux/types.h>
-#include <linux/unistd.h>
-#include <linux/fs.h>
-#include <linux/posix_acl.h>
 #include <linux/mount.h>
 
 #include <linux/nfsd/debug.h>
-#include <linux/nfsd/nfsfh.h>
 #include <linux/nfsd/export.h>
 #include <linux/nfsd/stats.h>
 /*
@@ -25,30 +19,10 @@
  */
 #define NFSD_SUPPORTED_MINOR_VERSION	1
 
-/*
- * Flags for nfsd_permission
- */
-#define NFSD_MAY_NOP		0
-#define NFSD_MAY_EXEC		1 /* == MAY_EXEC */
-#define NFSD_MAY_WRITE		2 /* == MAY_WRITE */
-#define NFSD_MAY_READ		4 /* == MAY_READ */
-#define NFSD_MAY_SATTR		8
-#define NFSD_MAY_TRUNC		16
-#define NFSD_MAY_LOCK		32
-#define NFSD_MAY_OWNER_OVERRIDE	64
-#define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
-#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
-
-#define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
-#define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
-
-/*
- * Callback function for readdir
- */
 struct readdir_cd {
 	__be32			err;	/* 0, nfserr, or nfserr_eof */
 };
-typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
+
 
 extern struct svc_program	nfsd_program;
 extern struct svc_version	nfsd_version2, nfsd_version3,
@@ -73,69 +47,6 @@
 int		nfsd_get_nrthreads(int n, int *);
 int		nfsd_set_nrthreads(int n, int *);
 
-/* nfsd/vfs.c */
-int		fh_lock_parent(struct svc_fh *, struct dentry *);
-int		nfsd_racache_init(int);
-void		nfsd_racache_shutdown(void);
-int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
-		                struct svc_export **expp);
-__be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
-				const char *, unsigned int, struct svc_fh *);
-__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
-				const char *, unsigned int,
-				struct svc_export **, struct dentry **);
-__be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
-				struct iattr *, int, time_t);
-#ifdef CONFIG_NFSD_V4
-__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
-                    struct nfs4_acl *);
-int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
-#endif /* CONFIG_NFSD_V4 */
-__be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
-				char *name, int len, struct iattr *attrs,
-				int type, dev_t rdev, struct svc_fh *res);
-#ifdef CONFIG_NFSD_V3
-__be32		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
-__be32		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
-				char *name, int len, struct iattr *attrs,
-				struct svc_fh *res, int createmode,
-				u32 *verifier, int *truncp, int *created);
-__be32		nfsd_commit(struct svc_rqst *, struct svc_fh *,
-				loff_t, unsigned long);
-#endif /* CONFIG_NFSD_V3 */
-__be32		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
-				int, struct file **);
-void		nfsd_close(struct file *);
-__be32 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
-				loff_t, struct kvec *, int, unsigned long *);
-__be32 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
-				loff_t, struct kvec *,int, unsigned long *, int *);
-__be32		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
-				char *, int *);
-__be32		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
-				char *name, int len, char *path, int plen,
-				struct svc_fh *res, struct iattr *);
-__be32		nfsd_link(struct svc_rqst *, struct svc_fh *,
-				char *, int, struct svc_fh *);
-__be32		nfsd_rename(struct svc_rqst *,
-				struct svc_fh *, char *, int,
-				struct svc_fh *, char *, int);
-__be32		nfsd_remove(struct svc_rqst *,
-				struct svc_fh *, char *, int);
-__be32		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
-				char *name, int len);
-int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
-				unsigned long size);
-__be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
-			     loff_t *, struct readdir_cd *, filldir_t);
-__be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
-				struct kstatfs *, int access);
-
-int		nfsd_notify_change(struct inode *, struct iattr *);
-__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)
 #ifdef CONFIG_NFSD_V2_ACL
 extern struct svc_version nfsd_acl_version2;
@@ -147,8 +58,6 @@
 #else
 #define nfsd_acl_version3 NULL
 #endif
-struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
-int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
 #endif
 
 enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
@@ -159,6 +68,11 @@
 
 extern int nfsd_max_blksize;
 
+static inline int nfsd_v4client(struct svc_rqst *rq)
+{
+	return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
+}
+
 /* 
  * NFSv4 State
  */
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 01965b2..1c12177 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/nfsfh.c
- *
  * NFS server file handle treatment.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
@@ -9,19 +7,11 @@
  * ... and again Southern-Winter 2001 to support export_operations
  */
 
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/unistd.h>
-#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>
+#include "nfsd.h"
+#include "vfs.h"
 #include "auth.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_FH
@@ -96,8 +86,10 @@
 static __be32 nfsd_setuser_and_check_port(struct svc_rqst *rqstp,
 					  struct svc_export *exp)
 {
+	int flags = nfsexp_flags(rqstp, exp);
+
 	/* Check if the request originated from a secure port. */
-	if (!rqstp->rq_secure && EX_SECURE(exp)) {
+	if (!rqstp->rq_secure && (flags & NFSEXP_INSECURE_PORT)) {
 		RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
 		dprintk(KERN_WARNING
 		       "nfsd: request from insecure port %s!\n",
@@ -109,6 +101,36 @@
 	return nfserrno(nfsd_setuser(rqstp, exp));
 }
 
+static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
+	struct dentry *dentry, struct svc_export *exp)
+{
+	if (!(exp->ex_flags & NFSEXP_V4ROOT))
+		return nfs_ok;
+	/*
+	 * v2/v3 clients have no need for the V4ROOT export--they use
+	 * the mount protocl instead; also, further V4ROOT checks may be
+	 * in v4-specific code, in which case v2/v3 clients could bypass
+	 * them.
+	 */
+	if (!nfsd_v4client(rqstp))
+		return nfserr_stale;
+	/*
+	 * We're exposing only the directories and symlinks that have to be
+	 * traversed on the way to real exports:
+	 */
+	if (unlikely(!S_ISDIR(dentry->d_inode->i_mode) &&
+		     !S_ISLNK(dentry->d_inode->i_mode)))
+		return nfserr_stale;
+	/*
+	 * A pseudoroot export gives permission to access only one
+	 * single directory; the kernel has to make another upcall
+	 * before granting access to anything else under it:
+	 */
+	if (unlikely(dentry != exp->ex_path.dentry))
+		return nfserr_stale;
+	return nfs_ok;
+}
+
 /*
  * Use the given filehandle to look up the corresponding export and
  * dentry.  On success, the results are used to set fh_export and
@@ -232,14 +254,6 @@
 		goto out;
 	}
 
-	if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) {
-		error = nfsd_setuser_and_check_port(rqstp, exp);
-		if (error) {
-			dput(dentry);
-			goto out;
-		}
-	}
-
 	if (S_ISDIR(dentry->d_inode->i_mode) &&
 			(dentry->d_flags & DCACHE_DISCONNECTED)) {
 		printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
@@ -294,28 +308,32 @@
 		error = nfsd_set_fh_dentry(rqstp, fhp);
 		if (error)
 			goto out;
-		dentry = fhp->fh_dentry;
-		exp = fhp->fh_export;
-	} else {
-		/*
-		 * just rechecking permissions
-		 * (e.g. nfsproc_create calls fh_verify, then nfsd_create
-		 * does as well)
-		 */
-		dprintk("nfsd: fh_verify - just checking\n");
-		dentry = fhp->fh_dentry;
-		exp = fhp->fh_export;
-		/*
-		 * Set user creds for this exportpoint; necessary even
-		 * in the "just checking" case because this may be a
-		 * filehandle that was created by fh_compose, and that
-		 * is about to be used in another nfsv4 compound
-		 * operation.
-		 */
-		error = nfsd_setuser_and_check_port(rqstp, exp);
-		if (error)
-			goto out;
 	}
+	dentry = fhp->fh_dentry;
+	exp = fhp->fh_export;
+	/*
+	 * We still have to do all these permission checks, even when
+	 * fh_dentry is already set:
+	 * 	- fh_verify may be called multiple times with different
+	 * 	  "access" arguments (e.g. nfsd_proc_create calls
+	 * 	  fh_verify(...,NFSD_MAY_EXEC) first, then later (in
+	 * 	  nfsd_create) calls fh_verify(...,NFSD_MAY_CREATE).
+	 *	- in the NFSv4 case, the filehandle may have been filled
+	 *	  in by fh_compose, and given a dentry, but further
+	 *	  compound operations performed with that filehandle
+	 *	  still need permissions checks.  In the worst case, a
+	 *	  mountpoint crossing may have changed the export
+	 *	  options, and we may now need to use a different uid
+	 *	  (for example, if different id-squashing options are in
+	 *	  effect on the new filesystem).
+	 */
+	error = check_pseudo_root(rqstp, dentry, exp);
+	if (error)
+		goto out;
+
+	error = nfsd_setuser_and_check_port(rqstp, exp);
+	if (error)
+		goto out;
 
 	error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
 	if (error)
diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h
new file mode 100644
index 0000000..cdfb8c6
--- /dev/null
+++ b/fs/nfsd/nfsfh.h
@@ -0,0 +1,208 @@
+/* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> */
+
+#ifndef _LINUX_NFSD_FH_INT_H
+#define _LINUX_NFSD_FH_INT_H
+
+#include <linux/nfsd/nfsfh.h>
+
+enum nfsd_fsid {
+	FSID_DEV = 0,
+	FSID_NUM,
+	FSID_MAJOR_MINOR,
+	FSID_ENCODE_DEV,
+	FSID_UUID4_INUM,
+	FSID_UUID8,
+	FSID_UUID16,
+	FSID_UUID16_INUM,
+};
+
+enum fsid_source {
+	FSIDSOURCE_DEV,
+	FSIDSOURCE_FSID,
+	FSIDSOURCE_UUID,
+};
+extern enum fsid_source fsid_source(struct svc_fh *fhp);
+
+
+/* This might look a little large to "inline" but in all calls except
+ * one, 'vers' is constant so moste of the function disappears.
+ */
+static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
+			   u32 fsid, unsigned char *uuid)
+{
+	u32 *up;
+	switch(vers) {
+	case FSID_DEV:
+		fsidv[0] = htonl((MAJOR(dev)<<16) |
+				 MINOR(dev));
+		fsidv[1] = ino_t_to_u32(ino);
+		break;
+	case FSID_NUM:
+		fsidv[0] = fsid;
+		break;
+	case FSID_MAJOR_MINOR:
+		fsidv[0] = htonl(MAJOR(dev));
+		fsidv[1] = htonl(MINOR(dev));
+		fsidv[2] = ino_t_to_u32(ino);
+		break;
+
+	case FSID_ENCODE_DEV:
+		fsidv[0] = new_encode_dev(dev);
+		fsidv[1] = ino_t_to_u32(ino);
+		break;
+
+	case FSID_UUID4_INUM:
+		/* 4 byte fsid and inode number */
+		up = (u32*)uuid;
+		fsidv[0] = ino_t_to_u32(ino);
+		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
+		break;
+
+	case FSID_UUID8:
+		/* 8 byte fsid  */
+		up = (u32*)uuid;
+		fsidv[0] = up[0] ^ up[2];
+		fsidv[1] = up[1] ^ up[3];
+		break;
+
+	case FSID_UUID16:
+		/* 16 byte fsid - NFSv3+ only */
+		memcpy(fsidv, uuid, 16);
+		break;
+
+	case FSID_UUID16_INUM:
+		/* 8 byte inode and 16 byte fsid */
+		*(u64*)fsidv = (u64)ino;
+		memcpy(fsidv+2, uuid, 16);
+		break;
+	default: BUG();
+	}
+}
+
+static inline int key_len(int type)
+{
+	switch(type) {
+	case FSID_DEV:		return 8;
+	case FSID_NUM: 		return 4;
+	case FSID_MAJOR_MINOR:	return 12;
+	case FSID_ENCODE_DEV:	return 8;
+	case FSID_UUID4_INUM:	return 8;
+	case FSID_UUID8:	return 8;
+	case FSID_UUID16:	return 16;
+	case FSID_UUID16_INUM:	return 24;
+	default: return 0;
+	}
+}
+
+/*
+ * Shorthand for dprintk()'s
+ */
+extern char * SVCFH_fmt(struct svc_fh *fhp);
+
+/*
+ * Function prototypes
+ */
+__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
+__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
+__be32	fh_update(struct svc_fh *);
+void	fh_put(struct svc_fh *);
+
+static __inline__ struct svc_fh *
+fh_copy(struct svc_fh *dst, struct svc_fh *src)
+{
+	WARN_ON(src->fh_dentry || src->fh_locked);
+			
+	*dst = *src;
+	return dst;
+}
+
+static inline void
+fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
+{
+	dst->fh_size = src->fh_size;
+	memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
+}
+
+static __inline__ struct svc_fh *
+fh_init(struct svc_fh *fhp, int maxsize)
+{
+	memset(fhp, 0, sizeof(*fhp));
+	fhp->fh_maxsize = maxsize;
+	return fhp;
+}
+
+#ifdef CONFIG_NFSD_V3
+/*
+ * Fill in the pre_op attr for the wcc data
+ */
+static inline void
+fill_pre_wcc(struct svc_fh *fhp)
+{
+	struct inode    *inode;
+
+	inode = fhp->fh_dentry->d_inode;
+	if (!fhp->fh_pre_saved) {
+		fhp->fh_pre_mtime = inode->i_mtime;
+		fhp->fh_pre_ctime = inode->i_ctime;
+		fhp->fh_pre_size  = inode->i_size;
+		fhp->fh_pre_change = inode->i_version;
+		fhp->fh_pre_saved = 1;
+	}
+}
+
+extern void fill_post_wcc(struct svc_fh *);
+#else
+#define	fill_pre_wcc(ignored)
+#define fill_post_wcc(notused)
+#endif /* CONFIG_NFSD_V3 */
+
+
+/*
+ * Lock a file handle/inode
+ * NOTE: both fh_lock and fh_unlock are done "by hand" in
+ * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
+ * so, any changes here should be reflected there.
+ */
+
+static inline void
+fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
+{
+	struct dentry	*dentry = fhp->fh_dentry;
+	struct inode	*inode;
+
+	BUG_ON(!dentry);
+
+	if (fhp->fh_locked) {
+		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name);
+		return;
+	}
+
+	inode = dentry->d_inode;
+	mutex_lock_nested(&inode->i_mutex, subclass);
+	fill_pre_wcc(fhp);
+	fhp->fh_locked = 1;
+}
+
+static inline void
+fh_lock(struct svc_fh *fhp)
+{
+	fh_lock_nested(fhp, I_MUTEX_NORMAL);
+}
+
+/*
+ * Unlock a file handle/inode
+ */
+static inline void
+fh_unlock(struct svc_fh *fhp)
+{
+	BUG_ON(!fhp->fh_dentry);
+
+	if (fhp->fh_locked) {
+		fill_post_wcc(fhp);
+		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
+		fhp->fh_locked = 0;
+	}
+}
+
+#endif /* _LINUX_NFSD_FH_INT_H */
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0eb9c82..a047ad6 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -1,29 +1,14 @@
 /*
- * nfsproc2.c	Process version 2 NFS requests.
- * linux/fs/nfsd/nfs2proc.c
- * 
  * Process version 2 NFS requests.
  *
  * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/linkage.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/net.h>
-#include <linux/in.h>
 #include <linux/namei.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
 
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/xdr.h>
+#include "cache.h"
+#include "xdr.h"
+#include "vfs.h"
 
 typedef struct svc_rqst	svc_rqst;
 typedef struct svc_buf	svc_buf;
@@ -758,6 +743,7 @@
 		{ nfserr_io, -ETXTBSY },
 		{ nfserr_notsupp, -EOPNOTSUPP },
 		{ nfserr_toosmall, -ETOOSMALL },
+		{ nfserr_serverfault, -ESERVERFAULT },
 	};
 	int	i;
 
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 67ea83e..171699e 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/nfssvc.c
- *
  * Central processing for nfsd.
  *
  * Authors:	Olaf Kirch (okir@monad.swb.de)
@@ -8,33 +6,19 @@
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/nfs.h>
-#include <linux/in.h>
-#include <linux/uio.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
 #include <linux/freezer.h>
 #include <linux/fs_struct.h>
-#include <linux/kthread.h>
 #include <linux/swap.h>
 
-#include <linux/sunrpc/types.h>
 #include <linux/sunrpc/stats.h>
-#include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcsock.h>
-#include <linux/sunrpc/cache.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/stats.h>
-#include <linux/nfsd/cache.h>
-#include <linux/nfsd/syscall.h>
 #include <linux/lockd/bind.h>
 #include <linux/nfsacl.h>
 #include <linux/seq_file.h>
+#include "nfsd.h"
+#include "cache.h"
+#include "vfs.h"
 
 #define NFSDDBG_FACILITY	NFSDDBG_SVC
 
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index afd08e2..4ce005d 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -1,20 +1,10 @@
 /*
- * linux/fs/nfsd/nfsxdr.c
- *
  * XDR support for nfsd
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/nfs.h>
-#include <linux/vfs.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#include <linux/nfsd/xdr.h>
-#include <linux/mm.h>
+#include "xdr.h"
 #include "auth.h"
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
diff --git a/include/linux/nfsd/state.h b/fs/nfsd/state.h
similarity index 98%
rename from include/linux/nfsd/state.h
rename to fs/nfsd/state.h
index b38d113..fefeae2 100644
--- a/include/linux/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -1,6 +1,4 @@
 /*
- *  linux/include/nfsd/state.h
- *
  *  Copyright (c) 2001 The Regents of the University of Michigan.
  *  All rights reserved.
  *
@@ -37,9 +35,8 @@
 #ifndef _NFSD4_STATE_H
 #define _NFSD4_STATE_H
 
-#include <linux/list.h>
-#include <linux/kref.h>
-#include <linux/sunrpc/clnt.h>
+#include <linux/nfsd/nfsfh.h>
+#include "nfsfh.h"
 
 typedef struct {
 	u32             cl_boot;
@@ -60,6 +57,13 @@
 #define si_stateownerid   si_opaque.so_stateownerid
 #define si_fileid         si_opaque.so_fileid
 
+#define STATEID_FMT	"(%08x/%08x/%08x/%08x)"
+#define STATEID_VAL(s) \
+	(s)->si_boot, \
+	(s)->si_stateownerid, \
+	(s)->si_fileid, \
+	(s)->si_generation
+
 struct nfsd4_cb_sequence {
 	/* args/res */
 	u32			cbs_minorversion;
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 71944cd..5232d3e 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -1,6 +1,4 @@
 /*
- * linux/fs/nfsd/stats.c
- *
  * procfs-based user access to knfsd statistics
  *
  * /proc/net/rpc/nfsd
@@ -23,18 +21,13 @@
  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  */
 
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/stat.h>
 #include <linux/module.h>
-
-#include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/stats.h>
-#include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/stats.h>
 
+#include "nfsd.h"
+
 struct nfsd_stats	nfsdstats;
 struct svc_stat		nfsd_svcstats = {
 	.program	= &nfsd_program,
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index a293f02..7c2e337 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1,7 +1,5 @@
 #define MSNFS	/* HACK HACK */
 /*
- * linux/fs/nfsd/vfs.c
- *
  * File operations used by nfsd. Some of these have been ripped from
  * other parts of the kernel because they weren't exported, others
  * are partial duplicates with added or changed functionality.
@@ -16,49 +14,32 @@
  * Zerocpy NFS support (C) 2002 Hirokazu Takahashi <taka@valinux.co.jp>
  */
 
-#include <linux/string.h>
-#include <linux/time.h>
-#include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/major.h>
 #include <linux/splice.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <linux/net.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/in.h>
-#include <linux/module.h>
 #include <linux/namei.h>
-#include <linux/vfs.h>
 #include <linux/delay.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/nfsd/nfsd.h>
-#ifdef CONFIG_NFSD_V3
-#include <linux/nfs3.h>
-#include <linux/nfsd/xdr3.h>
-#endif /* CONFIG_NFSD_V3 */
-#include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 #include <linux/fsnotify.h>
-#include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/xattr.h>
-#ifdef CONFIG_NFSD_V4
-#include <linux/nfs4.h>
-#include <linux/nfs4_acl.h>
-#include <linux/nfsd_idmap.h>
-#include <linux/security.h>
-#endif /* CONFIG_NFSD_V4 */
 #include <linux/jhash.h>
 #include <linux/ima.h>
-
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_NFSD_V3
+#include "xdr3.h"
+#endif /* CONFIG_NFSD_V3 */
+
+#ifdef CONFIG_NFSD_V4
+#include <linux/nfs4_acl.h>
+#include <linux/nfsd_idmap.h>
+#endif /* CONFIG_NFSD_V4 */
+
+#include "nfsd.h"
+#include "vfs.h"
+
 #define NFSDDBG_FACILITY		NFSDDBG_FILEOP
 
 
@@ -89,12 +70,6 @@
 #define RAPARM_HASH_MASK	(RAPARM_HASH_SIZE-1)
 static struct raparm_hbucket	raparm_hash[RAPARM_HASH_SIZE];
 
-static inline int
-nfsd_v4client(struct svc_rqst *rq)
-{
-    return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
-}
-
 /* 
  * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
  * a mount point.
@@ -116,8 +91,16 @@
 
 	exp2 = rqst_exp_get_by_name(rqstp, &path);
 	if (IS_ERR(exp2)) {
-		if (PTR_ERR(exp2) != -ENOENT)
-			err = PTR_ERR(exp2);
+		err = PTR_ERR(exp2);
+		/*
+		 * We normally allow NFS clients to continue
+		 * "underneath" a mountpoint that is not exported.
+		 * The exception is V4ROOT, where no traversal is ever
+		 * allowed without an explicit export of the new
+		 * directory.
+		 */
+		if (err == -ENOENT && !(exp->ex_flags & NFSEXP_V4ROOT))
+			err = 0;
 		path_put(&path);
 		goto out;
 	}
@@ -141,6 +124,53 @@
 	return err;
 }
 
+static void follow_to_parent(struct path *path)
+{
+	struct dentry *dp;
+
+	while (path->dentry == path->mnt->mnt_root && follow_up(path))
+		;
+	dp = dget_parent(path->dentry);
+	dput(path->dentry);
+	path->dentry = dp;
+}
+
+static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp)
+{
+	struct svc_export *exp2;
+	struct path path = {.mnt = mntget((*exp)->ex_path.mnt),
+			    .dentry = dget(dparent)};
+
+	follow_to_parent(&path);
+
+	exp2 = rqst_exp_parent(rqstp, &path);
+	if (PTR_ERR(exp2) == -ENOENT) {
+		*dentryp = dget(dparent);
+	} else if (IS_ERR(exp2)) {
+		path_put(&path);
+		return PTR_ERR(exp2);
+	} else {
+		*dentryp = dget(path.dentry);
+		exp_put(*exp);
+		*exp = exp2;
+	}
+	path_put(&path);
+	return 0;
+}
+
+/*
+ * For nfsd purposes, we treat V4ROOT exports as though there was an
+ * export at *every* directory.
+ */
+int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
+{
+	if (d_mountpoint(dentry))
+		return 1;
+	if (!(exp->ex_flags & NFSEXP_V4ROOT))
+		return 0;
+	return dentry->d_inode != NULL;
+}
+
 __be32
 nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
 		   const char *name, unsigned int len,
@@ -169,35 +199,13 @@
 			dentry = dget(dparent);
 		else if (dparent != exp->ex_path.dentry)
 			dentry = dget_parent(dparent);
-		else if (!EX_NOHIDE(exp))
+		else if (!EX_NOHIDE(exp) && !nfsd_v4client(rqstp))
 			dentry = dget(dparent); /* .. == . just like at / */
 		else {
 			/* checking mountpoint crossing is very different when stepping up */
-			struct svc_export *exp2 = NULL;
-			struct dentry *dp;
-			struct path path = {.mnt = mntget(exp->ex_path.mnt),
-					    .dentry = dget(dparent)};
-
-			while (path.dentry == path.mnt->mnt_root &&
-			       follow_up(&path))
-				;
-			dp = dget_parent(path.dentry);
-			dput(path.dentry);
-			path.dentry = dp;
-
-			exp2 = rqst_exp_parent(rqstp, &path);
-			if (PTR_ERR(exp2) == -ENOENT) {
-				dentry = dget(dparent);
-			} else if (IS_ERR(exp2)) {
-				host_err = PTR_ERR(exp2);
-				path_put(&path);
+			host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry);
+			if (host_err)
 				goto out_nfserr;
-			} else {
-				dentry = dget(path.dentry);
-				exp_put(exp);
-				exp = exp2;
-			}
-			path_put(&path);
 		}
 	} else {
 		fh_lock(fhp);
@@ -208,7 +216,7 @@
 		/*
 		 * check if we have crossed a mount point ...
 		 */
-		if (d_mountpoint(dentry)) {
+		if (nfsd_mountpoint(dentry, exp)) {
 			if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
 				dput(dentry);
 				goto out_nfserr;
@@ -744,8 +752,6 @@
 			    flags, current_cred());
 	if (IS_ERR(*filp))
 		host_err = PTR_ERR(*filp);
-	else
-		ima_counts_get(*filp);
 out_nfserr:
 	err = nfserrno(host_err);
 out:
@@ -2124,8 +2130,7 @@
 	 */
 	path.mnt = exp->ex_path.mnt;
 	path.dentry = dentry;
-	err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
-			     IMA_COUNT_LEAVE);
+	err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC));
 nfsd_out:
 	return err? nfserrno(err) : 0;
 }
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
new file mode 100644
index 0000000..4b1de0a
--- /dev/null
+++ b/fs/nfsd/vfs.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef LINUX_NFSD_VFS_H
+#define LINUX_NFSD_VFS_H
+
+#include "nfsfh.h"
+
+/*
+ * Flags for nfsd_permission
+ */
+#define NFSD_MAY_NOP		0
+#define NFSD_MAY_EXEC		1 /* == MAY_EXEC */
+#define NFSD_MAY_WRITE		2 /* == MAY_WRITE */
+#define NFSD_MAY_READ		4 /* == MAY_READ */
+#define NFSD_MAY_SATTR		8
+#define NFSD_MAY_TRUNC		16
+#define NFSD_MAY_LOCK		32
+#define NFSD_MAY_OWNER_OVERRIDE	64
+#define NFSD_MAY_LOCAL_ACCESS	128 /* IRIX doing local access check on device special file*/
+#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
+
+#define NFSD_MAY_CREATE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE)
+#define NFSD_MAY_REMOVE		(NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
+
+/*
+ * Callback function for readdir
+ */
+typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
+
+/* nfsd/vfs.c */
+int		fh_lock_parent(struct svc_fh *, struct dentry *);
+int		nfsd_racache_init(int);
+void		nfsd_racache_shutdown(void);
+int		nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
+		                struct svc_export **expp);
+__be32		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
+				const char *, unsigned int, struct svc_fh *);
+__be32		 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *,
+				const char *, unsigned int,
+				struct svc_export **, struct dentry **);
+__be32		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+				struct iattr *, int, time_t);
+int nfsd_mountpoint(struct dentry *, struct svc_export *);
+#ifdef CONFIG_NFSD_V4
+__be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+                    struct nfs4_acl *);
+int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+#endif /* CONFIG_NFSD_V4 */
+__be32		nfsd_create(struct svc_rqst *, struct svc_fh *,
+				char *name, int len, struct iattr *attrs,
+				int type, dev_t rdev, struct svc_fh *res);
+#ifdef CONFIG_NFSD_V3
+__be32		nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
+__be32		nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
+				char *name, int len, struct iattr *attrs,
+				struct svc_fh *res, int createmode,
+				u32 *verifier, int *truncp, int *created);
+__be32		nfsd_commit(struct svc_rqst *, struct svc_fh *,
+				loff_t, unsigned long);
+#endif /* CONFIG_NFSD_V3 */
+__be32		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
+				int, struct file **);
+void		nfsd_close(struct file *);
+__be32 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
+				loff_t, struct kvec *, int, unsigned long *);
+__be32 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
+				loff_t, struct kvec *,int, unsigned long *, int *);
+__be32		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
+				char *, int *);
+__be32		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
+				char *name, int len, char *path, int plen,
+				struct svc_fh *res, struct iattr *);
+__be32		nfsd_link(struct svc_rqst *, struct svc_fh *,
+				char *, int, struct svc_fh *);
+__be32		nfsd_rename(struct svc_rqst *,
+				struct svc_fh *, char *, int,
+				struct svc_fh *, char *, int);
+__be32		nfsd_remove(struct svc_rqst *,
+				struct svc_fh *, char *, int);
+__be32		nfsd_unlink(struct svc_rqst *, struct svc_fh *, int type,
+				char *name, int len);
+int		nfsd_truncate(struct svc_rqst *, struct svc_fh *,
+				unsigned long size);
+__be32		nfsd_readdir(struct svc_rqst *, struct svc_fh *,
+			     loff_t *, struct readdir_cd *, filldir_t);
+__be32		nfsd_statfs(struct svc_rqst *, struct svc_fh *,
+				struct kstatfs *, int access);
+
+int		nfsd_notify_change(struct inode *, struct iattr *);
+__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)
+struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
+int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+#endif
+
+#endif /* LINUX_NFSD_VFS_H */
diff --git a/include/linux/nfsd/xdr.h b/fs/nfsd/xdr.h
similarity index 96%
rename from include/linux/nfsd/xdr.h
rename to fs/nfsd/xdr.h
index a0132ef..53b1863 100644
--- a/include/linux/nfsd/xdr.h
+++ b/fs/nfsd/xdr.h
@@ -1,15 +1,11 @@
-/*
- * linux/include/linux/nfsd/xdr.h
- *
- * XDR types for nfsd. This is mainly a typing exercise.
- */
+/* XDR types for nfsd. This is mainly a typing exercise. */
 
 #ifndef LINUX_NFSD_H
 #define LINUX_NFSD_H
 
-#include <linux/fs.h>
 #include <linux/vfs.h>
-#include <linux/nfs.h>
+#include "nfsd.h"
+#include "nfsfh.h"
 
 struct nfsd_fhandle {
 	struct svc_fh		fh;
diff --git a/include/linux/nfsd/xdr3.h b/fs/nfsd/xdr3.h
similarity index 98%
rename from include/linux/nfsd/xdr3.h
rename to fs/nfsd/xdr3.h
index 421eddd..7df980e 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/fs/nfsd/xdr3.h
@@ -1,6 +1,4 @@
 /*
- * linux/include/linux/nfsd/xdr3.h
- *
  * XDR types for NFSv3 in nfsd.
  *
  * Copyright (C) 1996-1998, Olaf Kirch <okir@monad.swb.de>
@@ -9,7 +7,7 @@
 #ifndef _LINUX_NFSD_XDR3_H
 #define _LINUX_NFSD_XDR3_H
 
-#include <linux/nfsd/xdr.h>
+#include "xdr.h"
 
 struct nfsd3_sattrargs {
 	struct svc_fh		fh;
diff --git a/include/linux/nfsd/xdr4.h b/fs/nfsd/xdr4.h
similarity index 99%
rename from include/linux/nfsd/xdr4.h
rename to fs/nfsd/xdr4.h
index 73164c2..efa3377 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -1,6 +1,4 @@
 /*
- *  include/linux/nfsd/xdr4.h
- *
  *  Server-side types for NFSv4.
  *
  *  Copyright (c) 2002 The Regents of the University of Michigan.
@@ -39,7 +37,8 @@
 #ifndef _LINUX_NFSD_XDR4_H
 #define _LINUX_NFSD_XDR4_H
 
-#include <linux/nfs4.h>
+#include "state.h"
+#include "nfsd.h"
 
 #define NFSD4_MAX_TAGLEN	128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
index 1225af7..251da07 100644
--- a/fs/nilfs2/Kconfig
+++ b/fs/nilfs2/Kconfig
@@ -2,7 +2,6 @@
 	tristate "NILFS2 file system support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	select CRC32
-	select FS_JOURNAL_INFO
 	help
 	  NILFS2 is a log-structured file system (LFS) supporting continuous
 	  snapshotting.  In addition to versioning capability of the entire
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 5403b3e..8173fae 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -1118,8 +1118,7 @@
 	/* Abandoning the newly allocated superblock */
 	mutex_unlock(&nilfs->ns_mount_mutex);
 	put_nilfs(nilfs);
-	up_write(&s->s_umount);
-	deactivate_super(s);
+	deactivate_locked_super(s);
 	/*
 	 * deactivate_super() invokes close_bdev_exclusive().
 	 * We must finish all post-cleaning before this call;
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 5ef5f36..8271cf0 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -646,6 +646,7 @@
 	struct fsnotify_group *group;
 	struct user_struct *user;
 	struct file *filp;
+	struct path path;
 	int fd, ret;
 
 	/* Check the IN_* constants for consistency.  */
@@ -659,12 +660,6 @@
 	if (fd < 0)
 		return fd;
 
-	filp = get_empty_filp();
-	if (!filp) {
-		ret = -ENFILE;
-		goto out_put_fd;
-	}
-
 	user = get_current_user();
 	if (unlikely(atomic_read(&user->inotify_devs) >=
 			inotify_max_user_instances)) {
@@ -679,24 +674,28 @@
 		goto out_free_uid;
 	}
 
-	filp->f_op = &inotify_fops;
-	filp->f_path.mnt = mntget(inotify_mnt);
-	filp->f_path.dentry = dget(inotify_mnt->mnt_root);
-	filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping;
-	filp->f_mode = FMODE_READ;
+	atomic_inc(&user->inotify_devs);
+
+	path.mnt = inotify_mnt;
+	path.dentry = inotify_mnt->mnt_root;
+	path_get(&path);
+	filp = alloc_file(&path, FMODE_READ, &inotify_fops);
+	if (!filp)
+		goto Enfile;
+
 	filp->f_flags = O_RDONLY | (flags & O_NONBLOCK);
 	filp->private_data = group;
 
-	atomic_inc(&user->inotify_devs);
-
 	fd_install(fd, filp);
 
 	return fd;
 
+Enfile:
+	ret = -ENFILE;
+	path_put(&path);
+	atomic_dec(&user->inotify_devs);
 out_free_uid:
 	free_uid(user);
-	put_filp(filp);
-out_put_fd:
 	put_unused_fd(fd);
 	return ret;
 }
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 9938034..dc2505a 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -530,7 +530,7 @@
  * the ntfs inode.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *    i_flags is set to 0 and we have no business touching it.  Only an ioctl()
  *    is allowed to write to them. We should of course be honouring them but
@@ -1207,7 +1207,7 @@
  * necessary fields in @vi as well as initializing the ntfs inode.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *
  * Return 0 on success and -errno on error.  In the error case, the inode will
@@ -1474,7 +1474,7 @@
  * normal directory inodes.
  *
  * Q: What locks are held when the function is called?
- * A: i_state has I_LOCK set, hence the inode is locked, also
+ * A: i_state has I_NEW set, hence the inode is locked, also
  *    i_count is set to 1, so it is not going to go away
  *
  * Return 0 on success and -errno on error.  In the error case, the inode will
diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c
index fbeaec7..e3e4741 100644
--- a/fs/ocfs2/acl.c
+++ b/fs/ocfs2/acl.c
@@ -331,13 +331,14 @@
 	return ret;
 }
 
-static size_t ocfs2_xattr_list_acl_access(struct inode *inode,
+static size_t ocfs2_xattr_list_acl_access(struct dentry *dentry,
 					  char *list,
 					  size_t list_len,
 					  const char *name,
-					  size_t name_len)
+					  size_t name_len,
+					  int type)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@@ -348,13 +349,14 @@
 	return size;
 }
 
-static size_t ocfs2_xattr_list_acl_default(struct inode *inode,
+static size_t ocfs2_xattr_list_acl_default(struct dentry *dentry,
 					   char *list,
 					   size_t list_len,
 					   const char *name,
-					   size_t name_len)
+					   size_t name_len,
+					   int type)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
@@ -365,19 +367,19 @@
 	return size;
 }
 
-static int ocfs2_xattr_get_acl(struct inode *inode,
-			       int type,
-			       void *buffer,
-			       size_t size)
+static int ocfs2_xattr_get_acl(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 	struct posix_acl *acl;
 	int ret;
 
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
 		return -EOPNOTSUPP;
 
-	acl = ocfs2_get_acl(inode, type);
+	acl = ocfs2_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -388,35 +390,16 @@
 	return ret;
 }
 
-static int ocfs2_xattr_get_acl_access(struct inode *inode,
-				      const char *name,
-				      void *buffer,
-				      size_t size)
+static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ocfs2_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int ocfs2_xattr_get_acl_default(struct inode *inode,
-				       const char *name,
-				       void *buffer,
-				       size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ocfs2_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int ocfs2_xattr_set_acl(struct inode *inode,
-			       int type,
-			       const void *value,
-			       size_t size)
-{
+	struct inode *inode = dentry->d_inode;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct posix_acl *acl;
 	int ret = 0;
 
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
 	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
 		return -EOPNOTSUPP;
 
@@ -442,38 +425,18 @@
 	return ret;
 }
 
-static int ocfs2_xattr_set_acl_access(struct inode *inode,
-				      const char *name,
-				      const void *value,
-				      size_t size,
-				      int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ocfs2_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static int ocfs2_xattr_set_acl_default(struct inode *inode,
-				       const char *name,
-				       const void *value,
-				       size_t size,
-				       int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return ocfs2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
 struct xattr_handler ocfs2_xattr_acl_access_handler = {
 	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
 	.list	= ocfs2_xattr_list_acl_access,
-	.get	= ocfs2_xattr_get_acl_access,
-	.set	= ocfs2_xattr_set_acl_access,
+	.get	= ocfs2_xattr_get_acl,
+	.set	= ocfs2_xattr_set_acl,
 };
 
 struct xattr_handler ocfs2_xattr_acl_default_handler = {
 	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
 	.list	= ocfs2_xattr_list_acl_default,
-	.get	= ocfs2_xattr_get_acl_default,
-	.set	= ocfs2_xattr_set_acl_default,
+	.get	= ocfs2_xattr_get_acl,
+	.set	= ocfs2_xattr_set_acl,
 };
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 7c7198a..fb4e672 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -7190,8 +7190,8 @@
 	 * wait on them - the truncate_inode_pages() call later will
 	 * do that for us.
 	 */
-	ret = do_sync_mapping_range(inode->i_mapping, range_start,
-				    range_end - 1, SYNC_FILE_RANGE_WRITE);
+	ret = filemap_fdatawrite_range(inode->i_mapping, range_start,
+				       range_end - 1);
 	if (ret)
 		mlog_errno(ret);
 
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index deb2b13..3dae4a1 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -547,6 +547,9 @@
  *
  * called like this: dio->get_blocks(dio->inode, fs_startblk,
  * 					fs_count, map_bh, dio->rw == WRITE);
+ *
+ * Note that we never bother to allocate blocks here, and thus ignore the
+ * create argument.
  */
 static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
 				     struct buffer_head *bh_result, int create)
@@ -563,14 +566,6 @@
 
 	inode_blocks = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
 
-	/*
-	 * Any write past EOF is not allowed because we'd be extending.
-	 */
-	if (create && (iblock + max_blocks) > inode_blocks) {
-		ret = -EIO;
-		goto bail;
-	}
-
 	/* This figures out the size of the next contiguous block, and
 	 * our logical offset */
 	ret = ocfs2_extent_map_get_blocks(inode, iblock, &p_blkno,
@@ -582,15 +577,6 @@
 		goto bail;
 	}
 
-	if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)) && !p_blkno && create) {
-		ocfs2_error(inode->i_sb,
-			    "Inode %llu has a hole at block %llu\n",
-			    (unsigned long long)OCFS2_I(inode)->ip_blkno,
-			    (unsigned long long)iblock);
-		ret = -EROFS;
-		goto bail;
-	}
-
 	/* We should already CoW the refcounted extent. */
 	BUG_ON(ext_flags & OCFS2_EXT_REFCOUNTED);
 	/*
@@ -601,20 +587,8 @@
 	 */
 	if (p_blkno && !(ext_flags & OCFS2_EXT_UNWRITTEN))
 		map_bh(bh_result, inode->i_sb, p_blkno);
-	else {
-		/*
-		 * ocfs2_prepare_inode_for_write() should have caught
-		 * the case where we'd be filling a hole and triggered
-		 * a buffered write instead.
-		 */
-		if (create) {
-			ret = -EIO;
-			mlog_errno(ret);
-			goto bail;
-		}
-
+	else
 		clear_buffer_mapped(bh_result);
-	}
 
 	/* make sure we don't map more than max_blocks blocks here as
 	   that's all the kernel will handle at this point. */
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index fe34190..43c1148 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -205,8 +205,6 @@
 					   int offset,
 					   struct ocfs2_xattr_value_root **xv,
 					   struct buffer_head **bh);
-static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
-				    const void *value, size_t size, int flags);
 
 static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
 {
@@ -6978,9 +6976,9 @@
 
 	ret = ocfs2_init_security_get(inode, dir, &si);
 	if (!ret) {
-		ret = ocfs2_xattr_security_set(inode, si.name,
-					       si.value, si.value_len,
-					       XATTR_CREATE);
+		ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
+				      si.name, si.value, si.value_len,
+				      XATTR_CREATE);
 		if (ret) {
 			mlog_errno(ret);
 			goto leave;
@@ -7008,9 +7006,9 @@
 /*
  * 'security' attributes support
  */
-static size_t ocfs2_xattr_security_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_security_list(struct dentry *dentry, char *list,
 					size_t list_size, const char *name,
-					size_t name_len)
+					size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7023,23 +7021,23 @@
 	return total_len;
 }
 
-static int ocfs2_xattr_security_get(struct inode *inode, const char *name,
-				    void *buffer, size_t size)
+static int ocfs2_xattr_security_get(struct dentry *dentry, const char *name,
+				    void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY, name,
-			       buffer, size);
+	return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+			       name, buffer, size);
 }
 
-static int ocfs2_xattr_security_set(struct inode *inode, const char *name,
-				    const void *value, size_t size, int flags)
+static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY, name, value,
-			       size, flags);
+	return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_SECURITY,
+			       name, value, size, flags);
 }
 
 int ocfs2_init_security_get(struct inode *inode,
@@ -7076,9 +7074,9 @@
 /*
  * 'trusted' attributes support
  */
-static size_t ocfs2_xattr_trusted_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_trusted_list(struct dentry *dentry, char *list,
 				       size_t list_size, const char *name,
-				       size_t name_len)
+				       size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
@@ -7091,23 +7089,23 @@
 	return total_len;
 }
 
-static int ocfs2_xattr_trusted_get(struct inode *inode, const char *name,
-				   void *buffer, size_t size)
+static int ocfs2_xattr_trusted_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED, name,
-			       buffer, size);
+	return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+			       name, buffer, size);
 }
 
-static int ocfs2_xattr_trusted_set(struct inode *inode, const char *name,
-				   const void *value, size_t size, int flags)
+static int ocfs2_xattr_trusted_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 
-	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED, name, value,
-			       size, flags);
+	return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_TRUSTED,
+			       name, value, size, flags);
 }
 
 struct xattr_handler ocfs2_xattr_trusted_handler = {
@@ -7120,13 +7118,13 @@
 /*
  * 'user' attributes support
  */
-static size_t ocfs2_xattr_user_list(struct inode *inode, char *list,
+static size_t ocfs2_xattr_user_list(struct dentry *dentry, char *list,
 				    size_t list_size, const char *name,
-				    size_t name_len)
+				    size_t name_len, int type)
 {
 	const size_t prefix_len = XATTR_USER_PREFIX_LEN;
 	const size_t total_len = prefix_len + name_len + 1;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return 0;
@@ -7139,31 +7137,31 @@
 	return total_len;
 }
 
-static int ocfs2_xattr_user_get(struct inode *inode, const char *name,
-				void *buffer, size_t size)
+static int ocfs2_xattr_user_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int type)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
-	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
+	return ocfs2_xattr_get(dentry->d_inode, OCFS2_XATTR_INDEX_USER, name,
 			       buffer, size);
 }
 
-static int ocfs2_xattr_user_set(struct inode *inode, const char *name,
-				const void *value, size_t size, int flags)
+static int ocfs2_xattr_user_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
 	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
 		return -EOPNOTSUPP;
 
-	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER, name, value,
-			       size, flags);
+	return ocfs2_xattr_set(dentry->d_inode, OCFS2_XATTR_INDEX_USER,
+			       name, value, size, flags);
 }
 
 struct xattr_handler ocfs2_xattr_user_handler = {
diff --git a/fs/open.c b/fs/open.c
index b4b31d2..ca69241 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -30,6 +30,9 @@
 #include <linux/audit.h>
 #include <linux/falloc.h>
 #include <linux/fs_struct.h>
+#include <linux/ima.h>
+
+#include "internal.h"
 
 int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
@@ -855,6 +858,7 @@
 		if (error)
 			goto cleanup_all;
 	}
+	ima_counts_get(f);
 
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
diff --git a/fs/pipe.c b/fs/pipe.c
index ae17d02..37ba29f 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -906,17 +906,6 @@
 }
 
 static struct vfsmount *pipe_mnt __read_mostly;
-static int pipefs_delete_dentry(struct dentry *dentry)
-{
-	/*
-	 * At creation time, we pretended this dentry was hashed
-	 * (by clearing DCACHE_UNHASHED bit in d_flags)
-	 * At delete time, we restore the truth : not hashed.
-	 * (so that dput() can proceed correctly)
-	 */
-	dentry->d_flags |= DCACHE_UNHASHED;
-	return 0;
-}
 
 /*
  * pipefs_dname() is called from d_path().
@@ -928,7 +917,6 @@
 }
 
 static const struct dentry_operations pipefs_dentry_operations = {
-	.d_delete	= pipefs_delete_dentry,
 	.d_dname	= pipefs_dname,
 };
 
@@ -974,7 +962,7 @@
 	int err;
 	struct inode *inode;
 	struct file *f;
-	struct dentry *dentry;
+	struct path path;
 	struct qstr name = { .name = "" };
 
 	err = -ENFILE;
@@ -983,21 +971,16 @@
 		goto err;
 
 	err = -ENOMEM;
-	dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
-	if (!dentry)
+	path.dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name);
+	if (!path.dentry)
 		goto err_inode;
+	path.mnt = mntget(pipe_mnt);
 
-	dentry->d_op = &pipefs_dentry_operations;
-	/*
-	 * We dont want to publish this dentry into global dentry hash table.
-	 * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
-	 * This permits a working /proc/$pid/fd/XXX on pipes
-	 */
-	dentry->d_flags &= ~DCACHE_UNHASHED;
-	d_instantiate(dentry, inode);
+	path.dentry->d_op = &pipefs_dentry_operations;
+	d_instantiate(path.dentry, inode);
 
 	err = -ENFILE;
-	f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipefifo_fops);
+	f = alloc_file(&path, FMODE_WRITE, &write_pipefifo_fops);
 	if (!f)
 		goto err_dentry;
 	f->f_mapping = inode->i_mapping;
@@ -1009,7 +992,7 @@
 
  err_dentry:
 	free_pipe_info(inode);
-	dput(dentry);
+	path_put(&path);
 	return ERR_PTR(err);
 
  err_inode:
@@ -1028,20 +1011,14 @@
 
 struct file *create_read_pipe(struct file *wrf, int flags)
 {
-	struct file *f = get_empty_filp();
+	/* Grab pipe from the writer */
+	struct file *f = alloc_file(&wrf->f_path, FMODE_READ,
+				    &read_pipefifo_fops);
 	if (!f)
 		return ERR_PTR(-ENFILE);
 
-	/* Grab pipe from the writer */
-	f->f_path = wrf->f_path;
 	path_get(&wrf->f_path);
-	f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;
-
-	f->f_pos = 0;
 	f->f_flags = O_RDONLY | (flags & O_NONBLOCK);
-	f->f_op = &read_pipefifo_fops;
-	f->f_mode = FMODE_READ;
-	f->f_version = 0;
 
 	return f;
 }
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4df4a46..18d5cc6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2266,7 +2266,7 @@
 
 #endif
 
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+#ifdef CONFIG_ELF_CORE
 static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,
 					 size_t count, loff_t *ppos)
 {
@@ -2623,7 +2623,7 @@
 #ifdef CONFIG_FAULT_INJECTION
 	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
 #endif
-#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
+#ifdef CONFIG_ELF_CORE
 	REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
 #endif
 #ifdef CONFIG_TASK_IO_ACCOUNTING
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index fa678ab..480cb10 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -429,7 +429,7 @@
 			unsigned int ino;
 
 			ino = de->low_ino;
-			de_get(de);
+			pde_get(de);
 			spin_unlock(&proc_subdir_lock);
 			error = -EINVAL;
 			inode = proc_get_inode(dir->i_sb, ino, de);
@@ -445,7 +445,7 @@
 		return NULL;
 	}
 	if (de)
-		de_put(de);
+		pde_put(de);
 	return ERR_PTR(error);
 }
 
@@ -509,17 +509,17 @@
 				struct proc_dir_entry *next;
 
 				/* filldir passes info to user space */
-				de_get(de);
+				pde_get(de);
 				spin_unlock(&proc_subdir_lock);
 				if (filldir(dirent, de->name, de->namelen, filp->f_pos,
 					    de->low_ino, de->mode >> 12) < 0) {
-					de_put(de);
+					pde_put(de);
 					goto out;
 				}
 				spin_lock(&proc_subdir_lock);
 				filp->f_pos++;
 				next = de->next;
-				de_put(de);
+				pde_put(de);
 				de = next;
 			} while (de);
 			spin_unlock(&proc_subdir_lock);
@@ -763,7 +763,7 @@
 	return NULL;
 }
 
-void free_proc_entry(struct proc_dir_entry *de)
+static void free_proc_entry(struct proc_dir_entry *de)
 {
 	unsigned int ino = de->low_ino;
 
@@ -777,6 +777,12 @@
 	kfree(de);
 }
 
+void pde_put(struct proc_dir_entry *pde)
+{
+	if (atomic_dec_and_test(&pde->count))
+		free_proc_entry(pde);
+}
+
 /*
  * Remove a /proc entry and free it if it's not currently in use.
  */
@@ -845,6 +851,5 @@
 	WARN(de->subdir, KERN_WARNING "%s: removing non-empty directory "
 			"'%s/%s', leaking at least '%s'\n", __func__,
 			de->parent->name, de->name, de->subdir->name);
-	if (atomic_dec_and_test(&de->count))
-		free_proc_entry(de);
+	pde_put(de);
 }
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index d78ade30..445a02b 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -24,29 +24,6 @@
 
 #include "internal.h"
 
-struct proc_dir_entry *de_get(struct proc_dir_entry *de)
-{
-	atomic_inc(&de->count);
-	return de;
-}
-
-/*
- * Decrements the use count and checks for deferred deletion.
- */
-void de_put(struct proc_dir_entry *de)
-{
-	if (!atomic_read(&de->count)) {
-		printk("de_put: entry %s already free!\n", de->name);
-		return;
-	}
-
-	if (atomic_dec_and_test(&de->count))
-		free_proc_entry(de);
-}
-
-/*
- * Decrement the use count of the proc_dir_entry.
- */
 static void proc_delete_inode(struct inode *inode)
 {
 	struct proc_dir_entry *de;
@@ -59,7 +36,7 @@
 	/* Let go of any associated proc directory entry */
 	de = PROC_I(inode)->pde;
 	if (de)
-		de_put(de);
+		pde_put(de);
 	if (PROC_I(inode)->sysctl)
 		sysctl_head_put(PROC_I(inode)->sysctl);
 	clear_inode(inode);
@@ -480,7 +457,7 @@
 		}
 		unlock_new_inode(inode);
 	} else
-	       de_put(de);
+	       pde_put(de);
 	return inode;
 }			
 
@@ -495,7 +472,7 @@
 	s->s_op = &proc_sops;
 	s->s_time_gran = 1;
 	
-	de_get(&proc_root);
+	pde_get(&proc_root);
 	root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
 	if (!root_inode)
 		goto out_no_root;
@@ -509,6 +486,6 @@
 out_no_root:
 	printk("proc_read_super: get root inode failed\n");
 	iput(root_inode);
-	de_put(&proc_root);
+	pde_put(&proc_root);
 	return -ENOMEM;
 }
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 753ca37..1f24a3e 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -61,8 +61,6 @@
 extern const struct file_operations proc_net_operations;
 extern const struct inode_operations proc_net_inode_operations;
 
-void free_proc_entry(struct proc_dir_entry *de);
-
 void proc_init_inodecache(void);
 
 static inline struct pid *proc_pid(struct inode *inode)
@@ -101,8 +99,12 @@
 int task_statm(struct mm_struct *, int *, int *, int *, int *);
 void task_mem(struct seq_file *, struct mm_struct *);
 
-struct proc_dir_entry *de_get(struct proc_dir_entry *de);
-void de_put(struct proc_dir_entry *de);
+static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
+{
+	atomic_inc(&pde->count);
+	return pde;
+}
+void pde_put(struct proc_dir_entry *pde);
 
 extern struct vfsmount *proc_mnt;
 int proc_fill_super(struct super_block *);
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 5033ce0..180cf5a 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -8,6 +8,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/hugetlb.h>
+#include <linux/kernel-page-flags.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -71,52 +72,12 @@
  * physical page flags.
  */
 
-/* These macros are used to decouple internal flags from exported ones */
-
-#define KPF_LOCKED		0
-#define KPF_ERROR		1
-#define KPF_REFERENCED		2
-#define KPF_UPTODATE		3
-#define KPF_DIRTY		4
-#define KPF_LRU			5
-#define KPF_ACTIVE		6
-#define KPF_SLAB		7
-#define KPF_WRITEBACK		8
-#define KPF_RECLAIM		9
-#define KPF_BUDDY		10
-
-/* 11-20: new additions in 2.6.31 */
-#define KPF_MMAP		11
-#define KPF_ANON		12
-#define KPF_SWAPCACHE		13
-#define KPF_SWAPBACKED		14
-#define KPF_COMPOUND_HEAD	15
-#define KPF_COMPOUND_TAIL	16
-#define KPF_HUGE		17
-#define KPF_UNEVICTABLE		18
-#define KPF_HWPOISON		19
-#define KPF_NOPAGE		20
-
-#define KPF_KSM			21
-
-/* kernel hacking assistances
- * WARNING: subject to change, never rely on them!
- */
-#define KPF_RESERVED		32
-#define KPF_MLOCKED		33
-#define KPF_MAPPEDTODISK	34
-#define KPF_PRIVATE		35
-#define KPF_PRIVATE_2		36
-#define KPF_OWNER_PRIVATE	37
-#define KPF_ARCH		38
-#define KPF_UNCACHED		39
-
 static inline u64 kpf_copy_bit(u64 kflags, int ubit, int kbit)
 {
 	return ((kflags >> kbit) & 1) << ubit;
 }
 
-static u64 get_uflags(struct page *page)
+u64 stable_page_flags(struct page *page)
 {
 	u64 k;
 	u64 u;
@@ -219,7 +180,7 @@
 		else
 			ppage = NULL;
 
-		if (put_user(get_uflags(ppage), out)) {
+		if (put_user(stable_page_flags(ppage), out)) {
 			ret = -EFAULT;
 			break;
 		}
diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
index 32f5d13..22e0d60 100644
--- a/fs/qnx4/bitmap.c
+++ b/fs/qnx4/bitmap.c
@@ -17,13 +17,6 @@
 #include <linux/bitops.h>
 #include "qnx4.h"
 
-#if 0
-int qnx4_new_block(struct super_block *sb)
-{
-	return 0;
-}
-#endif  /*  0  */
-
 static void count_bits(register const char *bmPart, register int size,
 		       int *const tf)
 {
@@ -35,22 +28,7 @@
 	}
 	do {
 		b = *bmPart++;
-		if ((b & 1) == 0)
-			tot++;
-		if ((b & 2) == 0)
-			tot++;
-		if ((b & 4) == 0)
-			tot++;
-		if ((b & 8) == 0)
-			tot++;
-		if ((b & 16) == 0)
-			tot++;
-		if ((b & 32) == 0)
-			tot++;
-		if ((b & 64) == 0)
-			tot++;
-		if ((b & 128) == 0)
-			tot++;
+		tot += 8 - hweight8(b);
 		size--;
 	} while (size != 0);
 	*tf = tot;
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 449f5a6..ebf3440 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -64,25 +64,7 @@
 		result = sb_getblk(inode->i_sb, nr);
 		return result;
 	}
-	if (!create) {
-		return NULL;
-	}
-#if 0
-	tmp = qnx4_new_block(inode->i_sb);
-	if (!tmp) {
-		return NULL;
-	}
-	result = sb_getblk(inode->i_sb, tmp);
-	if (tst) {
-		qnx4_free_block(inode->i_sb, tmp);
-		brelse(result);
-		goto repeat;
-	}
-	tst = tmp;
-#endif
-	inode->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
-	return result;
+	return NULL;
 }
 
 struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
@@ -113,8 +95,6 @@
 	if ( phys ) {
 		// logical block is before EOF
 		map_bh(bh, inode->i_sb, phys);
-	} else if ( create ) {
-		// to be done.
 	}
 	return 0;
 }
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 32fae40..2efc571 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -60,7 +60,7 @@
  */
 int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
 {
-	unsigned long npages, xpages, loop, limit;
+	unsigned long npages, xpages, loop;
 	struct page *pages;
 	unsigned order;
 	void *data;
diff --git a/fs/reiserfs/Kconfig b/fs/reiserfs/Kconfig
index ac7cd75..513f431 100644
--- a/fs/reiserfs/Kconfig
+++ b/fs/reiserfs/Kconfig
@@ -1,7 +1,6 @@
 config REISERFS_FS
 	tristate "Reiserfs support"
 	select CRC32
-	select FS_JOURNAL_INFO
 	help
 	  Stores not just filenames but the files themselves in a balanced
 	  tree.  Uses journalling.
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
index 6a9e30c..792b3cb 100644
--- a/fs/reiserfs/Makefile
+++ b/fs/reiserfs/Makefile
@@ -7,7 +7,11 @@
 reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \
 		 super.o prints.o objectid.o lbalance.o ibalance.o stree.o \
 		 hashes.o tail_conversion.o journal.o resize.o \
-		 item_ops.o ioctl.o procfs.o xattr.o lock.o
+		 item_ops.o ioctl.o xattr.o lock.o
+
+ifeq ($(CONFIG_REISERFS_PROC_INFO),y)
+reiserfs-objs += procfs.o
+endif
 
 ifeq ($(CONFIG_REISERFS_FS_XATTR),y)
 reiserfs-objs += xattr_user.o xattr_trusted.o
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 3a28e77..290ae38 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2538,6 +2538,12 @@
 	return reiserfs_write_full_page(page, wbc);
 }
 
+static void reiserfs_truncate_failed_write(struct inode *inode)
+{
+	truncate_inode_pages(inode->i_mapping, inode->i_size);
+	reiserfs_truncate_file(inode, 0);
+}
+
 static int reiserfs_write_begin(struct file *file,
 				struct address_space *mapping,
 				loff_t pos, unsigned len, unsigned flags,
@@ -2604,6 +2610,8 @@
 	if (ret) {
 		unlock_page(page);
 		page_cache_release(page);
+		/* Truncate allocated blocks */
+		reiserfs_truncate_failed_write(inode);
 	}
 	return ret;
 }
@@ -2701,9 +2709,7 @@
 	 ** transaction tracking stuff when the size changes.  So, we have
 	 ** to do the i_size updates here.
 	 */
-	pos += copied;
-
-	if (pos > inode->i_size) {
+	if (pos + copied > inode->i_size) {
 		struct reiserfs_transaction_handle myth;
 		lock_depth = reiserfs_write_lock_once(inode->i_sb);
 		locked = true;
@@ -2721,7 +2727,7 @@
 			goto journal_error;
 
 		reiserfs_update_inode_transaction(inode);
-		inode->i_size = pos;
+		inode->i_size = pos + copied;
 		/*
 		 * this will just nest into our transaction.  It's important
 		 * to use mark_inode_dirty so the inode gets pushed around on the
@@ -2751,6 +2757,10 @@
 		reiserfs_write_unlock_once(inode->i_sb, lock_depth);
 	unlock_page(page);
 	page_cache_release(page);
+
+	if (pos + len > inode->i_size)
+		reiserfs_truncate_failed_write(inode);
+
 	return ret == 0 ? copied : ret;
 
       journal_error:
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c
index 9229e55..7a99811 100644
--- a/fs/reiserfs/procfs.c
+++ b/fs/reiserfs/procfs.c
@@ -17,8 +17,6 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
-#ifdef CONFIG_REISERFS_PROC_INFO
-
 /*
  * LOCKING:
  *
@@ -48,14 +46,6 @@
 	return 0;
 }
 
-int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset,
-				    int count, int *eof, void *data)
-{
-	*start = buffer;
-	*eof = 1;
-	return 0;
-}
-
 #define SF( x ) ( r -> x )
 #define SFP( x ) SF( s_proc_info_data.x )
 #define SFPL( x ) SFP( x[ level ] )
@@ -538,19 +528,6 @@
 	return 0;
 }
 
-struct proc_dir_entry *reiserfs_proc_register_global(char *name,
-						     read_proc_t * func)
-{
-	return (proc_info_root) ? create_proc_read_entry(name, 0,
-							 proc_info_root,
-							 func, NULL) : NULL;
-}
-
-void reiserfs_proc_unregister_global(const char *name)
-{
-	remove_proc_entry(name, proc_info_root);
-}
-
 int reiserfs_proc_info_global_init(void)
 {
 	if (proc_info_root == NULL) {
@@ -572,48 +549,6 @@
 	}
 	return 0;
 }
-
-/* REISERFS_PROC_INFO */
-#else
-
-int reiserfs_proc_info_init(struct super_block *sb)
-{
-	return 0;
-}
-int reiserfs_proc_info_done(struct super_block *sb)
-{
-	return 0;
-}
-
-struct proc_dir_entry *reiserfs_proc_register_global(char *name,
-						     read_proc_t * func)
-{
-	return NULL;
-}
-
-void reiserfs_proc_unregister_global(const char *name)
-{;
-}
-
-int reiserfs_proc_info_global_init(void)
-{
-	return 0;
-}
-int reiserfs_proc_info_global_done(void)
-{
-	return 0;
-}
-
-int reiserfs_global_version_in_proc(char *buffer, char **start,
-				    off_t offset,
-				    int count, int *eof, void *data)
-{
-	return 0;
-}
-
-/* REISERFS_PROC_INFO */
-#endif
-
 /*
  * Revision 1.1.8.2  2001/07/15 17:08:42  god
  *  . use get_super() in procfs.c
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 339b0ba..b4a7dd0 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2222,8 +2222,6 @@
 	}
 
 	reiserfs_proc_info_global_init();
-	reiserfs_proc_register_global("version",
-				      reiserfs_global_version_in_proc);
 
 	ret = register_filesystem(&reiserfs_fs_type);
 
@@ -2231,7 +2229,6 @@
 		return 0;
 	}
 
-	reiserfs_proc_unregister_global("version");
 	reiserfs_proc_info_global_done();
 	destroy_inodecache();
 
@@ -2240,7 +2237,6 @@
 
 static void __exit exit_reiserfs_fs(void)
 {
-	reiserfs_proc_unregister_global("version");
 	reiserfs_proc_info_global_done();
 	unregister_filesystem(&reiserfs_fs_type);
 	destroy_inodecache();
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 58aa8e7..8c7033a 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -48,6 +48,7 @@
 #include <net/checksum.h>
 #include <linux/stat.h>
 #include <linux/quotaops.h>
+#include <linux/security.h>
 
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
@@ -726,15 +727,14 @@
 reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
 		  size_t size)
 {
-	struct inode *inode = dentry->d_inode;
 	struct xattr_handler *handler;
 
-	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->get(inode, name, buffer, size);
+	return handler->get(dentry, name, buffer, size, handler->flags);
 }
 
 /*
@@ -746,15 +746,14 @@
 reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 		  size_t size, int flags)
 {
-	struct inode *inode = dentry->d_inode;
 	struct xattr_handler *handler;
 
-	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(inode, name, value, size, flags);
+	return handler->set(dentry, name, value, size, flags, handler->flags);
 }
 
 /*
@@ -764,21 +763,20 @@
  */
 int reiserfs_removexattr(struct dentry *dentry, const char *name)
 {
-	struct inode *inode = dentry->d_inode;
 	struct xattr_handler *handler;
-	handler = find_xattr_handler_prefix(inode->i_sb->s_xattr, name);
+	handler = find_xattr_handler_prefix(dentry->d_sb->s_xattr, name);
 
-	if (!handler || get_inode_sd_version(inode) == STAT_DATA_V1)
+	if (!handler || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
 		return -EOPNOTSUPP;
 
-	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+	return handler->set(dentry, name, NULL, 0, XATTR_REPLACE, handler->flags);
 }
 
 struct listxattr_buf {
 	size_t size;
 	size_t pos;
 	char *buf;
-	struct inode *inode;
+	struct dentry *dentry;
 };
 
 static int listxattr_filler(void *buf, const char *name, int namelen,
@@ -789,17 +787,19 @@
 	if (name[0] != '.' ||
 	    (namelen != 1 && (name[1] != '.' || namelen != 2))) {
 		struct xattr_handler *handler;
-		handler = find_xattr_handler_prefix(b->inode->i_sb->s_xattr,
+		handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
 						    name);
 		if (!handler)	/* Unsupported xattr name */
 			return 0;
 		if (b->buf) {
-			size = handler->list(b->inode, b->buf + b->pos,
-					 b->size, name, namelen);
+			size = handler->list(b->dentry, b->buf + b->pos,
+					 b->size, name, namelen,
+					 handler->flags);
 			if (size > b->size)
 				return -ERANGE;
 		} else {
-			size = handler->list(b->inode, NULL, 0, name, namelen);
+			size = handler->list(b->dentry, NULL, 0, name,
+					     namelen, handler->flags);
 		}
 
 		b->pos += size;
@@ -820,7 +820,7 @@
 	int err = 0;
 	loff_t pos = 0;
 	struct listxattr_buf buf = {
-		.inode = dentry->d_inode,
+		.dentry = dentry,
 		.buf = buffer,
 		.size = buffer ? size : 0,
 	};
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 35d6e67..cc32e6a 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -15,8 +15,10 @@
 			    struct posix_acl *acl);
 
 static int
-xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
+posix_acl_set(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags, int type)
 {
+	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl;
 	int error, error2;
 	struct reiserfs_transaction_handle th;
@@ -60,15 +62,16 @@
 }
 
 static int
-xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
+posix_acl_get(struct dentry *dentry, const char *name, void *buffer,
+		size_t size, int type)
 {
 	struct posix_acl *acl;
 	int error;
 
-	if (!reiserfs_posixacl(inode->i_sb))
+	if (!reiserfs_posixacl(dentry->d_sb))
 		return -EOPNOTSUPP;
 
-	acl = reiserfs_get_acl(inode, type);
+	acl = reiserfs_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -482,30 +485,12 @@
 	return error;
 }
 
-static int
-posix_acl_access_get(struct inode *inode, const char *name,
-		     void *buffer, size_t size)
-{
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
-		return -EINVAL;
-	return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-}
-
-static int
-posix_acl_access_set(struct inode *inode, const char *name,
-		     const void *value, size_t size, int flags)
-{
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS) - 1)
-		return -EINVAL;
-	return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-}
-
-static size_t posix_acl_access_list(struct inode *inode, char *list,
+static size_t posix_acl_access_list(struct dentry *dentry, char *list,
 				    size_t list_size, const char *name,
-				    size_t name_len)
+				    size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-	if (!reiserfs_posixacl(inode->i_sb))
+	if (!reiserfs_posixacl(dentry->d_sb))
 		return 0;
 	if (list && size <= list_size)
 		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
@@ -514,35 +499,18 @@
 
 struct xattr_handler reiserfs_posix_acl_access_handler = {
 	.prefix = POSIX_ACL_XATTR_ACCESS,
-	.get = posix_acl_access_get,
-	.set = posix_acl_access_set,
+	.flags = ACL_TYPE_ACCESS,
+	.get = posix_acl_get,
+	.set = posix_acl_set,
 	.list = posix_acl_access_list,
 };
 
-static int
-posix_acl_default_get(struct inode *inode, const char *name,
-		      void *buffer, size_t size)
-{
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
-		return -EINVAL;
-	return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-}
-
-static int
-posix_acl_default_set(struct inode *inode, const char *name,
-		      const void *value, size_t size, int flags)
-{
-	if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT) - 1)
-		return -EINVAL;
-	return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-}
-
-static size_t posix_acl_default_list(struct inode *inode, char *list,
+static size_t posix_acl_default_list(struct dentry *dentry, char *list,
 				     size_t list_size, const char *name,
-				     size_t name_len)
+				     size_t name_len, int type)
 {
 	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-	if (!reiserfs_posixacl(inode->i_sb))
+	if (!reiserfs_posixacl(dentry->d_sb))
 		return 0;
 	if (list && size <= list_size)
 		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
@@ -551,7 +519,8 @@
 
 struct xattr_handler reiserfs_posix_acl_default_handler = {
 	.prefix = POSIX_ACL_XATTR_DEFAULT,
-	.get = posix_acl_default_get,
-	.set = posix_acl_default_set,
+	.flags = ACL_TYPE_DEFAULT,
+	.get = posix_acl_get,
+	.set = posix_acl_set,
 	.list = posix_acl_default_list,
 };
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index a92c879..d8b5bfc 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -8,36 +8,37 @@
 #include <asm/uaccess.h>
 
 static int
-security_get(struct inode *inode, const char *name, void *buffer, size_t size)
+security_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+		int handler_flags)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(inode))
+	if (IS_PRIVATE(dentry->d_inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(inode, name, buffer, size);
+	return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-security_set(struct inode *inode, const char *name, const void *buffer,
-	     size_t size, int flags)
+security_set(struct dentry *dentry, const char *name, const void *buffer,
+	     size_t size, int flags, int handler_flags)
 {
 	if (strlen(name) < sizeof(XATTR_SECURITY_PREFIX))
 		return -EINVAL;
 
-	if (IS_PRIVATE(inode))
+	if (IS_PRIVATE(dentry->d_inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(inode, name, buffer, size, flags);
+	return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t security_list(struct inode *inode, char *list, size_t list_len,
-			    const char *name, size_t namelen)
+static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
+			    const char *name, size_t namelen, int handler_flags)
 {
 	const size_t len = namelen + 1;
 
-	if (IS_PRIVATE(inode))
+	if (IS_PRIVATE(dentry->d_inode))
 		return 0;
 
 	if (list && len <= list_len) {
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index a865042..5b08aac 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -8,36 +8,37 @@
 #include <asm/uaccess.h>
 
 static int
-trusted_get(struct inode *inode, const char *name, void *buffer, size_t size)
+trusted_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+	    int handler_flags)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
 		return -EPERM;
 
-	return reiserfs_xattr_get(inode, name, buffer, size);
+	return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-trusted_set(struct inode *inode, const char *name, const void *buffer,
-	    size_t size, int flags)
+trusted_set(struct dentry *dentry, const char *name, const void *buffer,
+	    size_t size, int flags, int handler_flags)
 {
 	if (strlen(name) < sizeof(XATTR_TRUSTED_PREFIX))
 		return -EINVAL;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
 		return -EPERM;
 
-	return reiserfs_xattr_set(inode, name, buffer, size, flags);
+	return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t trusted_list(struct inode *inode, char *list, size_t list_size,
-			   const char *name, size_t name_len)
+static size_t trusted_list(struct dentry *dentry, char *list, size_t list_size,
+			   const char *name, size_t name_len, int handler_flags)
 {
 	const size_t len = name_len + 1;
 
-	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
+	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(dentry->d_inode))
 		return 0;
 
 	if (list && len <= list_size) {
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index e3238dc..75d59c4 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -7,34 +7,35 @@
 #include <asm/uaccess.h>
 
 static int
-user_get(struct inode *inode, const char *name, void *buffer, size_t size)
+user_get(struct dentry *dentry, const char *name, void *buffer, size_t size,
+	 int handler_flags)
 {
 
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
-	if (!reiserfs_xattrs_user(inode->i_sb))
+	if (!reiserfs_xattrs_user(dentry->d_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_get(inode, name, buffer, size);
+	return reiserfs_xattr_get(dentry->d_inode, name, buffer, size);
 }
 
 static int
-user_set(struct inode *inode, const char *name, const void *buffer,
-	 size_t size, int flags)
+user_set(struct dentry *dentry, const char *name, const void *buffer,
+	 size_t size, int flags, int handler_flags)
 {
 	if (strlen(name) < sizeof(XATTR_USER_PREFIX))
 		return -EINVAL;
 
-	if (!reiserfs_xattrs_user(inode->i_sb))
+	if (!reiserfs_xattrs_user(dentry->d_sb))
 		return -EOPNOTSUPP;
-	return reiserfs_xattr_set(inode, name, buffer, size, flags);
+	return reiserfs_xattr_set(dentry->d_inode, name, buffer, size, flags);
 }
 
-static size_t user_list(struct inode *inode, char *list, size_t list_size,
-			const char *name, size_t name_len)
+static size_t user_list(struct dentry *dentry, char *list, size_t list_size,
+			const char *name, size_t name_len, int handler_flags)
 {
 	const size_t len = name_len + 1;
 
-	if (!reiserfs_xattrs_user(inode->i_sb))
+	if (!reiserfs_xattrs_user(dentry->d_sb))
 		return 0;
 	if (list && len <= list_size) {
 		memcpy(list, name, name_len);
diff --git a/fs/stack.c b/fs/stack.c
index 67716f6..4a6f7f4 100644
--- a/fs/stack.c
+++ b/fs/stack.c
@@ -7,18 +7,63 @@
  * This function cannot be inlined since i_size_{read,write} is rather
  * heavy-weight on 32-bit systems
  */
-void fsstack_copy_inode_size(struct inode *dst, const struct inode *src)
+void fsstack_copy_inode_size(struct inode *dst, struct inode *src)
 {
-	i_size_write(dst, i_size_read((struct inode *)src));
-	dst->i_blocks = src->i_blocks;
+	loff_t i_size;
+	blkcnt_t i_blocks;
+
+	/*
+	 * i_size_read() includes its own seqlocking and protection from
+	 * preemption (see include/linux/fs.h): we need nothing extra for
+	 * that here, and prefer to avoid nesting locks than attempt to keep
+	 * i_size and i_blocks in sync together.
+	 */
+	i_size = i_size_read(src);
+
+	/*
+	 * But if CONFIG_LBDAF (on 32-bit), we ought to make an effort to
+	 * keep the two halves of i_blocks in sync despite SMP or PREEMPT -
+	 * though stat's generic_fillattr() doesn't bother, and we won't be
+	 * applying quotas (where i_blocks does become important) at the
+	 * upper level.
+	 *
+	 * We don't actually know what locking is used at the lower level;
+	 * but if it's a filesystem that supports quotas, it will be using
+	 * i_lock as in inode_add_bytes().  tmpfs uses other locking, and
+	 * its 32-bit is (just) able to exceed 2TB i_size with the aid of
+	 * holes; but its i_blocks cannot carry into the upper long without
+	 * almost 2TB swap - let's ignore that case.
+	 */
+	if (sizeof(i_blocks) > sizeof(long))
+		spin_lock(&src->i_lock);
+	i_blocks = src->i_blocks;
+	if (sizeof(i_blocks) > sizeof(long))
+		spin_unlock(&src->i_lock);
+
+	/*
+	 * If CONFIG_SMP or CONFIG_PREEMPT on 32-bit, it's vital for
+	 * fsstack_copy_inode_size() to hold some lock around
+	 * i_size_write(), otherwise i_size_read() may spin forever (see
+	 * include/linux/fs.h).  We don't necessarily hold i_mutex when this
+	 * is called, so take i_lock for that case.
+	 *
+	 * And if CONFIG_LBADF (on 32-bit), continue our effort to keep the
+	 * two halves of i_blocks in sync despite SMP or PREEMPT: use i_lock
+	 * for that case too, and do both at once by combining the tests.
+	 *
+	 * There is none of this locking overhead in the 64-bit case.
+	 */
+	if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
+		spin_lock(&dst->i_lock);
+	i_size_write(dst, i_size);
+	dst->i_blocks = i_blocks;
+	if (sizeof(i_size) > sizeof(long) || sizeof(i_blocks) > sizeof(long))
+		spin_unlock(&dst->i_lock);
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_inode_size);
 
-/* copy all attributes; get_nlinks is optional way to override the i_nlink
- * copying
- */
-void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-				int (*get_nlinks)(struct inode *))
+/* copy all attributes */
+void fsstack_copy_attr_all(struct inode *dest, const struct inode *src)
 {
 	dest->i_mode = src->i_mode;
 	dest->i_uid = src->i_uid;
@@ -29,14 +74,6 @@
 	dest->i_ctime = src->i_ctime;
 	dest->i_blkbits = src->i_blkbits;
 	dest->i_flags = src->i_flags;
-
-	/*
-	 * Update the nlinks AFTER updating the above fields, because the
-	 * get_links callback may depend on them.
-	 */
-	if (!get_nlinks)
-		dest->i_nlink = src->i_nlink;
-	else
-		dest->i_nlink = (*get_nlinks)(dest);
+	dest->i_nlink = src->i_nlink;
 }
 EXPORT_SYMBOL_GPL(fsstack_copy_attr_all);
diff --git a/fs/sync.c b/fs/sync.c
index 36752a6..418727a 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -355,6 +355,7 @@
 {
 	int ret;
 	struct file *file;
+	struct address_space *mapping;
 	loff_t endbyte;			/* inclusive */
 	int fput_needed;
 	umode_t i_mode;
@@ -405,7 +406,28 @@
 			!S_ISLNK(i_mode))
 		goto out_put;
 
-	ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
+	mapping = file->f_mapping;
+	if (!mapping) {
+		ret = -EINVAL;
+		goto out_put;
+	}
+
+	ret = 0;
+	if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
+		ret = filemap_fdatawait_range(mapping, offset, endbyte);
+		if (ret < 0)
+			goto out_put;
+	}
+
+	if (flags & SYNC_FILE_RANGE_WRITE) {
+		ret = filemap_fdatawrite_range(mapping, offset, endbyte);
+		if (ret < 0)
+			goto out_put;
+	}
+
+	if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
+		ret = filemap_fdatawait_range(mapping, offset, endbyte);
+
 out_put:
 	fput_light(file, fput_needed);
 out:
@@ -437,38 +459,3 @@
 }
 SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
 #endif
-
-/*
- * `endbyte' is inclusive
- */
-int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
-			  loff_t endbyte, unsigned int flags)
-{
-	int ret;
-
-	if (!mapping) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	ret = 0;
-	if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
-		ret = filemap_fdatawait_range(mapping, offset, endbyte);
-		if (ret < 0)
-			goto out;
-	}
-
-	if (flags & SYNC_FILE_RANGE_WRITE) {
-		ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
-						WB_SYNC_ALL);
-		if (ret < 0)
-			goto out;
-	}
-
-	if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
-		ret = filemap_fdatawait_range(mapping, offset, endbyte);
-	}
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(do_sync_mapping_range);
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 39849f8..16a6444 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -45,7 +45,7 @@
  *
  * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the
  * read-ahead path does not lock it ("sys_read -> generic_file_aio_read ->
- * ondemand_readahead -> readpage"). In case of readahead, @I_LOCK flag is not
+ * ondemand_readahead -> readpage"). In case of readahead, @I_SYNC flag is not
  * set as well. However, UBIFS disables readahead.
  */
 
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 6f671f1..22af68f 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -70,13 +70,13 @@
 	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
 }
 
-ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry)
+ino_t ufs_inode_by_name(struct inode *dir, struct qstr *qstr)
 {
 	ino_t res = 0;
 	struct ufs_dir_entry *de;
 	struct page *page;
 	
-	de = ufs_find_entry(dir, dentry, &page);
+	de = ufs_find_entry(dir, qstr, &page);
 	if (de) {
 		res = fs32_to_cpu(dir->i_sb, de->d_ino);
 		ufs_put_page(page);
@@ -249,12 +249,12 @@
  * (as a parameter - res_dir). Page is returned mapped and unlocked.
  * Entry is guaranteed to be valid.
  */
-struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry,
+struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct qstr *qstr,
 				     struct page **res_page)
 {
 	struct super_block *sb = dir->i_sb;
-	const char *name = dentry->d_name.name;
-	int namelen = dentry->d_name.len;
+	const char *name = qstr->name;
+	int namelen = qstr->len;
 	unsigned reclen = UFS_DIR_REC_LEN(namelen);
 	unsigned long start, n;
 	unsigned long npages = ufs_dir_pages(dir);
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 23119fe..4c26d9e 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -56,7 +56,7 @@
 		return ERR_PTR(-ENAMETOOLONG);
 
 	lock_kernel();
-	ino = ufs_inode_by_name(dir, dentry);
+	ino = ufs_inode_by_name(dir, &dentry->d_name);
 	if (ino) {
 		inode = ufs_iget(dir->i_sb, ino);
 		if (IS_ERR(inode)) {
@@ -237,7 +237,7 @@
 	struct page *page;
 	int err = -ENOENT;
 
-	de = ufs_find_entry(dir, dentry, &page);
+	de = ufs_find_entry(dir, &dentry->d_name, &page);
 	if (!de)
 		goto out;
 
@@ -281,7 +281,7 @@
 	struct ufs_dir_entry *old_de;
 	int err = -ENOENT;
 
-	old_de = ufs_find_entry(old_dir, old_dentry, &old_page);
+	old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
 	if (!old_de)
 		goto out;
 
@@ -301,7 +301,7 @@
 			goto out_dir;
 
 		err = -ENOENT;
-		new_de = ufs_find_entry(new_dir, new_dentry, &new_page);
+		new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
 		if (!new_de)
 			goto out_dir;
 		inode_inc_link_count(old_inode);
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 5faed79..143c20b 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -66,6 +66,7 @@
  */
 
 
+#include <linux/exportfs.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
 
@@ -96,6 +97,56 @@
 #include "swab.h"
 #include "util.h"
 
+static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
+{
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	struct inode *inode;
+
+	if (ino < UFS_ROOTINO || ino > uspi->s_ncg * uspi->s_ipg)
+		return ERR_PTR(-ESTALE);
+
+	inode = ufs_iget(sb, ino);
+	if (IS_ERR(inode))
+		return ERR_CAST(inode);
+	if (generation && inode->i_generation != generation) {
+		iput(inode);
+		return ERR_PTR(-ESTALE);
+	}
+	return inode;
+}
+
+static struct dentry *ufs_fh_to_dentry(struct super_block *sb, struct fid *fid,
+				       int fh_len, int fh_type)
+{
+	return generic_fh_to_dentry(sb, fid, fh_len, fh_type, ufs_nfs_get_inode);
+}
+
+static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid,
+				       int fh_len, int fh_type)
+{
+	return generic_fh_to_parent(sb, fid, fh_len, fh_type, ufs_nfs_get_inode);
+}
+
+static struct dentry *ufs_get_parent(struct dentry *child)
+{
+	struct qstr dot_dot = {
+		.name	= "..",
+		.len	= 2,
+	};
+	ino_t ino;
+
+	ino = ufs_inode_by_name(child->d_inode, &dot_dot);
+	if (!ino)
+		return ERR_PTR(-ENOENT);
+	return d_obtain_alias(ufs_iget(child->d_inode->i_sb, ino));
+}
+
+static const struct export_operations ufs_export_ops = {
+	.fh_to_dentry	= ufs_fh_to_dentry,
+	.fh_to_parent	= ufs_fh_to_parent,
+	.get_parent	= ufs_get_parent,
+};
+
 #ifdef CONFIG_UFS_DEBUG
 /*
  * Print contents of ufs_super_block, useful for debugging
@@ -990,6 +1041,7 @@
 	 * Read ufs_super_block into internal data structures
 	 */
 	sb->s_op = &ufs_super_ops;
+	sb->s_export_op = &ufs_export_ops;
 	sb->dq_op = NULL; /***/
 	sb->s_magic = fs32_to_cpu(sb, usb3->fs_magic);
 
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
index 644e77e..0b4c39b 100644
--- a/fs/ufs/ufs.h
+++ b/fs/ufs/ufs.h
@@ -86,9 +86,9 @@
 /* dir.c */
 extern const struct inode_operations ufs_dir_inode_operations;
 extern int ufs_add_link (struct dentry *, struct inode *);
-extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
+extern ino_t ufs_inode_by_name(struct inode *, struct qstr *);
 extern int ufs_make_empty(struct inode *, struct inode *);
-extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **);
+extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct qstr *, struct page **);
 extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
 extern int ufs_empty_dir (struct inode *);
 extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
diff --git a/fs/xattr.c b/fs/xattr.c
index 6d4f6d3..46f87e8 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -615,12 +615,11 @@
 generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
 {
 	struct xattr_handler *handler;
-	struct inode *inode = dentry->d_inode;
 
-	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->get(inode, name, buffer, size);
+	return handler->get(dentry, name, buffer, size, handler->flags);
 }
 
 /*
@@ -630,18 +629,20 @@
 ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
-	struct inode *inode = dentry->d_inode;
-	struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
+	struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
 	unsigned int size = 0;
 
 	if (!buffer) {
-		for_each_xattr_handler(handlers, handler)
-			size += handler->list(inode, NULL, 0, NULL, 0);
+		for_each_xattr_handler(handlers, handler) {
+			size += handler->list(dentry, NULL, 0, NULL, 0,
+					      handler->flags);
+		}
 	} else {
 		char *buf = buffer;
 
 		for_each_xattr_handler(handlers, handler) {
-			size = handler->list(inode, buf, buffer_size, NULL, 0);
+			size = handler->list(dentry, buf, buffer_size,
+					     NULL, 0, handler->flags);
 			if (size > buffer_size)
 				return -ERANGE;
 			buf += size;
@@ -659,14 +660,13 @@
 generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
 {
 	struct xattr_handler *handler;
-	struct inode *inode = dentry->d_inode;
 
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
-	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, value, size, flags);
+	return handler->set(dentry, name, value, size, 0, handler->flags);
 }
 
 /*
@@ -677,12 +677,12 @@
 generic_removexattr(struct dentry *dentry, const char *name)
 {
 	struct xattr_handler *handler;
-	struct inode *inode = dentry->d_inode;
 
-	handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
+	handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
 	if (!handler)
 		return -EOPNOTSUPP;
-	return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
+	return handler->set(dentry, name, NULL, 0,
+			    XATTR_REPLACE, handler->flags);
 }
 
 EXPORT_SYMBOL(generic_getxattr);
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c
index 69e598b..2512125 100644
--- a/fs/xfs/linux-2.6/xfs_acl.c
+++ b/fs/xfs/linux-2.6/xfs_acl.c
@@ -354,37 +354,14 @@
 	return error;
 }
 
-/*
- * System xattr handlers.
- *
- * Currently Posix ACLs are the only system namespace extended attribute
- * handlers supported by XFS, so we just implement the handlers here.
- * If we ever support other system extended attributes this will need
- * some refactoring.
- */
-
 static int
-xfs_decode_acl(const char *name)
-{
-	if (strcmp(name, "posix_acl_access") == 0)
-		return ACL_TYPE_ACCESS;
-	else if (strcmp(name, "posix_acl_default") == 0)
-		return ACL_TYPE_DEFAULT;
-	return -EINVAL;
-}
-
-static int
-xfs_xattr_system_get(struct inode *inode, const char *name,
-		void *value, size_t size)
+xfs_xattr_acl_get(struct dentry *dentry, const char *name,
+		void *value, size_t size, int type)
 {
 	struct posix_acl *acl;
-	int type, error;
+	int error;
 
-	type = xfs_decode_acl(name);
-	if (type < 0)
-		return type;
-
-	acl = xfs_get_acl(inode, type);
+	acl = xfs_get_acl(dentry->d_inode, type);
 	if (IS_ERR(acl))
 		return PTR_ERR(acl);
 	if (acl == NULL)
@@ -397,15 +374,13 @@
 }
 
 static int
-xfs_xattr_system_set(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags)
+xfs_xattr_acl_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int type)
 {
+	struct inode *inode = dentry->d_inode;
 	struct posix_acl *acl = NULL;
-	int error = 0, type;
+	int error = 0;
 
-	type = xfs_decode_acl(name);
-	if (type < 0)
-		return type;
 	if (flags & XATTR_CREATE)
 		return -EINVAL;
 	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
@@ -462,8 +437,16 @@
 	return error;
 }
 
-struct xattr_handler xfs_xattr_system_handler = {
-	.prefix	= XATTR_SYSTEM_PREFIX,
-	.get	= xfs_xattr_system_get,
-	.set	= xfs_xattr_system_set,
+struct xattr_handler xfs_xattr_acl_access_handler = {
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.flags	= ACL_TYPE_ACCESS,
+	.get	= xfs_xattr_acl_get,
+	.set	= xfs_xattr_acl_set,
+};
+
+struct xattr_handler xfs_xattr_acl_default_handler = {
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.flags	= ACL_TYPE_DEFAULT,
+	.get	= xfs_xattr_acl_get,
+	.set	= xfs_xattr_acl_set,
 };
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index d798c54..66abe36 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1474,19 +1474,13 @@
 
 	bdev = xfs_find_bdev_for_inode(XFS_I(inode));
 
-	if (rw == WRITE) {
-		iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
-		ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
-			bdev, iov, offset, nr_segs,
-			xfs_get_blocks_direct,
-			xfs_end_io_direct);
-	} else {
-		iocb->private = xfs_alloc_ioend(inode, IOMAP_READ);
-		ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
-			bdev, iov, offset, nr_segs,
-			xfs_get_blocks_direct,
-			xfs_end_io_direct);
-	}
+	iocb->private = xfs_alloc_ioend(inode, rw == WRITE ?
+					IOMAP_UNWRITTEN : IOMAP_READ);
+
+	ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov,
+					    offset, nr_segs,
+					    xfs_get_blocks_direct,
+					    xfs_end_io_direct);
 
 	if (unlikely(ret != -EIOCBQUEUED && iocb->private))
 		xfs_destroy_ioend(iocb->private);
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index b4c7d42..77b8be8 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -292,6 +292,7 @@
 {
 	if (bp->b_pages != bp->b_page_array) {
 		kmem_free(bp->b_pages);
+		bp->b_pages = NULL;
 	}
 }
 
@@ -323,9 +324,8 @@
 				ASSERT(!PagePrivate(page));
 			page_cache_release(page);
 		}
-		_xfs_buf_free_pages(bp);
 	}
-
+	_xfs_buf_free_pages(bp);
 	xfs_buf_deallocate(bp);
 }
 
@@ -1149,10 +1149,14 @@
 	if (bp->b_flags & XBF_ORDERED) {
 		ASSERT(!(bp->b_flags & XBF_READ));
 		rw = WRITE_BARRIER;
-	} else if (bp->b_flags & _XBF_RUN_QUEUES) {
+	} else if (bp->b_flags & XBF_LOG_BUFFER) {
 		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
 		bp->b_flags &= ~_XBF_RUN_QUEUES;
 		rw = (bp->b_flags & XBF_WRITE) ? WRITE_SYNC : READ_SYNC;
+	} else if (bp->b_flags & _XBF_RUN_QUEUES) {
+		ASSERT(!(bp->b_flags & XBF_READ_AHEAD));
+		bp->b_flags &= ~_XBF_RUN_QUEUES;
+		rw = (bp->b_flags & XBF_WRITE) ? WRITE_META : READ_META;
 	} else {
 		rw = (bp->b_flags & XBF_WRITE) ? WRITE :
 		     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index a509f4a..a34c7b5 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -55,6 +55,7 @@
 	XBF_FS_MANAGED = (1 << 8),  /* filesystem controls freeing memory  */
  	XBF_ORDERED = (1 << 11),    /* use ordered writes		   */
 	XBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead		   */
+	XBF_LOG_BUFFER = (1 << 13), /* this is a buffer used for the log   */
 
 	/* flags used only as arguments to access routines */
 	XBF_LOCK = (1 << 14),       /* lock requested			   */
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 1d5b298..2259460 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -794,7 +794,7 @@
 	struct inode		*inode = &ip->i_vnode;
 
 	inode->i_ino = ip->i_ino;
-	inode->i_state = I_NEW|I_LOCK;
+	inode->i_state = I_NEW;
 	inode_add_to_lists(ip->i_mount->m_super, inode);
 
 	inode->i_mode	= ip->i_d.di_mode;
diff --git a/fs/xfs/linux-2.6/xfs_xattr.c b/fs/xfs/linux-2.6/xfs_xattr.c
index 497c7fb..0b18788 100644
--- a/fs/xfs/linux-2.6/xfs_xattr.c
+++ b/fs/xfs/linux-2.6/xfs_xattr.c
@@ -30,10 +30,10 @@
 
 
 static int
-__xfs_xattr_get(struct inode *inode, const char *name,
+xfs_xattr_get(struct dentry *dentry, const char *name,
 		void *value, size_t size, int xflags)
 {
-	struct xfs_inode *ip = XFS_I(inode);
+	struct xfs_inode *ip = XFS_I(dentry->d_inode);
 	int error, asize = size;
 
 	if (strcmp(name, "") == 0)
@@ -52,10 +52,10 @@
 }
 
 static int
-__xfs_xattr_set(struct inode *inode, const char *name, const void *value,
+xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
 		size_t size, int flags, int xflags)
 {
-	struct xfs_inode *ip = XFS_I(inode);
+	struct xfs_inode *ip = XFS_I(dentry->d_inode);
 
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
@@ -71,75 +71,34 @@
 	return -xfs_attr_set(ip, name, (void *)value, size, xflags);
 }
 
-static int
-xfs_xattr_user_get(struct inode *inode, const char *name,
-		void *value, size_t size)
-{
-	return __xfs_xattr_get(inode, name, value, size, 0);
-}
-
-static int
-xfs_xattr_user_set(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags)
-{
-	return __xfs_xattr_set(inode, name, value, size, flags, 0);
-}
-
 static struct xattr_handler xfs_xattr_user_handler = {
 	.prefix	= XATTR_USER_PREFIX,
-	.get	= xfs_xattr_user_get,
-	.set	= xfs_xattr_user_set,
+	.flags	= 0, /* no flags implies user namespace */
+	.get	= xfs_xattr_get,
+	.set	= xfs_xattr_set,
 };
 
-
-static int
-xfs_xattr_trusted_get(struct inode *inode, const char *name,
-		void *value, size_t size)
-{
-	return __xfs_xattr_get(inode, name, value, size, ATTR_ROOT);
-}
-
-static int
-xfs_xattr_trusted_set(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags)
-{
-	return __xfs_xattr_set(inode, name, value, size, flags, ATTR_ROOT);
-}
-
 static struct xattr_handler xfs_xattr_trusted_handler = {
 	.prefix	= XATTR_TRUSTED_PREFIX,
-	.get	= xfs_xattr_trusted_get,
-	.set	= xfs_xattr_trusted_set,
+	.flags	= ATTR_ROOT,
+	.get	= xfs_xattr_get,
+	.set	= xfs_xattr_set,
 };
 
-
-static int
-xfs_xattr_secure_get(struct inode *inode, const char *name,
-		void *value, size_t size)
-{
-	return __xfs_xattr_get(inode, name, value, size, ATTR_SECURE);
-}
-
-static int
-xfs_xattr_secure_set(struct inode *inode, const char *name,
-		const void *value, size_t size, int flags)
-{
-	return __xfs_xattr_set(inode, name, value, size, flags, ATTR_SECURE);
-}
-
 static struct xattr_handler xfs_xattr_security_handler = {
 	.prefix	= XATTR_SECURITY_PREFIX,
-	.get	= xfs_xattr_secure_get,
-	.set	= xfs_xattr_secure_set,
+	.flags	= ATTR_SECURE,
+	.get	= xfs_xattr_get,
+	.set	= xfs_xattr_set,
 };
 
-
 struct xattr_handler *xfs_xattr_handlers[] = {
 	&xfs_xattr_user_handler,
 	&xfs_xattr_trusted_handler,
 	&xfs_xattr_security_handler,
 #ifdef CONFIG_XFS_POSIX_ACL
-	&xfs_xattr_system_handler,
+	&xfs_xattr_acl_access_handler,
+	&xfs_xattr_acl_default_handler,
 #endif
 	NULL
 };
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 947b150..00fd357c 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -49,7 +49,8 @@
 extern int posix_acl_access_exists(struct inode *inode);
 extern int posix_acl_default_exists(struct inode *inode);
 
-extern struct xattr_handler xfs_xattr_system_handler;
+extern struct xattr_handler xfs_xattr_acl_access_handler;
+extern struct xattr_handler xfs_xattr_acl_default_handler;
 #else
 # define xfs_check_acl					NULL
 # define xfs_get_acl(inode, type)			NULL
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 5549d49..cf07ca7 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -46,20 +46,12 @@
 #define BMBT_STARTBLOCK_BITLEN	52
 #define BMBT_BLOCKCOUNT_BITLEN	21
 
-
-#define BMBT_USE_64	1
-
-typedef struct xfs_bmbt_rec_32
-{
-	__uint32_t		l0, l1, l2, l3;
-} xfs_bmbt_rec_32_t;
-typedef struct xfs_bmbt_rec_64
-{
+typedef struct xfs_bmbt_rec {
 	__be64			l0, l1;
-} xfs_bmbt_rec_64_t;
+} xfs_bmbt_rec_t;
 
 typedef __uint64_t	xfs_bmbt_rec_base_t;	/* use this for casts */
-typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
+typedef xfs_bmbt_rec_t xfs_bmdr_rec_t;
 
 typedef struct xfs_bmbt_rec_host {
 	__uint64_t		l0, l1;
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index f5c904a..fa402a6 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -91,7 +91,7 @@
 	ip->i_new_size = 0;
 
 	/* prevent anyone from using this yet */
-	VFS_I(ip)->i_state = I_NEW|I_LOCK;
+	VFS_I(ip)->i_state = I_NEW;
 
 	return ip;
 }
@@ -217,7 +217,7 @@
 			trace_xfs_iget_reclaim(ip);
 			goto out_error;
 		}
-		inode->i_state = I_LOCK|I_NEW;
+		inode->i_state = I_NEW;
 	} else {
 		/* If the VFS inode is being torn down, pause and try again. */
 		if (!igrab(inode)) {
@@ -478,17 +478,21 @@
 {
 	struct xfs_mount	*mp = ip->i_mount;
 	struct xfs_perag	*pag;
+	xfs_agino_t		agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
 
 	XFS_STATS_INC(xs_ig_reclaims);
 
 	/*
-	 * Remove the inode from the per-AG radix tree.  It doesn't matter
-	 * if it was never added to it because radix_tree_delete can deal
-	 * with that case just fine.
+	 * Remove the inode from the per-AG radix tree.
+	 *
+	 * Because radix_tree_delete won't complain even if the item was never
+	 * added to the tree assert that it's been there before to catch
+	 * problems with the inode life time early on.
 	 */
 	pag = xfs_get_perag(mp, ip->i_ino);
 	write_lock(&pag->pag_ici_lock);
-	radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino));
+	if (!radix_tree_delete(&pag->pag_ici_root, agino))
+		ASSERT(0);
 	write_unlock(&pag->pag_ici_lock);
 	xfs_put_perag(mp, pag);
 
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index 65bae4c..cc8df1a 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -127,7 +127,7 @@
 #ifdef __KERNEL__
 
 struct xfs_buf;
-struct xfs_bmbt_rec_64;
+struct xfs_bmbt_rec;
 struct xfs_inode;
 struct xfs_mount;
 
@@ -140,9 +140,9 @@
 	unsigned short		ili_flags;	   /* misc flags */
 	unsigned short		ili_logged;	   /* flushed logged data */
 	unsigned int		ili_last_fields;   /* fields when flushed */
-	struct xfs_bmbt_rec_64	*ili_extents_buf;  /* array of logged
+	struct xfs_bmbt_rec	*ili_extents_buf;  /* array of logged
 						      data exts */
-	struct xfs_bmbt_rec_64	*ili_aextents_buf; /* array of logged
+	struct xfs_bmbt_rec	*ili_aextents_buf; /* array of logged
 						      attr exts */
 	unsigned int            ili_pushbuf_flag;  /* one bit used in push_ail */
 
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 4cb1792..600b5b0 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1441,6 +1441,7 @@
 	XFS_BUF_ZEROFLAGS(bp);
 	XFS_BUF_BUSY(bp);
 	XFS_BUF_ASYNC(bp);
+	bp->b_flags |= XBF_LOG_BUFFER;
 	/*
 	 * Do an ordered write for the log block.
 	 * Its unnecessary to flush the first split block in the log wrap case.
@@ -1478,6 +1479,7 @@
 		XFS_BUF_ZEROFLAGS(bp);
 		XFS_BUF_BUSY(bp);
 		XFS_BUF_ASYNC(bp);
+		bp->b_flags |= XBF_LOG_BUFFER;
 		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
 			XFS_BUF_ORDERED(bp);
 		dptr = XFS_BUF_PTR(bp);
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 5c823d5..d814da4 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -85,7 +85,8 @@
 #define ACPI_LV_INIT                0x00000001
 #define ACPI_LV_DEBUG_OBJECT        0x00000002
 #define ACPI_LV_INFO                0x00000004
-#define ACPI_LV_ALL_EXCEPTIONS      0x00000007
+#define ACPI_LV_REPAIR              0x00000008
+#define ACPI_LV_ALL_EXCEPTIONS      0x0000000F
 
 /* Trace verbosity level 1 [Standard Trace Level] */
 
@@ -143,6 +144,7 @@
 #define ACPI_DB_INIT                ACPI_DEBUG_LEVEL (ACPI_LV_INIT)
 #define ACPI_DB_DEBUG_OBJECT        ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT)
 #define ACPI_DB_INFO                ACPI_DEBUG_LEVEL (ACPI_LV_INFO)
+#define ACPI_DB_REPAIR              ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR)
 #define ACPI_DB_ALL_EXCEPTIONS      ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS)
 
 /* Trace level -- also used in the global "DebugLevel" */
@@ -174,8 +176,8 @@
 
 /* Defaults for debug_level, debug and normal */
 
-#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INFO)
-#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT)
+#define ACPI_DEBUG_DEFAULT          (ACPI_LV_INFO | ACPI_LV_REPAIR)
+#define ACPI_NORMAL_DEFAULT         (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT | ACPI_LV_REPAIR)
 #define ACPI_DEBUG_ALL              (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
 
 #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 5e1ad3c..86e9735 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20091112
+#define ACPI_CA_VERSION                 0x20091214
 
 #include "actypes.h"
 #include "actbl.h"
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 8b668ea..29245c6 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -294,7 +294,7 @@
 #ifdef CONFIG_CPU_FREQ
 void acpi_processor_ppc_init(void);
 void acpi_processor_ppc_exit(void);
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr);
+int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
 extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit);
 #else
 static inline void acpi_processor_ppc_init(void)
@@ -305,7 +305,8 @@
 {
 	return;
 }
-static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
+static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
+								int event_flag)
 {
 	static unsigned int printout = 1;
 	if (printout) {
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 681ddf3..fcd268c 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -51,7 +51,7 @@
 #endif
 
 /*
- * Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
+ * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
  * for O_DSYNC semantics now, but using the correct symbolic name for it.
  * This new value is used to request true Posix O_SYNC semantics.  It is
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 204bed3..485eeb6 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -145,6 +145,7 @@
 extern int gpio_export(unsigned gpio, bool direction_may_change);
 extern int gpio_export_link(struct device *dev, const char *name,
 			unsigned gpio);
+extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
 extern void gpio_unexport(unsigned gpio);
 
 #endif	/* CONFIG_GPIO_SYSFS */
@@ -197,6 +198,11 @@
 	return -ENOSYS;
 }
 
+static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
+{
+	return -ENOSYS;
+}
+
 static inline void gpio_unexport(unsigned gpio)
 {
 }
diff --git a/include/asm-generic/mman-common.h b/include/asm-generic/mman-common.h
index 2011126..3da9e27 100644
--- a/include/asm-generic/mman-common.h
+++ b/include/asm-generic/mman-common.h
@@ -40,6 +40,7 @@
 #define MADV_DONTFORK	10		/* don't inherit across fork */
 #define MADV_DOFORK	11		/* do inherit across fork */
 #define MADV_HWPOISON	100		/* poison a page for testing */
+#define MADV_SOFT_OFFLINE 101		/* soft offline page for testing */
 
 #define MADV_MERGEABLE   12		/* KSM may merge identical pages */
 #define MADV_UNMERGEABLE 13		/* KSM may not merge identical pages */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index b6e818f..67e6520 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -52,8 +52,12 @@
 #define LOAD_OFFSET 0
 #endif
 
-#ifndef VMLINUX_SYMBOL
-#define VMLINUX_SYMBOL(_sym_) _sym_
+#ifndef SYMBOL_PREFIX
+#define VMLINUX_SYMBOL(sym) sym
+#else
+#define PASTE2(x,y) x##y
+#define PASTE(x,y) PASTE2(x,y)
+#define VMLINUX_SYMBOL(sym) PASTE(SYMBOL_PREFIX, sym)
 #endif
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
diff --git a/include/drm/Kbuild b/include/drm/Kbuild
index cfa6af4..bd3a1c2 100644
--- a/include/drm/Kbuild
+++ b/include/drm/Kbuild
@@ -7,5 +7,6 @@
 unifdef-y += radeon_drm.h
 unifdef-y += sis_drm.h
 unifdef-y += savage_drm.h
+unifdef-y += vmwgfx_drm.h
 unifdef-y += via_drm.h
 unifdef-y += nouveau_drm.h
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h
index 703ca4d..0d9db09 100644
--- a/include/drm/ttm/ttm_object.h
+++ b/include/drm/ttm/ttm_object.h
@@ -77,7 +77,11 @@
 	ttm_buffer_type,
 	ttm_lock_type,
 	ttm_driver_type0 = 256,
-	ttm_driver_type1
+	ttm_driver_type1,
+	ttm_driver_type2,
+	ttm_driver_type3,
+	ttm_driver_type4,
+	ttm_driver_type5
 };
 
 struct ttm_object_file;
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
new file mode 100644
index 0000000..2be7e12
--- /dev/null
+++ b/include/drm/vmwgfx_drm.h
@@ -0,0 +1,574 @@
+/**************************************************************************
+ *
+ * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef __VMWGFX_DRM_H__
+#define __VMWGFX_DRM_H__
+
+#define DRM_VMW_MAX_SURFACE_FACES 6
+#define DRM_VMW_MAX_MIP_LEVELS 24
+
+#define DRM_VMW_EXT_NAME_LEN 128
+
+#define DRM_VMW_GET_PARAM            0
+#define DRM_VMW_ALLOC_DMABUF         1
+#define DRM_VMW_UNREF_DMABUF         2
+#define DRM_VMW_CURSOR_BYPASS        3
+/* guarded by DRM_VMW_PARAM_NUM_STREAMS != 0*/
+#define DRM_VMW_CONTROL_STREAM       4
+#define DRM_VMW_CLAIM_STREAM         5
+#define DRM_VMW_UNREF_STREAM         6
+/* guarded by DRM_VMW_PARAM_3D == 1 */
+#define DRM_VMW_CREATE_CONTEXT       7
+#define DRM_VMW_UNREF_CONTEXT        8
+#define DRM_VMW_CREATE_SURFACE       9
+#define DRM_VMW_UNREF_SURFACE        10
+#define DRM_VMW_REF_SURFACE          11
+#define DRM_VMW_EXECBUF              12
+#define DRM_VMW_FIFO_DEBUG           13
+#define DRM_VMW_FENCE_WAIT           14
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_GET_PARAM - get device information.
+ *
+ * DRM_VMW_PARAM_FIFO_OFFSET:
+ * Offset to use to map the first page of the FIFO read-only.
+ * The fifo is mapped using the mmap() system call on the drm device.
+ *
+ * DRM_VMW_PARAM_OVERLAY_IOCTL:
+ * Does the driver support the overlay ioctl.
+ */
+
+#define DRM_VMW_PARAM_NUM_STREAMS      0
+#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
+#define DRM_VMW_PARAM_3D               2
+#define DRM_VMW_PARAM_FIFO_OFFSET      3
+
+
+/**
+ * struct drm_vmw_getparam_arg
+ *
+ * @value: Returned value. //Out
+ * @param: Parameter to query. //In.
+ *
+ * Argument to the DRM_VMW_GET_PARAM Ioctl.
+ */
+
+struct drm_vmw_getparam_arg {
+	uint64_t value;
+	uint32_t param;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_EXTENSION - Query device extensions.
+ */
+
+/**
+ * struct drm_vmw_extension_rep
+ *
+ * @exists: The queried extension exists.
+ * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension.
+ * @driver_sarea_offset: Offset to any space in the DRI SAREA
+ * used by the extension.
+ * @major: Major version number of the extension.
+ * @minor: Minor version number of the extension.
+ * @pl: Patch level version number of the extension.
+ *
+ * Output argument to the DRM_VMW_EXTENSION Ioctl.
+ */
+
+struct drm_vmw_extension_rep {
+	int32_t exists;
+	uint32_t driver_ioctl_offset;
+	uint32_t driver_sarea_offset;
+	uint32_t major;
+	uint32_t minor;
+	uint32_t pl;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_extension_arg
+ *
+ * @extension - Ascii name of the extension to be queried. //In
+ * @rep - Reply as defined above. //Out
+ *
+ * Argument to the DRM_VMW_EXTENSION Ioctl.
+ */
+
+union drm_vmw_extension_arg {
+	char extension[DRM_VMW_EXT_NAME_LEN];
+	struct drm_vmw_extension_rep rep;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_CONTEXT - Create a host context.
+ *
+ * Allocates a device unique context id, and queues a create context command
+ * for the host. Does not wait for host completion.
+ */
+
+/**
+ * struct drm_vmw_context_arg
+ *
+ * @cid: Device unique context ID.
+ *
+ * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
+ * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
+ */
+
+struct drm_vmw_context_arg {
+	int32_t cid;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_CONTEXT - Create a host context.
+ *
+ * Frees a global context id, and queues a destroy host command for the host.
+ * Does not wait for host completion. The context ID can be used directly
+ * in the command stream and shows up as the same context ID on the host.
+ */
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CREATE_SURFACE - Create a host suface.
+ *
+ * Allocates a device unique surface id, and queues a create surface command
+ * for the host. Does not wait for host completion. The surface ID can be
+ * used directly in the command stream and shows up as the same surface
+ * ID on the host.
+ */
+
+/**
+ * struct drm_wmv_surface_create_req
+ *
+ * @flags: Surface flags as understood by the host.
+ * @format: Surface format as understood by the host.
+ * @mip_levels: Number of mip levels for each face.
+ * An unused face should have 0 encoded.
+ * @size_addr: Address of a user-space array of sruct drm_vmw_size
+ * cast to an uint64_t for 32-64 bit compatibility.
+ * The size of the array should equal the total number of mipmap levels.
+ * @shareable: Boolean whether other clients (as identified by file descriptors)
+ * may reference this surface.
+ *
+ * Input data to the DRM_VMW_CREATE_SURFACE Ioctl.
+ * Output data from the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+struct drm_vmw_surface_create_req {
+	uint32_t flags;
+	uint32_t format;
+	uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
+	uint64_t size_addr;
+	int32_t shareable;
+	uint32_t pad64;
+};
+
+/**
+ * struct drm_wmv_surface_arg
+ *
+ * @sid: Surface id of created surface or surface to destroy or reference.
+ *
+ * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
+ * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
+ * Input argument to the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+struct drm_vmw_surface_arg {
+	int32_t sid;
+	uint32_t pad64;
+};
+
+/**
+ * struct drm_vmw_size ioctl.
+ *
+ * @width - mip level width
+ * @height - mip level height
+ * @depth - mip level depth
+ *
+ * Description of a mip level.
+ * Input data to the DRM_WMW_CREATE_SURFACE Ioctl.
+ */
+
+struct drm_vmw_size {
+	uint32_t width;
+	uint32_t height;
+	uint32_t depth;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_surface_create_arg
+ *
+ * @rep: Output data as described above.
+ * @req: Input data as described above.
+ *
+ * Argument to the DRM_VMW_CREATE_SURFACE Ioctl.
+ */
+
+union drm_vmw_surface_create_arg {
+	struct drm_vmw_surface_arg rep;
+	struct drm_vmw_surface_create_req req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_REF_SURFACE - Reference a host surface.
+ *
+ * Puts a reference on a host surface with a give sid, as previously
+ * returned by the DRM_VMW_CREATE_SURFACE ioctl.
+ * A reference will make sure the surface isn't destroyed while we hold
+ * it and will allow the calling client to use the surface ID in the command
+ * stream.
+ *
+ * On successful return, the Ioctl returns the surface information given
+ * in the DRM_VMW_CREATE_SURFACE ioctl.
+ */
+
+/**
+ * union drm_vmw_surface_reference_arg
+ *
+ * @rep: Output data as described above.
+ * @req: Input data as described above.
+ *
+ * Argument to the DRM_VMW_REF_SURFACE Ioctl.
+ */
+
+union drm_vmw_surface_reference_arg {
+	struct drm_vmw_surface_create_req rep;
+	struct drm_vmw_surface_arg req;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_SURFACE - Unreference a host surface.
+ *
+ * Clear a reference previously put on a host surface.
+ * When all references are gone, including the one implicitly placed
+ * on creation,
+ * a destroy surface command will be queued for the host.
+ * Does not wait for completion.
+ */
+
+/*************************************************************************/
+/**
+ * DRM_VMW_EXECBUF
+ *
+ * Submit a command buffer for execution on the host, and return a
+ * fence sequence that when signaled, indicates that the command buffer has
+ * executed.
+ */
+
+/**
+ * struct drm_vmw_execbuf_arg
+ *
+ * @commands: User-space address of a command buffer cast to an uint64_t.
+ * @command-size: Size in bytes of the command buffer.
+ * @fence_rep: User-space address of a struct drm_vmw_fence_rep cast to an
+ * uint64_t.
+ *
+ * Argument to the DRM_VMW_EXECBUF Ioctl.
+ */
+
+struct drm_vmw_execbuf_arg {
+	uint64_t commands;
+	uint32_t command_size;
+	uint32_t pad64;
+	uint64_t fence_rep;
+};
+
+/**
+ * struct drm_vmw_fence_rep
+ *
+ * @fence_seq: Fence sequence associated with a command submission.
+ * @error: This member should've been set to -EFAULT on submission.
+ * The following actions should be take on completion:
+ * error == -EFAULT: Fence communication failed. The host is synchronized.
+ * Use the last fence id read from the FIFO fence register.
+ * error != 0 && error != -EFAULT:
+ * Fence submission failed. The host is synchronized. Use the fence_seq member.
+ * error == 0: All is OK, The host may not be synchronized.
+ * Use the fence_seq member.
+ *
+ * Input / Output data to the DRM_VMW_EXECBUF Ioctl.
+ */
+
+struct drm_vmw_fence_rep {
+	uint64_t fence_seq;
+	int32_t error;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_ALLOC_DMABUF
+ *
+ * Allocate a DMA buffer that is visible also to the host.
+ * NOTE: The buffer is
+ * identified by a handle and an offset, which are private to the guest, but
+ * useable in the command stream. The guest kernel may translate these
+ * and patch up the command stream accordingly. In the future, the offset may
+ * be zero at all times, or it may disappear from the interface before it is
+ * fixed.
+ *
+ * The DMA buffer may stay user-space mapped in the guest at all times,
+ * and is thus suitable for sub-allocation.
+ *
+ * DMA buffers are mapped using the mmap() syscall on the drm device.
+ */
+
+/**
+ * struct drm_vmw_alloc_dmabuf_req
+ *
+ * @size: Required minimum size of the buffer.
+ *
+ * Input data to the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+struct drm_vmw_alloc_dmabuf_req {
+	uint32_t size;
+	uint32_t pad64;
+};
+
+/**
+ * struct drm_vmw_dmabuf_rep
+ *
+ * @map_handle: Offset to use in the mmap() call used to map the buffer.
+ * @handle: Handle unique to this buffer. Used for unreferencing.
+ * @cur_gmr_id: GMR id to use in the command stream when this buffer is
+ * referenced. See not above.
+ * @cur_gmr_offset: Offset to use in the command stream when this buffer is
+ * referenced. See note above.
+ *
+ * Output data from the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+struct drm_vmw_dmabuf_rep {
+	uint64_t map_handle;
+	uint32_t handle;
+	uint32_t cur_gmr_id;
+	uint32_t cur_gmr_offset;
+	uint32_t pad64;
+};
+
+/**
+ * union drm_vmw_dmabuf_arg
+ *
+ * @req: Input data as described above.
+ * @rep: Output data as described above.
+ *
+ * Argument to the DRM_VMW_ALLOC_DMABUF Ioctl.
+ */
+
+union drm_vmw_alloc_dmabuf_arg {
+	struct drm_vmw_alloc_dmabuf_req req;
+	struct drm_vmw_dmabuf_rep rep;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_DMABUF - Free a DMA buffer.
+ *
+ */
+
+/**
+ * struct drm_vmw_unref_dmabuf_arg
+ *
+ * @handle: Handle indicating what buffer to free. Obtained from the
+ * DRM_VMW_ALLOC_DMABUF Ioctl.
+ *
+ * Argument to the DRM_VMW_UNREF_DMABUF Ioctl.
+ */
+
+struct drm_vmw_unref_dmabuf_arg {
+	uint32_t handle;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_FIFO_DEBUG - Get last FIFO submission.
+ *
+ * This IOCTL copies the last FIFO submission directly out of the FIFO buffer.
+ */
+
+/**
+ * struct drm_vmw_fifo_debug_arg
+ *
+ * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In
+ * @debug_buffer_size: Size in bytes of debug buffer //In
+ * @used_size: Number of bytes copied to the buffer // Out
+ * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out
+ *
+ * Argument to the DRM_VMW_FIFO_DEBUG Ioctl.
+ */
+
+struct drm_vmw_fifo_debug_arg {
+	uint64_t debug_buffer;
+	uint32_t debug_buffer_size;
+	uint32_t used_size;
+	int32_t did_not_fit;
+	uint32_t pad64;
+};
+
+struct drm_vmw_fence_wait_arg {
+	uint64_t sequence;
+	uint64_t kernel_cookie;
+	int32_t cookie_valid;
+	int32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CONTROL_STREAM - Control overlays, aka streams.
+ *
+ * This IOCTL controls the overlay units of the svga device.
+ * The SVGA overlay units does not work like regular hardware units in
+ * that they do not automaticaly read back the contents of the given dma
+ * buffer. But instead only read back for each call to this ioctl, and
+ * at any point between this call being made and a following call that
+ * either changes the buffer or disables the stream.
+ */
+
+/**
+ * struct drm_vmw_rect
+ *
+ * Defines a rectangle. Used in the overlay ioctl to define
+ * source and destination rectangle.
+ */
+
+struct drm_vmw_rect {
+	int32_t x;
+	int32_t y;
+	uint32_t w;
+	uint32_t h;
+};
+
+/**
+ * struct drm_vmw_control_stream_arg
+ *
+ * @stream_id: Stearm to control
+ * @enabled: If false all following arguments are ignored.
+ * @handle: Handle to buffer for getting data from.
+ * @format: Format of the overlay as understood by the host.
+ * @width: Width of the overlay.
+ * @height: Height of the overlay.
+ * @size: Size of the overlay in bytes.
+ * @pitch: Array of pitches, the two last are only used for YUV12 formats.
+ * @offset: Offset from start of dma buffer to overlay.
+ * @src: Source rect, must be within the defined area above.
+ * @dst: Destination rect, x and y may be negative.
+ *
+ * Argument to the DRM_VMW_CONTROL_STREAM Ioctl.
+ */
+
+struct drm_vmw_control_stream_arg {
+	uint32_t stream_id;
+	uint32_t enabled;
+
+	uint32_t flags;
+	uint32_t color_key;
+
+	uint32_t handle;
+	uint32_t offset;
+	int32_t format;
+	uint32_t size;
+	uint32_t width;
+	uint32_t height;
+	uint32_t pitch[3];
+
+	uint32_t pad64;
+	struct drm_vmw_rect src;
+	struct drm_vmw_rect dst;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CURSOR_BYPASS - Give extra information about cursor bypass.
+ *
+ */
+
+#define DRM_VMW_CURSOR_BYPASS_ALL    (1 << 0)
+#define DRM_VMW_CURSOR_BYPASS_FLAGS       (1)
+
+/**
+ * struct drm_vmw_cursor_bypass_arg
+ *
+ * @flags: Flags.
+ * @crtc_id: Crtc id, only used if DMR_CURSOR_BYPASS_ALL isn't passed.
+ * @xpos: X position of cursor.
+ * @ypos: Y position of cursor.
+ * @xhot: X hotspot.
+ * @yhot: Y hotspot.
+ *
+ * Argument to the DRM_VMW_CURSOR_BYPASS Ioctl.
+ */
+
+struct drm_vmw_cursor_bypass_arg {
+	uint32_t flags;
+	uint32_t crtc_id;
+	int32_t xpos;
+	int32_t ypos;
+	int32_t xhot;
+	int32_t yhot;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_CLAIM_STREAM - Claim a single stream.
+ */
+
+/**
+ * struct drm_vmw_context_arg
+ *
+ * @stream_id: Device unique context ID.
+ *
+ * Output argument to the DRM_VMW_CREATE_CONTEXT Ioctl.
+ * Input argument to the DRM_VMW_UNREF_CONTEXT Ioctl.
+ */
+
+struct drm_vmw_stream_arg {
+	uint32_t stream_id;
+	uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UNREF_STREAM - Unclaim a stream.
+ *
+ * Return a single stream that was claimed by this process. Also makes
+ * sure that the stream has been stopped.
+ */
+
+#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index f72914d..756f831 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -118,6 +118,7 @@
 header-y += ncp_no.h
 header-y += neighbour.h
 header-y += net_dropmon.h
+header-y += net_tstamp.h
 header-y += netfilter_arp.h
 header-y += netrom.h
 header-y += nfs2.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dfcd920..ce945d4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -240,7 +240,7 @@
 #define PXM_INVAL	(-1)
 #define NID_INVAL	(-1)
 
-int acpi_check_resource_conflict(struct resource *res);
+int acpi_check_resource_conflict(const struct resource *res);
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
 		      const char *name);
@@ -253,10 +253,16 @@
 void __init acpi_s4_no_nvs(void);
 #endif /* CONFIG_PM_SLEEP */
 
+struct acpi_osc_context {
+	char *uuid_str; /* uuid string */
+	int rev;
+	struct acpi_buffer cap; /* arg2/arg3 */
+	struct acpi_buffer ret; /* free by caller if success */
+};
+
 #define OSC_QUERY_TYPE			0
 #define OSC_SUPPORT_TYPE 		1
 #define OSC_CONTROL_TYPE		2
-#define OSC_SUPPORT_MASKS		0x1f
 
 /* _OSC DW0 Definition */
 #define OSC_QUERY_ENABLE		1
@@ -265,12 +271,23 @@
 #define OSC_INVALID_REVISION_ERROR	8
 #define OSC_CAPABILITIES_MASK_ERROR	16
 
+acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
+
+/* platform-wide _OSC bits */
+#define OSC_SB_PAD_SUPPORT		1
+#define OSC_SB_PPC_OST_SUPPORT		2
+#define OSC_SB_PR3_SUPPORT		4
+#define OSC_SB_CPUHP_OST_SUPPORT	8
+#define OSC_SB_APEI_SUPPORT		16
+
+/* PCI defined _OSC bits */
 /* _OSC DW1 Definition (OS Support Fields) */
 #define OSC_EXT_PCI_CONFIG_SUPPORT		1
 #define OSC_ACTIVE_STATE_PWR_SUPPORT 		2
 #define OSC_CLOCK_PWR_CAPABILITY_SUPPORT	4
 #define OSC_PCI_SEGMENT_GROUPS_SUPPORT		8
 #define OSC_MSI_SUPPORT				16
+#define OSC_PCI_SUPPORT_MASKS			0x1f
 
 /* _OSC DW1 Definition (OS Control Fields) */
 #define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL	1
@@ -279,7 +296,7 @@
 #define OSC_PCI_EXPRESS_AER_CONTROL		8
 #define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL	16
 
-#define OSC_CONTROL_MASKS 	(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | 	\
+#define OSC_PCI_CONTROL_MASKS 	(OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | 	\
 				OSC_SHPC_NATIVE_HP_CONTROL | 		\
 				OSC_PCI_EXPRESS_PME_CONTROL |		\
 				OSC_PCI_EXPRESS_AER_CONTROL |		\
diff --git a/include/linux/aio.h b/include/linux/aio.h
index aea219d..811dbb3 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -102,7 +102,6 @@
 	} ki_obj;
 
 	__u64			ki_user_data;	/* user's data for completion */
-	wait_queue_t		ki_wait;
 	loff_t			ki_pos;
 
 	void			*private;
@@ -140,7 +139,6 @@
 		(x)->ki_dtor = NULL;			\
 		(x)->ki_obj.tsk = tsk;			\
 		(x)->ki_user_data = 0;                  \
-		init_wait((&(x)->ki_wait));             \
 	} while (0)
 
 #define AIO_RING_MAGIC			0xa10a10a1
@@ -223,8 +221,6 @@
 static inline void exit_aio(struct mm_struct *mm) { }
 #endif /* CONFIG_AIO */
 
-#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
-
 static inline struct kiocb *list_kiocb(struct list_head *h)
 {
 	return list_entry(h, struct kiocb, ki_list);
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 0f5f578..8c4f884 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -36,18 +36,18 @@
 struct fb_info;
 
 struct backlight_ops {
-	unsigned int options;
+	const unsigned int options;
 
 #define BL_CORE_SUSPENDRESUME	(1 << 0)
 
 	/* Notify the backlight driver some property has changed */
-	int (*update_status)(struct backlight_device *);
+	int (* const update_status)(struct backlight_device *);
 	/* Return the current backlight brightness (accounting for power,
 	   fb_blank etc.) */
-	int (*get_brightness)(struct backlight_device *);
+	int (* const get_brightness)(struct backlight_device *);
 	/* Check if given framebuffer device is the one bound to this backlight;
 	   return 0 if not, !=0 if it is. If NULL, backlight always matches the fb. */
-	int (*check_fb)(struct fb_info *);
+	int (* const check_fb)(struct fb_info *);
 };
 
 /* This structure defines all the properties of a backlight */
@@ -86,7 +86,7 @@
 	   registered this device has been unloaded, and if class_get_devdata()
 	   points to something in the body of that driver, it is also invalid. */
 	struct mutex ops_lock;
-	struct backlight_ops *ops;
+	const struct backlight_ops *ops;
 
 	/* The framebuffer notifier block */
 	struct notifier_block fb_notif;
@@ -103,7 +103,7 @@
 }
 
 extern struct backlight_device *backlight_device_register(const char *name,
-	struct device *dev, void *devdata, struct backlight_ops *ops);
+	struct device *dev, void *devdata, const struct backlight_ops *ops);
 extern void backlight_device_unregister(struct backlight_device *bd);
 extern void backlight_force_update(struct backlight_device *bd,
 				   enum backlight_update_reason reason);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index aece486..cd4349b 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -68,6 +68,14 @@
 
 #define BINPRM_MAX_RECURSION 4
 
+/* Function parameter for binfmt->coredump */
+struct coredump_params {
+	long signr;
+	struct pt_regs *regs;
+	struct file *file;
+	unsigned long limit;
+};
+
 /*
  * This structure defines the functions that are used to load the binary formats that
  * linux accepts.
@@ -77,7 +85,7 @@
 	struct module *module;
 	int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
 	int (*load_shlib)(struct file *);
-	int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
+	int (*core_dump)(struct coredump_params *cprm);
 	unsigned long min_coredump;	/* minimal dump size */
 	int hasvdso;
 };
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 756d78b..daf8c48 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -42,6 +42,9 @@
  * bitmap_empty(src, nbits)			Are all bits zero in *src?
  * bitmap_full(src, nbits)			Are all bits set in *src?
  * bitmap_weight(src, nbits)			Hamming Weight: number set bits
+ * bitmap_set(dst, pos, nbits)			Set specified bit area
+ * bitmap_clear(dst, pos, nbits)		Clear specified bit area
+ * bitmap_find_next_zero_area(buf, len, pos, n, mask)	Find bit free area
  * bitmap_shift_right(dst, src, n, nbits)	*dst = *src >> n
  * bitmap_shift_left(dst, src, n, nbits)	*dst = *src << n
  * bitmap_remap(dst, src, old, new, nbits)	*dst = map(old, new)(src)
@@ -108,6 +111,14 @@
 			const unsigned long *bitmap2, int bits);
 extern int __bitmap_weight(const unsigned long *bitmap, int bits);
 
+extern void bitmap_set(unsigned long *map, int i, int len);
+extern void bitmap_clear(unsigned long *map, int start, int nr);
+extern unsigned long bitmap_find_next_zero_area(unsigned long *map,
+					 unsigned long size,
+					 unsigned long start,
+					 unsigned int nr,
+					 unsigned long align_mask);
+
 extern int bitmap_scnprintf(char *buf, unsigned int len,
 			const unsigned long *src, int nbits);
 extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 1ed2a5c..3db7767 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -51,6 +51,15 @@
 	struct sk_buff **echo_skb;
 };
 
+/*
+ * get_can_dlc(value) - helper macro to cast a given data length code (dlc)
+ * to __u8 and ensure the dlc value to be max. 8 bytes.
+ *
+ * To be used in the CAN netdriver receive path to ensure conformance with
+ * ISO 11898-1 Chapter 8.4.2.3 (DLC field)
+ */
+#define get_can_dlc(i)	(min_t(__u8, (i), 8))
+
 struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
 void free_candev(struct net_device *dev);
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 2b9f2ac..7878498 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -74,7 +74,7 @@
  *  control completion, and communicate status.
  * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
  *  this transaction
- * @DMA_CTRL_ACK - the descriptor cannot be reused until the client
+ * @DMA_CTRL_ACK - if clear, the descriptor cannot be reused until the client
  *  acknowledges receipt, i.e. has has a chance to establish any dependency
  *  chains
  * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s)
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index 90d1c21..9a33c5f 100644
--- a/include/linux/enclosure.h
+++ b/include/linux/enclosure.h
@@ -42,6 +42,8 @@
 	ENCLOSURE_STATUS_NOT_INSTALLED,
 	ENCLOSURE_STATUS_UNKNOWN,
 	ENCLOSURE_STATUS_UNAVAILABLE,
+	/* last element for counting purposes */
+	ENCLOSURE_STATUS_MAX
 };
 
 /* SFF-8485 activity light settings */
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 27e772c..dc12f41 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -97,7 +97,7 @@
  * @get_name:       find the name for a given inode in a given directory
  * @get_parent:     find the parent of a given directory
  *
- * See Documentation/filesystems/Exporting for details on how to use
+ * See Documentation/filesystems/nfs/Exporting for details on how to use
  * this interface correctly.
  *
  * encode_fh:
diff --git a/include/linux/file.h b/include/linux/file.h
index 335a0a5..5555508 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -18,11 +18,9 @@
 struct file_operations;
 struct vfsmount;
 struct dentry;
-extern int init_file(struct file *, struct vfsmount *mnt,
-		struct dentry *dentry, fmode_t mode,
-		const struct file_operations *fop);
-extern struct file *alloc_file(struct vfsmount *, struct dentry *dentry,
-		fmode_t mode, const struct file_operations *fop);
+struct path;
+extern struct file *alloc_file(struct path *, fmode_t mode,
+	const struct file_operations *fop);
 
 static inline void fput_light(struct file *file, int fput_needed)
 {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a057f48..cca1919 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -152,6 +152,7 @@
 #define WRITE_SYNC_PLUG	(WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE))
 #define WRITE_SYNC	(WRITE_SYNC_PLUG | (1 << BIO_RW_UNPLUG))
 #define WRITE_ODIRECT_PLUG	(WRITE | (1 << BIO_RW_SYNCIO))
+#define WRITE_META	(WRITE | (1 << BIO_RW_META))
 #define SWRITE_SYNC_PLUG	\
 			(SWRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_NOIDLE))
 #define SWRITE_SYNC	(SWRITE_SYNC_PLUG | (1 << BIO_RW_UNPLUG))
@@ -1094,10 +1095,6 @@
 
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
-/* fs/sync.c */
-extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
-			loff_t endbyte, unsigned int flags);
-
 #ifdef CONFIG_FILE_LOCKING
 extern int fcntl_getlk(struct file *, struct flock __user *);
 extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
@@ -1590,7 +1587,7 @@
  * until that flag is cleared.  I_WILL_FREE, I_FREEING and I_CLEAR are set at
  * various stages of removing an inode.
  *
- * Two bits are used for locking and completion notification, I_LOCK and I_SYNC.
+ * Two bits are used for locking and completion notification, I_NEW and I_SYNC.
  *
  * I_DIRTY_SYNC		Inode is dirty, but doesn't have to be written on
  *			fdatasync().  i_atime is the usual cause.
@@ -1599,8 +1596,14 @@
  *			don't have to write inode on fdatasync() when only
  *			mtime has changed in it.
  * I_DIRTY_PAGES	Inode has dirty pages.  Inode itself may be clean.
- * I_NEW		get_new_inode() sets i_state to I_LOCK|I_NEW.  Both
- *			are cleared by unlock_new_inode(), called from iget().
+ * I_NEW		Serves as both a mutex and completion notification.
+ *			New inodes set I_NEW.  If two processes both create
+ *			the same inode, one of them will release its inode and
+ *			wait for I_NEW to be released before returning.
+ *			Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
+ *			also cause waiting on I_NEW, without I_NEW actually
+ *			being set.  find_inode() uses this to prevent returning
+ *			nearly-dead inodes.
  * I_WILL_FREE		Must be set when calling write_inode_now() if i_count
  *			is zero.  I_FREEING must be set when I_WILL_FREE is
  *			cleared.
@@ -1614,20 +1617,11 @@
  *			prohibited for many purposes.  iget() must wait for
  *			the inode to be completely released, then create it
  *			anew.  Other functions will just ignore such inodes,
- *			if appropriate.  I_LOCK is used for waiting.
+ *			if appropriate.  I_NEW is used for waiting.
  *
- * I_LOCK		Serves as both a mutex and completion notification.
- *			New inodes set I_LOCK.  If two processes both create
- *			the same inode, one of them will release its inode and
- *			wait for I_LOCK to be released before returning.
- *			Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
- *			also cause waiting on I_LOCK, without I_LOCK actually
- *			being set.  find_inode() uses this to prevent returning
- *			nearly-dead inodes.
- * I_SYNC		Similar to I_LOCK, but limited in scope to writeback
- *			of inode dirty data.  Having a separate lock for this
- *			purpose reduces latency and prevents some filesystem-
- *			specific deadlocks.
+ * I_SYNC		Synchonized write of dirty inode data.  The bits is
+ *			set during data writeback, and cleared with a wakeup
+ *			on the bit address once it is done.
  *
  * Q: What is the difference between I_WILL_FREE and I_FREEING?
  * Q: igrab() only checks on (I_FREEING|I_WILL_FREE).  Should it also check on
@@ -1636,13 +1630,12 @@
 #define I_DIRTY_SYNC		1
 #define I_DIRTY_DATASYNC	2
 #define I_DIRTY_PAGES		4
-#define I_NEW			8
+#define __I_NEW			3
+#define I_NEW			(1 << __I_NEW)
 #define I_WILL_FREE		16
 #define I_FREEING		32
 #define I_CLEAR			64
-#define __I_LOCK		7
-#define I_LOCK			(1 << __I_LOCK)
-#define __I_SYNC		8
+#define __I_SYNC		7
 #define I_SYNC			(1 << __I_SYNC)
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
@@ -2189,7 +2182,6 @@
 	__insert_inode_hash(inode, inode->i_ino);
 }
 
-extern struct file * get_empty_filp(void);
 extern void file_move(struct file *f, struct list_head *list);
 extern void file_kill(struct file *f);
 #ifdef CONFIG_BLOCK
@@ -2264,9 +2256,11 @@
 	int lock_type);
 
 enum {
-	DIO_LOCKING = 1, /* need locking between buffered and direct access */
-	DIO_NO_LOCKING,  /* bdev; no locking at all between buffered/direct */
-	DIO_OWN_LOCKING, /* filesystem locks buffered and direct internally */
+	/* need locking between buffered and direct access */
+	DIO_LOCKING	= 0x01,
+
+	/* filesystem does not support filling holes */
+	DIO_SKIP_HOLES	= 0x02,
 };
 
 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
@@ -2275,7 +2269,8 @@
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_block, end_io, DIO_LOCKING);
+				    nr_segs, get_block, end_io,
+				    DIO_LOCKING | DIO_SKIP_HOLES);
 }
 
 static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
@@ -2284,16 +2279,7 @@
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_block, end_io, DIO_NO_LOCKING);
-}
-
-static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
-	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
-	loff_t offset, unsigned long nr_segs, get_block_t get_block,
-	dio_iodone_t end_io)
-{
-	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_block, end_io, DIO_OWN_LOCKING);
+				nr_segs, get_block, end_io, 0);
 }
 #endif
 
diff --git a/include/linux/fs_stack.h b/include/linux/fs_stack.h
index bb516ce..da317c7 100644
--- a/include/linux/fs_stack.h
+++ b/include/linux/fs_stack.h
@@ -8,10 +8,8 @@
 #include <linux/fs.h>
 
 /* externs for fs/stack.c */
-extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src,
-				int (*get_nlinks)(struct inode *));
-
-extern void fsstack_copy_inode_size(struct inode *dst, const struct inode *src);
+extern void fsstack_copy_attr_all(struct inode *dest, const struct inode *src);
+extern void fsstack_copy_inode_size(struct inode *dst, struct inode *src);
 
 /* inlines */
 static inline void fsstack_copy_attr_atime(struct inode *dest,
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 38f8d65..2233c98 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -131,7 +131,7 @@
 	void			*mod;
 	void			*data;
 
-	atomic_t		profile_count;
+	int			profile_count;
 	int			(*profile_enable)(struct ftrace_event_call *);
 	void			(*profile_disable)(struct ftrace_event_call *);
 };
@@ -158,7 +158,7 @@
 	FILTER_PTR_STRING,
 };
 
-extern int trace_define_common_fields(struct ftrace_event_call *call);
+extern int trace_event_raw_init(struct ftrace_event_call *call);
 extern int trace_define_field(struct ftrace_event_call *call, const char *type,
 			      const char *name, int offset, int size,
 			      int is_signed, int filter_type);
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h
index 886f5fa..ca666d1 100644
--- a/include/linux/generic_acl.h
+++ b/include/linux/generic_acl.h
@@ -1,36 +1,15 @@
-/*
- * include/linux/generic_acl.h
- *
- * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
- *
- * This file is released under the GPL.
- */
+#ifndef LINUX_GENERIC_ACL_H
+#define LINUX_GENERIC_ACL_H
 
-#ifndef GENERIC_ACL_H
-#define GENERIC_ACL_H
+#include <linux/xattr.h>
 
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
+struct inode;
 
-/**
- * struct generic_acl_operations  -  filesystem operations
- *
- * Filesystems must make these operations available to the generic
- * operations.
- */
-struct generic_acl_operations {
-	struct posix_acl *(*getacl)(struct inode *, int);
-	void (*setacl)(struct inode *, int, struct posix_acl *);
-};
+extern struct xattr_handler generic_acl_access_handler;
+extern struct xattr_handler generic_acl_default_handler;
 
-size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
-			char *, size_t);
-int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
-		    void *, size_t);
-int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
-		    const void *, size_t);
-int generic_acl_init(struct inode *, struct inode *,
-		     struct generic_acl_operations *);
-int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
+int generic_acl_init(struct inode *, struct inode *);
+int generic_acl_chmod(struct inode *);
+int generic_check_acl(struct inode *inode, int mask);
 
-#endif
+#endif /* LINUX_GENERIC_ACL_H */
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 059bd18..4e949a5 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -99,6 +99,12 @@
 	return -EINVAL;
 }
 
+static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
+{
+	/* GPIO can never have been requested */
+	WARN_ON(1);
+	return -EINVAL;
+}
 
 static inline void gpio_unexport(unsigned gpio)
 {
diff --git a/include/linux/i8042.h b/include/linux/i8042.h
index 60c3360..9bf6870 100644
--- a/include/linux/i8042.h
+++ b/include/linux/i8042.h
@@ -39,6 +39,10 @@
 void i8042_unlock_chip(void);
 int i8042_command(unsigned char *param, int command);
 bool i8042_check_port_owner(const struct serio *);
+int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
+					struct serio *serio));
+int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
+				       struct serio *serio));
 
 #else
 
@@ -52,7 +56,7 @@
 
 int i8042_command(unsigned char *param, int command)
 {
-	return -ENOSYS;
+	return -ENODEV;
 }
 
 bool i8042_check_port_owner(const struct serio *serio)
@@ -60,6 +64,18 @@
 	return false;
 }
 
+int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
+					struct serio *serio))
+{
+	return -ENODEV;
+}
+
+int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
+				       struct serio *serio))
+{
+	return -ENODEV;
+}
+
 #endif
 
 #endif
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0e3f2a4..99dc6d5 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -13,18 +13,14 @@
 #include <linux/fs.h>
 struct linux_binprm;
 
-#define IMA_COUNT_UPDATE 1
-#define IMA_COUNT_LEAVE 0
-
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_inode_alloc(struct inode *inode);
 extern void ima_inode_free(struct inode *inode);
-extern int ima_path_check(struct path *path, int mask, int update_counts);
+extern int ima_path_check(struct path *path, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern void ima_counts_get(struct file *file);
-extern void ima_counts_put(struct path *path, int mask);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -42,7 +38,7 @@
 	return;
 }
 
-static inline int ima_path_check(struct path *path, int mask, int update_counts)
+static inline int ima_path_check(struct path *path, int mask)
 {
 	return 0;
 }
@@ -62,9 +58,5 @@
 	return;
 }
 
-static inline void ima_counts_put(struct path *path, int mask)
-{
-	return;
-}
 #endif /* CONFIG_IMA_H */
 #endif /* _LINUX_IMA_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index ff8bde5..ab1d31f 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -149,6 +149,8 @@
 
 extern void (*late_time_init)(void);
 
+extern int initcall_debug;
+
 #endif
   
 #ifndef MODULE
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 5ed8b9c..abec69b 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -111,12 +111,6 @@
 # define INIT_PERF_EVENTS(tsk)
 #endif
 
-#ifdef CONFIG_FS_JOURNAL_INFO
-#define INIT_JOURNAL_INFO	.journal_info = NULL,
-#else
-#define INIT_JOURNAL_INFO
-#endif
-
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -168,6 +162,7 @@
 		.signal = {{0}}},					\
 	.blocked	= {{0}},					\
 	.alloc_lock	= __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),		\
+	.journal_info	= NULL,						\
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
 	.fs_excl	= ATOMIC_INIT(0),				\
 	.pi_lock	= __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),	\
@@ -178,7 +173,6 @@
 		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
 	},								\
 	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
-	INIT_JOURNAL_INFO						\
 	INIT_IDS							\
 	INIT_PERF_EVENTS(tsk)						\
 	INIT_TRACE_IRQFLAGS						\
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 4f0a72a..9310c69 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -332,6 +332,7 @@
 #ifdef CONFIG_INTR_REMAP
 	struct ir_table *ir_table;	/* Interrupt remapping info */
 #endif
+	int		node;
 };
 
 static inline void __iommu_flush_cache(
diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h
index 3b068e5b..64d1b63 100644
--- a/include/linux/iommu-helper.h
+++ b/include/linux/iommu-helper.h
@@ -14,14 +14,11 @@
 extern int iommu_is_span_boundary(unsigned int index, unsigned int nr,
 				  unsigned long shift,
 				  unsigned long boundary_size);
-extern void iommu_area_reserve(unsigned long *map, unsigned long i, int len);
 extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
 				      unsigned long start, unsigned int nr,
 				      unsigned long shift,
 				      unsigned long boundary_size,
 				      unsigned long align_mask);
-extern void iommu_area_free(unsigned long *map, unsigned long start,
-			    unsigned int nr);
 
 extern unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
 				     unsigned long io_page_size);
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 83aa812..7129504 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -126,11 +126,11 @@
 int adjust_resource(struct resource *res, resource_size_t start,
 		    resource_size_t size);
 resource_size_t resource_alignment(struct resource *res);
-static inline resource_size_t resource_size(struct resource *res)
+static inline resource_size_t resource_size(const struct resource *res)
 {
 	return res->end - res->start + 1;
 }
-static inline unsigned long resource_type(struct resource *res)
+static inline unsigned long resource_type(const struct resource *res)
 {
 	return res->flags & IORESOURCE_TYPE_BITS;
 }
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index e408722..07baa38 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -87,7 +87,7 @@
 /* default values */
 #define DFLT_QUEUESMAX 256     /* max number of message queues */
 #define DFLT_MSGMAX    10      /* max number of messages in each queue */
-#define HARD_MSGMAX    (131072/sizeof(void *))
+#define HARD_MSGMAX    (32768*sizeof(void *)/4)
 #define DFLT_MSGSIZEMAX 8192   /* max message size */
 #else
 static inline int mq_init_ns(struct ipc_namespace *ns) { return 0; }
diff --git a/include/linux/kernel-page-flags.h b/include/linux/kernel-page-flags.h
new file mode 100644
index 0000000..bd92a89
--- /dev/null
+++ b/include/linux/kernel-page-flags.h
@@ -0,0 +1,46 @@
+#ifndef LINUX_KERNEL_PAGE_FLAGS_H
+#define LINUX_KERNEL_PAGE_FLAGS_H
+
+/*
+ * Stable page flag bits exported to user space
+ */
+
+#define KPF_LOCKED		0
+#define KPF_ERROR		1
+#define KPF_REFERENCED		2
+#define KPF_UPTODATE		3
+#define KPF_DIRTY		4
+#define KPF_LRU			5
+#define KPF_ACTIVE		6
+#define KPF_SLAB		7
+#define KPF_WRITEBACK		8
+#define KPF_RECLAIM		9
+#define KPF_BUDDY		10
+
+/* 11-20: new additions in 2.6.31 */
+#define KPF_MMAP		11
+#define KPF_ANON		12
+#define KPF_SWAPCACHE		13
+#define KPF_SWAPBACKED		14
+#define KPF_COMPOUND_HEAD	15
+#define KPF_COMPOUND_TAIL	16
+#define KPF_HUGE		17
+#define KPF_UNEVICTABLE		18
+#define KPF_HWPOISON		19
+#define KPF_NOPAGE		20
+
+#define KPF_KSM			21
+
+/* kernel hacking assistances
+ * WARNING: subject to change, never rely on them!
+ */
+#define KPF_RESERVED		32
+#define KPF_MLOCKED		33
+#define KPF_MAPPEDTODISK	34
+#define KPF_PRIVATE		35
+#define KPF_PRIVATE_2		36
+#define KPF_OWNER_PRIVATE	37
+#define KPF_ARCH		38
+#define KPF_UNCACHED		39
+
+#endif /* LINUX_KERNEL_PAGE_FLAGS_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4d9c916..3fc9f5a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -535,6 +535,8 @@
 __trace_printk(unsigned long ip, const char *fmt, ...)
 	__attribute__ ((format (printf, 2, 3)));
 
+extern void trace_dump_stack(void);
+
 /*
  * The double __builtin_constant_p is because gcc will give us an error
  * if we try to allocate the static variable to fmt if it is not a
@@ -568,6 +570,7 @@
 static inline void tracing_start(void) { }
 static inline void tracing_stop(void) { }
 static inline void ftrace_off_permanent(void) { }
+static inline void trace_dump_stack(void) { }
 static inline int
 trace_printk(const char *fmt, ...)
 {
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index adc34f2..c356b69 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -206,6 +206,8 @@
 
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
 		unsigned long long *crash_size, unsigned long long *crash_base);
+int crash_shrink_memory(unsigned long new_size);
+size_t crash_get_memory_size(void);
 
 #else /* !CONFIG_KEXEC */
 struct pt_regs;
diff --git a/include/linux/kmemleak.h b/include/linux/kmemleak.h
index 3c7497d..99d9a67 100644
--- a/include/linux/kmemleak.h
+++ b/include/linux/kmemleak.h
@@ -32,8 +32,7 @@
 			     size_t size) __ref;
 extern void kmemleak_not_leak(const void *ptr) __ref;
 extern void kmemleak_ignore(const void *ptr) __ref;
-extern void kmemleak_scan_area(const void *ptr, unsigned long offset,
-			       size_t length, gfp_t gfp) __ref;
+extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref;
 extern void kmemleak_no_scan(const void *ptr) __ref;
 
 static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
@@ -84,8 +83,7 @@
 static inline void kmemleak_ignore(const void *ptr)
 {
 }
-static inline void kmemleak_scan_area(const void *ptr, unsigned long offset,
-				      size_t length, gfp_t gfp)
+static inline void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
 }
 static inline void kmemleak_erase(void **ptr)
diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h
new file mode 100644
index 0000000..e32aa26
--- /dev/null
+++ b/include/linux/kmsg_dump.h
@@ -0,0 +1,60 @@
+/*
+ * linux/include/kmsg_dump.h
+ *
+ * Copyright (C) 2009 Net Insight AB
+ *
+ * Author: Simon Kagstrom <simon.kagstrom@netinsight.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+#ifndef _LINUX_KMSG_DUMP_H
+#define _LINUX_KMSG_DUMP_H
+
+#include <linux/list.h>
+
+enum kmsg_dump_reason {
+	KMSG_DUMP_OOPS,
+	KMSG_DUMP_PANIC,
+};
+
+/**
+ * struct kmsg_dumper - kernel crash message dumper structure
+ * @dump:	The callback which gets called on crashes. The buffer is passed
+ * 		as two sections, where s1 (length l1) contains the older
+ * 		messages and s2 (length l2) contains the newer.
+ * @list:	Entry in the dumper list (private)
+ * @registered:	Flag that specifies if this is already registered
+ */
+struct kmsg_dumper {
+	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
+			const char *s1, unsigned long l1,
+			const char *s2, unsigned long l2);
+	struct list_head list;
+	int registered;
+};
+
+#ifdef CONFIG_PRINTK
+void kmsg_dump(enum kmsg_dump_reason reason);
+
+int kmsg_dump_register(struct kmsg_dumper *dumper);
+
+int kmsg_dump_unregister(struct kmsg_dumper *dumper);
+#else
+static inline void kmsg_dump(enum kmsg_dump_reason reason)
+{
+}
+
+static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+	return -EINVAL;
+}
+
+static inline int kmsg_dump_unregister(struct kmsg_dumper *dumper)
+{
+	return -EINVAL;
+}
+#endif
+
+#endif /* _LINUX_KMSG_DUMP_H */
diff --git a/include/linux/ksm.h b/include/linux/ksm.h
index bed5f16..43bdab7 100644
--- a/include/linux/ksm.h
+++ b/include/linux/ksm.h
@@ -94,12 +94,6 @@
 
 #else  /* !CONFIG_KSM */
 
-static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
-		unsigned long end, int advice, unsigned long *vm_flags)
-{
-	return 0;
-}
-
 static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
 {
 	return 0;
@@ -114,6 +108,13 @@
 	return 0;
 }
 
+#ifdef CONFIG_MMU
+static inline int ksm_madvise(struct vm_area_struct *vma, unsigned long start,
+		unsigned long end, int advice, unsigned long *vm_flags)
+{
+	return 0;
+}
+
 static inline struct page *ksm_might_need_to_copy(struct page *page,
 			struct vm_area_struct *vma, unsigned long address)
 {
@@ -140,6 +141,7 @@
 static inline void ksm_migrate_page(struct page *newpage, struct page *oldpage)
 {
 }
+#endif /* CONFIG_MMU */
 #endif /* !CONFIG_KSM */
 
 #endif /* __LINUX_KSM_H */
diff --git a/include/linux/leds-lp3944.h b/include/linux/leds-lp3944.h
index afc9f9f..2618aa9 100644
--- a/include/linux/leds-lp3944.h
+++ b/include/linux/leds-lp3944.h
@@ -12,9 +12,6 @@
 #ifndef __LINUX_LEDS_LP3944_H
 #define __LINUX_LEDS_LP3944_H
 
-#include <linux/leds.h>
-#include <linux/workqueue.h>
-
 #define LP3944_LED0 0
 #define LP3944_LED1 1
 #define LP3944_LED2 2
diff --git a/include/linux/leds-pca9532.h b/include/linux/leds-pca9532.h
index 96eea90..f158eb1 100644
--- a/include/linux/leds-pca9532.h
+++ b/include/linux/leds-pca9532.h
@@ -32,7 +32,7 @@
 	struct i2c_client *client;
 	char *name;
 	struct led_classdev ldev;
-       struct work_struct work;
+	struct work_struct work;
 	enum pca9532_type type;
 	enum pca9532_state state;
 };
diff --git a/include/linux/leds-regulator.h b/include/linux/leds-regulator.h
new file mode 100644
index 0000000..5a8eb38
--- /dev/null
+++ b/include/linux/leds-regulator.h
@@ -0,0 +1,46 @@
+/*
+ * leds-regulator.h - platform data structure for regulator driven LEDs.
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * 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_LEDS_REGULATOR_H
+#define __LINUX_LEDS_REGULATOR_H
+
+/*
+ * Use "vled" as supply id when declaring the regulator consumer:
+ *
+ * static struct regulator_consumer_supply pcap_regulator_VVIB_consumers [] = {
+ * 	{ .dev_name = "leds-regulator.0", supply = "vled" },
+ * };
+ *
+ * If you have several regulator driven LEDs, you can append a numerical id to
+ * .dev_name as done above, and use the same id when declaring the platform
+ * device:
+ *
+ * static struct led_regulator_platform_data a780_vibrator_data = {
+ * 	.name   = "a780::vibrator",
+ * };
+ *
+ * static struct platform_device a780_vibrator = {
+ * 	.name = "leds-regulator",
+ * 	.id   = 0,
+ * 	.dev  = {
+ * 		.platform_data = &a780_vibrator_data,
+ * 	},
+ * };
+ */
+
+#include <linux/leds.h>
+
+struct led_regulator_platform_data {
+	char *name;                     /* LED name as expected by LED class */
+	enum led_brightness brightness; /* initial brightness value */
+};
+
+#endif /* __LINUX_LEDS_REGULATOR_H */
diff --git a/include/linux/lmb.h b/include/linux/lmb.h
index 2442e3f..ef82b8f 100644
--- a/include/linux/lmb.h
+++ b/include/linux/lmb.h
@@ -54,6 +54,7 @@
 extern u64 lmb_end_of_DRAM(void);
 extern void __init lmb_enforce_memory_limit(u64 memory_limit);
 extern int __init lmb_is_reserved(u64 addr);
+extern int lmb_is_region_reserved(u64 base, u64 size);
 extern int lmb_find(struct lmb_property *res);
 
 extern void lmb_dump_all(void);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index bf9213b..1f9b119 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -54,6 +54,11 @@
 extern void mem_cgroup_del_lru(struct page *page);
 extern void mem_cgroup_move_lists(struct page *page,
 				  enum lru_list from, enum lru_list to);
+
+/* For coalescing uncharge for reducing memcg' overhead*/
+extern void mem_cgroup_uncharge_start(void);
+extern void mem_cgroup_uncharge_end(void);
+
 extern void mem_cgroup_uncharge_page(struct page *page);
 extern void mem_cgroup_uncharge_cache_page(struct page *page);
 extern int mem_cgroup_shmem_charge_fallback(struct page *page,
@@ -68,6 +73,7 @@
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
+extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
 
 static inline
@@ -80,6 +86,8 @@
 	return cgroup == mem;
 }
 
+extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem);
+
 extern int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr);
 extern void mem_cgroup_end_migration(struct mem_cgroup *mem,
@@ -117,7 +125,7 @@
 }
 
 extern bool mem_cgroup_oom_called(struct task_struct *task);
-void mem_cgroup_update_mapped_file_stat(struct page *page, int val);
+void mem_cgroup_update_file_mapped(struct page *page, int val);
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 						gfp_t gfp_mask, int nid,
 						int zid);
@@ -151,6 +159,14 @@
 {
 }
 
+static inline void mem_cgroup_uncharge_start(void)
+{
+}
+
+static inline void mem_cgroup_uncharge_end(void)
+{
+}
+
 static inline void mem_cgroup_uncharge_page(struct page *page)
 {
 }
@@ -189,6 +205,11 @@
 {
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
+{
+	return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
 	return 1;
@@ -200,6 +221,11 @@
 	return 1;
 }
 
+static inline struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return NULL;
+}
+
 static inline int
 mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr)
 {
@@ -274,7 +300,7 @@
 {
 }
 
-static inline void mem_cgroup_update_mapped_file_stat(struct page *page,
+static inline void mem_cgroup_update_file_mapped(struct page *page,
 							int val)
 {
 }
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index 415c228..fd322ac 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -41,6 +41,23 @@
 	int timeout;        /** Charge cycle timeout, in minutes */
 };
 
+/**
+ * Configuration for the WM831x DC-DC BuckWise convertors.  This
+ * should be passed as driver_data in the regulator_init_data.
+ *
+ * Currently all the configuration is for the fast DVS switching
+ * support of the devices.  This allows MFPs on the device to be
+ * configured as an input to switch between two output voltages,
+ * allowing voltage transitions without the expense of an access over
+ * I2C or SPI buses.
+ */
+struct wm831x_buckv_pdata {
+	int dvs_gpio;        /** CPU GPIO to use for DVS switching */
+	int dvs_control_src; /** Hardware DVS source to use (1 or 2) */
+	int dvs_init_state;  /** DVS state to expect on startup */
+	int dvs_state_gpio;  /** CPU GPIO to use for monitoring status */
+};
+
 /* Sources for status LED configuration.  Values are register values
  * plus 1 to allow for a zero default for preserve.
  */
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index ce7cc6c..e92d1bf 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -61,6 +61,7 @@
 	MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR	= 1 <<  8,
 	MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR	= 1 <<  9,
 	MLX4_DEV_CAP_FLAG_DPDP		= 1 << 12,
+	MLX4_DEV_CAP_FLAG_BLH		= 1 << 15,
 	MLX4_DEV_CAP_FLAG_MEM_WINDOW	= 1 << 16,
 	MLX4_DEV_CAP_FLAG_APM		= 1 << 17,
 	MLX4_DEV_CAP_FLAG_ATOMIC	= 1 << 18,
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 9d65ae4..849b4a6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1331,11 +1331,17 @@
 				 size_t size);
 extern void refund_locked_memory(struct mm_struct *mm, size_t size);
 
+enum mf_flags {
+	MF_COUNT_INCREASED = 1 << 0,
+};
 extern void memory_failure(unsigned long pfn, int trapno);
-extern int __memory_failure(unsigned long pfn, int trapno, int ref);
+extern int __memory_failure(unsigned long pfn, int trapno, int flags);
+extern int unpoison_memory(unsigned long pfn);
 extern int sysctl_memory_failure_early_kill;
 extern int sysctl_memory_failure_recovery;
+extern void shake_page(struct page *p, int access);
 extern atomic_long_t mce_bad_pages;
+extern int soft_offline_page(struct page *page, int flags);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
index 8a55098..ee24ef8 100644
--- a/include/linux/mmdebug.h
+++ b/include/linux/mmdebug.h
@@ -1,8 +1,6 @@
 #ifndef LINUX_MM_DEBUG_H
 #define LINUX_MM_DEBUG_H 1
 
-#include <linux/autoconf.h>
-
 #ifdef CONFIG_DEBUG_VM
 #define VM_BUG_ON(cond) BUG_ON(cond)
 #else
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 6f75617..30fe668 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -15,7 +15,7 @@
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
 #include <linux/pageblock-flags.h>
-#include <linux/bounds.h>
+#include <generated/bounds.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
 
diff --git a/include/linux/module.h b/include/linux/module.h
index 482efc8..6cb1a3c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -25,8 +25,10 @@
 /* Not Yet Implemented */
 #define MODULE_SUPPORTED_DEVICE(name)
 
-/* some toolchains uses a `_' prefix for all user symbols */
-#ifndef MODULE_SYMBOL_PREFIX
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_SYMBOL_PREFIX
+#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#else
 #define MODULE_SYMBOL_PREFIX ""
 #endif
 
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index fff8c53..9c3757c 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -19,22 +19,21 @@
 
 /**
  * struct nand_bbt_descr - bad block table descriptor
- * @options:		options for this descriptor
- * @pages:		the page(s) where we find the bbt, used with
- * 			option BBT_ABSPAGE when bbt is searched,
- * 			then we store the found bbts pages here.
- *			Its an array and supports up to 8 chips now
- * @offs:		offset of the pattern in the oob area of the page
- * @veroffs:		offset of the bbt version counter in the oob area of the page
- * @version:		version read from the bbt page during scan
- * @len:		length of the pattern, if 0 no pattern check is performed
- * @maxblocks:		maximum number of blocks to search for a bbt. This
- *			number of blocks is reserved at the end of the device
- *			where the tables are written.
- * @reserved_block_code: if non-0, this pattern denotes a reserved
- *			(rather than bad) block in the stored bbt
- * @pattern:		pattern to identify bad block table or factory marked
- *			good / bad blocks, can be NULL, if len = 0
+ * @options:	options for this descriptor
+ * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
+ *		when bbt is searched, then we store the found bbts pages here.
+ *		Its an array and supports up to 8 chips now
+ * @offs:	offset of the pattern in the oob area of the page
+ * @veroffs:	offset of the bbt version counter in the oob are of the page
+ * @version:	version read from the bbt page during scan
+ * @len:	length of the pattern, if 0 no pattern check is performed
+ * @maxblocks:	maximum number of blocks to search for a bbt. This number of
+ *		blocks is reserved at the end of the device where the tables are
+ *		written.
+ * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
+ *              bad) block in the stored bbt
+ * @pattern:	pattern to identify bad block table or factory marked good /
+ *		bad blocks, can be NULL, if len = 0
  *
  * Descriptor for the bad block table marker and the descriptor for the
  * pattern which identifies good and bad blocks. The assumption is made
@@ -90,7 +89,9 @@
 /*
  * Constants for oob configuration
  */
-#define ONENAND_BADBLOCK_POS	0
+#define NAND_SMALL_BADBLOCK_POS		5
+#define NAND_LARGE_BADBLOCK_POS		0
+#define ONENAND_BADBLOCK_POS		0
 
 /*
  * Bad block scanning errors
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 88d3d8f..df89f42 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -518,10 +518,11 @@
 #define CFI_MFR_ANY 0xffff
 #define CFI_ID_ANY  0xffff
 
-#define CFI_MFR_AMD 0x0001
-#define CFI_MFR_ATMEL 0x001F
-#define CFI_MFR_SAMSUNG 0x00EC
-#define CFI_MFR_ST  0x0020 	/* STMicroelectronics */
+#define CFI_MFR_AMD	0x0001
+#define CFI_MFR_INTEL	0x0089
+#define CFI_MFR_ATMEL	0x001F
+#define CFI_MFR_SAMSUNG	0x00EC
+#define CFI_MFR_ST	0x0020 /* STMicroelectronics */
 
 void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);
 
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
index d4f38c5..d0bf422 100644
--- a/include/linux/mtd/flashchip.h
+++ b/include/linux/mtd/flashchip.h
@@ -38,6 +38,15 @@
 	FL_XIP_WHILE_ERASING,
 	FL_XIP_WHILE_WRITING,
 	FL_SHUTDOWN,
+	/* These 2 come from nand_state_t, which has been unified here */
+	FL_READING,
+	FL_CACHEDPRG,
+	/* These 4 come from onenand_state_t, which has been unified here */
+	FL_RESETING,
+	FL_OTPING,
+	FL_PREPARING_ERASE,
+	FL_VERIFYING_ERASE,
+
 	FL_UNKNOWN
 } flstate_t;
 
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 7a232a9..ccab9df 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -21,6 +21,8 @@
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/mtd/bbm.h>
 
 struct mtd_info;
 /* Scan and identify a NAND device */
@@ -168,7 +170,6 @@
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
 
-
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
 	(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
@@ -194,6 +195,9 @@
 /* This option is defined if the board driver allocates its own buffers
    (e.g. because it needs them DMA-coherent */
 #define NAND_OWN_BUFFERS	0x00040000
+/* Chip may not exist, so silence any errors in scan */
+#define NAND_SCAN_SILENT_NODEV	0x00080000
+
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
 #define NAND_CONTROLLER_ALLOC	0x80000000
@@ -202,20 +206,6 @@
 #define NAND_CI_CHIPNR_MSK	0x03
 #define NAND_CI_CELLTYPE_MSK	0x0C
 
-/*
- * nand_state_t - chip states
- * Enumeration for NAND flash chip state
- */
-typedef enum {
-	FL_READY,
-	FL_READING,
-	FL_WRITING,
-	FL_ERASING,
-	FL_SYNCING,
-	FL_CACHEDPRG,
-	FL_PM_SUSPENDED,
-} nand_state_t;
-
 /* Keep gcc happy */
 struct nand_chip;
 
@@ -402,7 +392,7 @@
 	uint8_t		cellinfo;
 	int		badblockpos;
 
-	nand_state_t	state;
+	flstate_t	state;
 
 	uint8_t		*oob_poi;
 	struct nand_hw_control  *controller;
@@ -470,75 +460,6 @@
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
-/**
- * struct nand_bbt_descr - bad block table descriptor
- * @options:	options for this descriptor
- * @pages:	the page(s) where we find the bbt, used with option BBT_ABSPAGE
- *		when bbt is searched, then we store the found bbts pages here.
- *		Its an array and supports up to 8 chips now
- * @offs:	offset of the pattern in the oob area of the page
- * @veroffs:	offset of the bbt version counter in the oob are of the page
- * @version:	version read from the bbt page during scan
- * @len:	length of the pattern, if 0 no pattern check is performed
- * @maxblocks:	maximum number of blocks to search for a bbt. This number of
- *		blocks is reserved at the end of the device where the tables are
- *		written.
- * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
- *              bad) block in the stored bbt
- * @pattern:	pattern to identify bad block table or factory marked good /
- *		bad blocks, can be NULL, if len = 0
- *
- * Descriptor for the bad block table marker and the descriptor for the
- * pattern which identifies good and bad blocks. The assumption is made
- * that the pattern and the version count are always located in the oob area
- * of the first block.
- */
-struct nand_bbt_descr {
-	int	options;
-	int	pages[NAND_MAX_CHIPS];
-	int	offs;
-	int	veroffs;
-	uint8_t	version[NAND_MAX_CHIPS];
-	int	len;
-	int	maxblocks;
-	int	reserved_block_code;
-	uint8_t	*pattern;
-};
-
-/* Options for the bad block table descriptors */
-
-/* The number of bits used per block in the bbt on the device */
-#define NAND_BBT_NRBITS_MSK	0x0000000F
-#define NAND_BBT_1BIT		0x00000001
-#define NAND_BBT_2BIT		0x00000002
-#define NAND_BBT_4BIT		0x00000004
-#define NAND_BBT_8BIT		0x00000008
-/* The bad block table is in the last good block of the device */
-#define	NAND_BBT_LASTBLOCK	0x00000010
-/* The bbt is at the given page, else we must scan for the bbt */
-#define NAND_BBT_ABSPAGE	0x00000020
-/* The bbt is at the given page, else we must scan for the bbt */
-#define NAND_BBT_SEARCH		0x00000040
-/* bbt is stored per chip on multichip devices */
-#define NAND_BBT_PERCHIP	0x00000080
-/* bbt has a version counter at offset veroffs */
-#define NAND_BBT_VERSION	0x00000100
-/* Create a bbt if none axists */
-#define NAND_BBT_CREATE		0x00000200
-/* Search good / bad pattern through all pages of a block */
-#define NAND_BBT_SCANALLPAGES	0x00000400
-/* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY	0x00000800
-/* Write bbt if neccecary */
-#define NAND_BBT_WRITE		0x00001000
-/* Read and write back block contents when writing bbt */
-#define NAND_BBT_SAVECONTENT	0x00002000
-/* Search good / bad pattern on the first and the second page */
-#define NAND_BBT_SCAN2NDPAGE	0x00004000
-
-/* The maximum number of blocks to scan for a bbt */
-#define NAND_BBT_SCAN_MAXBLOCKS	4
-
 extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
 extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_default_bbt(struct mtd_info *mtd);
@@ -548,12 +469,6 @@
 extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
 			size_t * retlen, uint8_t * buf);
 
-/*
-* Constants for oob configuration
-*/
-#define NAND_SMALL_BADBLOCK_POS		5
-#define NAND_LARGE_BADBLOCK_POS		0
-
 /**
  * struct platform_nand_chip - chip level device structure
  * @nr_chips:		max. number of chips to scan for
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
index 052ea8c..41bc013 100644
--- a/include/linux/mtd/nand_ecc.h
+++ b/include/linux/mtd/nand_ecc.h
@@ -16,7 +16,13 @@
 struct mtd_info;
 
 /*
- * Calculate 3 byte ECC code for 256 byte block
+ * Calculate 3 byte ECC code for eccsize byte block
+ */
+void __nand_calculate_ecc(const u_char *dat, unsigned int eccsize,
+				u_char *ecc_code);
+
+/*
+ * Calculate 3 byte ECC code for 256/512 byte block
  */
 int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
 
@@ -27,7 +33,7 @@
 			unsigned int eccsize);
 
 /*
- * Detect and correct a 1 bit error for 256 byte block
+ * Detect and correct a 1 bit error for 256/512 byte block
  */
 int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
 
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 4e49f33..5509eb0 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -1,7 +1,7 @@
 /*
  *  linux/include/linux/mtd/onenand.h
  *
- *  Copyright (C) 2005-2007 Samsung Electronics
+ *  Copyright © 2005-2009 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,6 +14,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/completion.h>
+#include <linux/mtd/flashchip.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/mtd/bbm.h>
 
@@ -25,22 +26,6 @@
 /* Free resources held by the OneNAND device */
 extern void onenand_release(struct mtd_info *mtd);
 
-/*
- * onenand_state_t - chip states
- * Enumeration for OneNAND flash chip state
- */
-typedef enum {
-	FL_READY,
-	FL_READING,
-	FL_WRITING,
-	FL_ERASING,
-	FL_SYNCING,
-	FL_LOCKING,
-	FL_RESETING,
-	FL_OTPING,
-	FL_PM_SUSPENDED,
-} onenand_state_t;
-
 /**
  * struct onenand_bufferram - OneNAND BufferRAM Data
  * @blockpage:		block & page address in BufferRAM
@@ -137,7 +122,7 @@
 
 	spinlock_t		chip_lock;
 	wait_queue_head_t	wq;
-	onenand_state_t		state;
+	flstate_t		state;
 	unsigned char		*page_buf;
 	unsigned char		*oob_buf;
 
@@ -152,6 +137,8 @@
 /*
  * Helper macros
  */
+#define ONENAND_PAGES_PER_BLOCK        (1<<6)
+
 #define ONENAND_CURRENT_BUFFERRAM(this)		(this->bufferram_index)
 #define ONENAND_NEXT_BUFFERRAM(this)		(this->bufferram_index ^ 1)
 #define ONENAND_SET_NEXT_BUFFERRAM(this)	(this->bufferram_index ^= 1)
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index acadbf5..cd6f3b4 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -131,6 +131,8 @@
 #define ONENAND_CMD_LOCK_TIGHT		(0x2C)
 #define ONENAND_CMD_UNLOCK_ALL		(0x27)
 #define ONENAND_CMD_ERASE		(0x94)
+#define ONENAND_CMD_MULTIBLOCK_ERASE	(0x95)
+#define ONENAND_CMD_ERASE_VERIFY	(0x71)
 #define ONENAND_CMD_RESET		(0xF0)
 #define ONENAND_CMD_OTP_ACCESS		(0x65)
 #define ONENAND_CMD_READID		(0x90)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 51071b3..89b2881 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -2,6 +2,7 @@
 #define _LINUX_NFS_XDR_H
 
 #include <linux/nfsacl.h>
+#include <linux/nfs3.h>
 
 /*
  * To change the maximum rsize and wsize supported by the NFS client, adjust
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
index 43011b6..f321b57 100644
--- a/include/linux/nfsacl.h
+++ b/include/linux/nfsacl.h
@@ -29,6 +29,7 @@
 #ifdef __KERNEL__
 
 #include <linux/posix_acl.h>
+#include <linux/sunrpc/xdr.h>
 
 /* Maximum number of ACL entries over NFS */
 #define NFS_ACL_MAX_ENTRIES	1024
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index a6d9ef2..8ae78a6 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -12,7 +12,7 @@
 
 # include <linux/types.h>
 #ifdef __KERNEL__
-# include <linux/in.h>
+# include <linux/nfsd/nfsfh.h>
 #endif
 
 /*
@@ -39,11 +39,23 @@
 #define NFSEXP_FSID		0x2000
 #define	NFSEXP_CROSSMOUNT	0x4000
 #define	NFSEXP_NOACL		0x8000	/* reserved for possible ACL related use */
-#define NFSEXP_ALLFLAGS		0xFE3F
+/*
+ * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
+ * clients, and only to the single directory that is the root of the
+ * export; further lookup and readdir operations are treated as if every
+ * subdirectory was a mountpoint, and ignored if they are not themselves
+ * exported.  This is used by nfsd and mountd to construct the NFSv4
+ * pseudofilesystem, which provides access only to paths leading to each
+ * exported filesystem.
+ */
+#define	NFSEXP_V4ROOT		0x10000
+/* All flags that we claim to support.  (Note we don't support NOACL.) */
+#define NFSEXP_ALLFLAGS		0x17E3F
 
 /* The flags that may vary depending on security flavor: */
 #define NFSEXP_SECINFO_FLAGS	(NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
-					| NFSEXP_ALLSQUASH)
+					| NFSEXP_ALLSQUASH \
+					| NFSEXP_INSECURE_PORT)
 
 #ifdef __KERNEL__
 
@@ -108,7 +120,6 @@
 	struct path		ek_path;
 };
 
-#define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
 #define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index 8f641c9..65e333a 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -16,11 +16,9 @@
 
 # include <linux/types.h>
 #ifdef __KERNEL__
-# include <linux/string.h>
-# include <linux/fs.h>
+# include <linux/sunrpc/svc.h>
 #endif
 #include <linux/nfsd/const.h>
-#include <linux/nfsd/debug.h>
 
 /*
  * This is the old "dentry style" Linux NFSv2 file handle.
@@ -164,208 +162,6 @@
 
 } svc_fh;
 
-enum nfsd_fsid {
-	FSID_DEV = 0,
-	FSID_NUM,
-	FSID_MAJOR_MINOR,
-	FSID_ENCODE_DEV,
-	FSID_UUID4_INUM,
-	FSID_UUID8,
-	FSID_UUID16,
-	FSID_UUID16_INUM,
-};
-
-enum fsid_source {
-	FSIDSOURCE_DEV,
-	FSIDSOURCE_FSID,
-	FSIDSOURCE_UUID,
-};
-extern enum fsid_source fsid_source(struct svc_fh *fhp);
-
-
-/* This might look a little large to "inline" but in all calls except
- * one, 'vers' is constant so moste of the function disappears.
- */
-static inline void mk_fsid(int vers, u32 *fsidv, dev_t dev, ino_t ino,
-			   u32 fsid, unsigned char *uuid)
-{
-	u32 *up;
-	switch(vers) {
-	case FSID_DEV:
-		fsidv[0] = htonl((MAJOR(dev)<<16) |
-				 MINOR(dev));
-		fsidv[1] = ino_t_to_u32(ino);
-		break;
-	case FSID_NUM:
-		fsidv[0] = fsid;
-		break;
-	case FSID_MAJOR_MINOR:
-		fsidv[0] = htonl(MAJOR(dev));
-		fsidv[1] = htonl(MINOR(dev));
-		fsidv[2] = ino_t_to_u32(ino);
-		break;
-
-	case FSID_ENCODE_DEV:
-		fsidv[0] = new_encode_dev(dev);
-		fsidv[1] = ino_t_to_u32(ino);
-		break;
-
-	case FSID_UUID4_INUM:
-		/* 4 byte fsid and inode number */
-		up = (u32*)uuid;
-		fsidv[0] = ino_t_to_u32(ino);
-		fsidv[1] = up[0] ^ up[1] ^ up[2] ^ up[3];
-		break;
-
-	case FSID_UUID8:
-		/* 8 byte fsid  */
-		up = (u32*)uuid;
-		fsidv[0] = up[0] ^ up[2];
-		fsidv[1] = up[1] ^ up[3];
-		break;
-
-	case FSID_UUID16:
-		/* 16 byte fsid - NFSv3+ only */
-		memcpy(fsidv, uuid, 16);
-		break;
-
-	case FSID_UUID16_INUM:
-		/* 8 byte inode and 16 byte fsid */
-		*(u64*)fsidv = (u64)ino;
-		memcpy(fsidv+2, uuid, 16);
-		break;
-	default: BUG();
-	}
-}
-
-static inline int key_len(int type)
-{
-	switch(type) {
-	case FSID_DEV:		return 8;
-	case FSID_NUM: 		return 4;
-	case FSID_MAJOR_MINOR:	return 12;
-	case FSID_ENCODE_DEV:	return 8;
-	case FSID_UUID4_INUM:	return 8;
-	case FSID_UUID8:	return 8;
-	case FSID_UUID16:	return 16;
-	case FSID_UUID16_INUM:	return 24;
-	default: return 0;
-	}
-}
-
-/*
- * Shorthand for dprintk()'s
- */
-extern char * SVCFH_fmt(struct svc_fh *fhp);
-
-/*
- * Function prototypes
- */
-__be32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
-__be32	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *, struct svc_fh *);
-__be32	fh_update(struct svc_fh *);
-void	fh_put(struct svc_fh *);
-
-static __inline__ struct svc_fh *
-fh_copy(struct svc_fh *dst, struct svc_fh *src)
-{
-	WARN_ON(src->fh_dentry || src->fh_locked);
-			
-	*dst = *src;
-	return dst;
-}
-
-static inline void
-fh_copy_shallow(struct knfsd_fh *dst, struct knfsd_fh *src)
-{
-	dst->fh_size = src->fh_size;
-	memcpy(&dst->fh_base, &src->fh_base, src->fh_size);
-}
-
-static __inline__ struct svc_fh *
-fh_init(struct svc_fh *fhp, int maxsize)
-{
-	memset(fhp, 0, sizeof(*fhp));
-	fhp->fh_maxsize = maxsize;
-	return fhp;
-}
-
-#ifdef CONFIG_NFSD_V3
-/*
- * Fill in the pre_op attr for the wcc data
- */
-static inline void
-fill_pre_wcc(struct svc_fh *fhp)
-{
-	struct inode    *inode;
-
-	inode = fhp->fh_dentry->d_inode;
-	if (!fhp->fh_pre_saved) {
-		fhp->fh_pre_mtime = inode->i_mtime;
-		fhp->fh_pre_ctime = inode->i_ctime;
-		fhp->fh_pre_size  = inode->i_size;
-		fhp->fh_pre_change = inode->i_version;
-		fhp->fh_pre_saved = 1;
-	}
-}
-
-extern void fill_post_wcc(struct svc_fh *);
-#else
-#define	fill_pre_wcc(ignored)
-#define fill_post_wcc(notused)
-#endif /* CONFIG_NFSD_V3 */
-
-
-/*
- * Lock a file handle/inode
- * NOTE: both fh_lock and fh_unlock are done "by hand" in
- * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
- * so, any changes here should be reflected there.
- */
-
-static inline void
-fh_lock_nested(struct svc_fh *fhp, unsigned int subclass)
-{
-	struct dentry	*dentry = fhp->fh_dentry;
-	struct inode	*inode;
-
-	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
-			SVCFH_fmt(fhp), fhp->fh_locked);
-
-	BUG_ON(!dentry);
-
-	if (fhp->fh_locked) {
-		printk(KERN_WARNING "fh_lock: %s/%s already locked!\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-		return;
-	}
-
-	inode = dentry->d_inode;
-	mutex_lock_nested(&inode->i_mutex, subclass);
-	fill_pre_wcc(fhp);
-	fhp->fh_locked = 1;
-}
-
-static inline void
-fh_lock(struct svc_fh *fhp)
-{
-	fh_lock_nested(fhp, I_MUTEX_NORMAL);
-}
-
-/*
- * Unlock a file handle/inode
- */
-static inline void
-fh_unlock(struct svc_fh *fhp)
-{
-	BUG_ON(!fhp->fh_dentry);
-
-	if (fhp->fh_locked) {
-		fill_post_wcc(fhp);
-		mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
-		fhp->fh_locked = 0;
-	}
-}
 #endif /* __KERNEL__ */
 
 
diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
index 7a3b565..812bc1e 100644
--- a/include/linux/nfsd/syscall.h
+++ b/include/linux/nfsd/syscall.h
@@ -9,14 +9,8 @@
 #ifndef NFSD_SYSCALL_H
 #define NFSD_SYSCALL_H
 
-# include <linux/types.h>
-#ifdef __KERNEL__
-# include <linux/in.h>
-#endif 
-#include <linux/posix_types.h>
-#include <linux/nfsd/const.h>
+#include <linux/types.h>
 #include <linux/nfsd/export.h>
-#include <linux/nfsd/nfsfh.h>
 
 /*
  * Version of the syscall interface
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 6aac5fe..5376623 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -10,6 +10,7 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <linux/nodemask.h>
 
 struct zonelist;
 struct notifier_block;
@@ -26,7 +27,8 @@
 extern int try_set_zone_oom(struct zonelist *zonelist, gfp_t gfp_flags);
 extern void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_flags);
 
-extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order);
+extern void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
+		int order, nodemask_t *mask);
 extern int register_oom_notifier(struct notifier_block *nb);
 extern int unregister_oom_notifier(struct notifier_block *nb);
 
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 49e907b..5b59f35 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -8,7 +8,7 @@
 #include <linux/types.h>
 #ifndef __GENERATING_BOUNDS_H
 #include <linux/mm_types.h>
-#include <linux/bounds.h>
+#include <generated/bounds.h>
 #endif /* !__GENERATING_BOUNDS_H */
 
 /*
@@ -275,13 +275,15 @@
 
 #ifdef CONFIG_MEMORY_FAILURE
 PAGEFLAG(HWPoison, hwpoison)
-TESTSETFLAG(HWPoison, hwpoison)
+TESTSCFLAG(HWPoison, hwpoison)
 #define __PG_HWPOISON (1UL << PG_hwpoison)
 #else
 PAGEFLAG_FALSE(HWPoison)
 #define __PG_HWPOISON 0
 #endif
 
+u64 stable_page_flags(struct page *page);
+
 static inline int PageUptodate(struct page *page)
 {
 	int ret = test_bit(PG_uptodate, &(page)->flags);
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h
index 4b938d4..b0e4eb1 100644
--- a/include/linux/page_cgroup.h
+++ b/include/linux/page_cgroup.h
@@ -57,6 +57,8 @@
 static inline int TestClearPageCgroup##uname(struct page_cgroup *pc)	\
 	{ return test_and_clear_bit(PCG_##lname, &pc->flags);  }
 
+TESTPCGFLAG(Locked, LOCK)
+
 /* Cache flag is set only once (at allocation) */
 TESTPCGFLAG(Cache, CACHE)
 CLEARPCGFLAG(Cache, CACHE)
@@ -86,11 +88,6 @@
 	bit_spin_lock(PCG_LOCK, &pc->flags);
 }
 
-static inline int trylock_page_cgroup(struct page_cgroup *pc)
-{
-	return bit_spin_trylock(PCG_LOCK, &pc->flags);
-}
-
 static inline void unlock_page_cgroup(struct page_cgroup *pc)
 {
 	bit_spin_unlock(PCG_LOCK, &pc->flags);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index da7bdc2..c66b34f 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -211,17 +211,11 @@
 		__u32		wakeup_watermark; /* bytes before wakeup   */
 	};
 
-	struct { /* Hardware breakpoint info */
-		__u64		bp_addr;
-		__u32		bp_type;
-		__u32		bp_len;
-		__u64		__bp_reserved_1;
-		__u64		__bp_reserved_2;
-	};
-
 	__u32			__reserved_2;
 
-	__u64			__reserved_3;
+	__u64			bp_addr;
+	__u32			bp_type;
+	__u32			bp_len;
 };
 
 /*
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index fddfafa..7c4193e 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -334,6 +334,19 @@
 #define pnp_device_is_pnpbios(dev) 0
 #endif
 
+#ifdef CONFIG_PNPACPI
+extern struct pnp_protocol pnpacpi_protocol;
+
+static inline struct acpi_device *pnp_acpi_device(struct pnp_dev *dev)
+{
+	if (dev->protocol == &pnpacpi_protocol)
+		return dev->data;
+	return NULL;
+}
+#else
+#define pnp_acpi_device(dev) 0
+#endif
+
 /* status */
 #define PNP_READY		0x0000
 #define PNP_ATTACHED		0x0001
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 7456d7d..56f2d63 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -105,12 +105,7 @@
 {
 	return child->real_parent != child->parent;
 }
-static inline void ptrace_link(struct task_struct *child,
-			       struct task_struct *new_parent)
-{
-	if (unlikely(child->ptrace))
-		__ptrace_link(child, new_parent);
-}
+
 static inline void ptrace_unlink(struct task_struct *child)
 {
 	if (unlikely(child->ptrace))
@@ -169,9 +164,9 @@
 	INIT_LIST_HEAD(&child->ptraced);
 	child->parent = child->real_parent;
 	child->ptrace = 0;
-	if (unlikely(ptrace)) {
+	if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) {
 		child->ptrace = current->ptrace;
-		ptrace_link(child, current->parent);
+		__ptrace_link(child, current->parent);
 	}
 }
 
@@ -278,6 +273,18 @@
 }
 #endif	/* arch_has_block_step */
 
+#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
+extern void user_single_step_siginfo(struct task_struct *tsk,
+				struct pt_regs *regs, siginfo_t *info);
+#else
+static inline void user_single_step_siginfo(struct task_struct *tsk,
+				struct pt_regs *regs, siginfo_t *info)
+{
+	memset(info, 0, sizeof(*info));
+	info->si_signo = SIGTRAP;
+}
+#endif
+
 #ifndef arch_ptrace_stop_needed
 /**
  * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index 7a9754c..01b3d75 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -10,7 +10,7 @@
 	unsigned int dft_brightness;
 	unsigned int pwm_period_ns;
 	int (*init)(struct device *dev);
-	int (*notify)(int brightness);
+	int (*notify)(struct device *dev, int brightness);
 	void (*exit)(struct device *dev);
 };
 
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 490c5b3..030d922 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -35,6 +35,8 @@
 #ifndef __LINUX_REGULATOR_CONSUMER_H_
 #define __LINUX_REGULATOR_CONSUMER_H_
 
+#include <linux/device.h>
+
 /*
  * Regulator operating modes.
  *
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 87f5f17..234a847 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -43,16 +43,20 @@
 /**
  * struct regulator_state - regulator state during low power system states
  *
- * This describes a regulators state during a system wide low power state.
+ * This describes a regulators state during a system wide low power
+ * state.  One of enabled or disabled must be set for the
+ * configuration to be applied.
  *
  * @uV: Operating voltage during suspend.
  * @mode: Operating mode during suspend.
  * @enabled: Enabled during suspend.
+ * @disabled: Disabled during suspend.
  */
 struct regulator_state {
 	int uV;	/* suspend voltage */
 	unsigned int mode; /* suspend regulator operating mode */
 	int enabled; /* is regulator enabled in this suspend state */
+	int disabled; /* is the regulator disbled in this suspend state */
 };
 
 /**
diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h
new file mode 100644
index 0000000..9936763
--- /dev/null
+++ b/include/linux/regulator/max8660.h
@@ -0,0 +1,57 @@
+/*
+ * max8660.h  --  Voltage regulation for the Maxim 8660/8661
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; 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
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8660_H
+#define __LINUX_REGULATOR_MAX8660_H
+
+#include <linux/regulator/machine.h>
+
+enum {
+	MAX8660_V3,
+	MAX8660_V4,
+	MAX8660_V5,
+	MAX8660_V6,
+	MAX8660_V7,
+	MAX8660_V_END,
+};
+
+/**
+ * max8660_subdev_data - regulator subdev data
+ * @id: regulator id
+ * @name: regulator name
+ * @platform_data: regulator init data
+ */
+struct max8660_subdev_data {
+	int				id;
+	char				*name;
+	struct regulator_init_data	*platform_data;
+};
+
+/**
+ * max8660_platform_data - platform data for max8660
+ * @num_subdevs: number of regulators used
+ * @subdevs: pointer to regulators used
+ * @en34_is_high: if EN34 is driven high, regulators cannot be en-/disabled.
+ */
+struct max8660_platform_data {
+	int num_subdevs;
+	struct max8660_subdev_data *subdevs;
+	unsigned en34_is_high:1;
+};
+#endif
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index a05b4a2..c96c185 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -2051,25 +2051,12 @@
 int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
 			struct treepath *path, struct reiserfs_dir_entry *de);
 struct dentry *reiserfs_get_parent(struct dentry *);
-/* procfs.c */
 
-#if defined( CONFIG_PROC_FS ) && defined( CONFIG_REISERFS_PROC_INFO )
-#define REISERFS_PROC_INFO
-#else
-#undef REISERFS_PROC_INFO
-#endif
-
+#ifdef CONFIG_REISERFS_PROC_INFO
 int reiserfs_proc_info_init(struct super_block *sb);
 int reiserfs_proc_info_done(struct super_block *sb);
-struct proc_dir_entry *reiserfs_proc_register_global(char *name,
-						     read_proc_t * func);
-void reiserfs_proc_unregister_global(const char *name);
 int reiserfs_proc_info_global_init(void);
 int reiserfs_proc_info_global_done(void);
-int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset,
-				    int count, int *eof, void *data);
-
-#if defined( REISERFS_PROC_INFO )
 
 #define PROC_EXP( e )   e
 
@@ -2084,6 +2071,26 @@
     PROC_INFO_ADD( sb, free_at[ ( level ) ], B_FREE_SPACE( bh ) );	\
     PROC_INFO_ADD( sb, items_at[ ( level ) ], B_NR_ITEMS( bh ) )
 #else
+static inline int reiserfs_proc_info_init(struct super_block *sb)
+{
+	return 0;
+}
+
+static inline int reiserfs_proc_info_done(struct super_block *sb)
+{
+	return 0;
+}
+
+static inline int reiserfs_proc_info_global_init(void)
+{
+	return 0;
+}
+
+static inline int reiserfs_proc_info_global_done(void)
+{
+	return 0;
+}
+
 #define PROC_EXP( e )
 #define VOID_V ( ( void ) 0 )
 #define PROC_INFO_MAX( sb, field, value ) VOID_V
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 14fc906..05330fc 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -368,11 +368,9 @@
 #define RTAX_MAX (__RTAX_MAX - 1)
 
 #define RTAX_FEATURE_ECN	0x00000001
-#define RTAX_FEATURE_NO_SACK	0x00000002
-#define RTAX_FEATURE_NO_TSTAMP	0x00000004
+#define RTAX_FEATURE_SACK	0x00000002
+#define RTAX_FEATURE_TIMESTAMP	0x00000004
 #define RTAX_FEATURE_ALLFRAG	0x00000008
-#define RTAX_FEATURE_NO_WSCALE	0x00000010
-#define RTAX_FEATURE_NO_DSACK	0x00000020
 
 struct rta_session {
 	__u8	proto;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5c858f3..211ed32 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1446,10 +1446,8 @@
 	gfp_t lockdep_reclaim_gfp;
 #endif
 
-#ifdef CONFIG_FS_JOURNAL_INFO
 /* journalling filesystem info */
 	void *journal_info;
-#endif
 
 /* stacked block device info */
 	struct bio *bio_list, **bio_tail;
@@ -1544,6 +1542,14 @@
 	unsigned long trace_recursion;
 #endif /* CONFIG_TRACING */
 	unsigned long stack_start;
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */
+	struct memcg_batch_info {
+		int do_batch;	/* incremented when batch uncharge started */
+		struct mem_cgroup *memcg; /* target memcg of uncharge */
+		unsigned long bytes; 		/* uncharged usage */
+		unsigned long memsw_bytes; /* uncharged mem+swap usage */
+	} memcg_batch;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -2075,7 +2081,6 @@
 extern int do_notify_parent(struct task_struct *, int);
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
 extern void force_sig(int, struct task_struct *);
-extern void force_sig_specific(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
 extern void zap_other_threads(struct task_struct *p);
 extern struct sigqueue *sigqueue_alloc(void);
@@ -2094,11 +2099,6 @@
 #define SEND_SIG_PRIV	((struct siginfo *) 1)
 #define SEND_SIG_FORCED	((struct siginfo *) 2)
 
-static inline int is_si_special(const struct siginfo *info)
-{
-	return info <= SEND_SIG_FORCED;
-}
-
 /*
  * True if we are on the alternate signal stack.
  */
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 1b191c1..8a4adbef 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -86,6 +86,7 @@
 struct sem {
 	int	semval;		/* current value */
 	int	sempid;		/* pid of last operation */
+	struct list_head sem_pending; /* pending single-sop operations */
 };
 
 /* One sem_array data structure for each set of semaphores in the system. */
@@ -96,11 +97,13 @@
 	struct sem		*sem_base;	/* ptr to first semaphore in array */
 	struct list_head	sem_pending;	/* pending operations to be processed */
 	struct list_head	list_id;	/* undo requests on this array */
-	unsigned long		sem_nsems;	/* no. of semaphores in array */
+	int			sem_nsems;	/* no. of semaphores in array */
+	int			complex_count;	/* pending complex operations */
 };
 
 /* One queue for each sleeping process in the system. */
 struct sem_queue {
+	struct list_head	simple_list; /* queue of pending operations */
 	struct list_head	list;	 /* queue of pending operations */
 	struct task_struct	*sleeper; /* this process */
 	struct sem_undo		*undo;	 /* undo structure */
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index deee7af..e164291 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -41,20 +41,4 @@
 extern int init_tmpfs(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
 
-#ifdef CONFIG_TMPFS_POSIX_ACL
-int shmem_check_acl(struct inode *, int);
-int shmem_acl_init(struct inode *, struct inode *);
-
-extern struct xattr_handler shmem_xattr_acl_access_handler;
-extern struct xattr_handler shmem_xattr_acl_default_handler;
-
-extern struct generic_acl_operations shmem_acl_ops;
-
-#else
-static inline int shmem_acl_init(struct inode *inode, struct inode *dir)
-{
-	return 0;
-}
-#endif  /* CONFIG_TMPFS_POSIX_ACL */
-
 #endif
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
index d53642d..67ed2c5 100644
--- a/include/linux/sm501-regs.h
+++ b/include/linux/sm501-regs.h
@@ -31,6 +31,8 @@
 #define SM501_SYSCTRL_PCI_SUBSYS_LOCK	(1<<11)
 #define SM501_SYSCTRL_PCI_BURST_READ_EN	(1<<15)
 
+#define SM501_SYSCTRL_2D_ENGINE_STATUS	(1<<19)
+
 /* miscellaneous control */
 
 #define SM501_MISC_CONTROL		(0x000004)
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
new file mode 100644
index 0000000..51b3e77
--- /dev/null
+++ b/include/linux/spi/dw_spi.h
@@ -0,0 +1,212 @@
+#ifndef DW_SPI_HEADER_H
+#define DW_SPI_HEADER_H
+#include <linux/io.h>
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+/* Bit fields in ISR, IMR, RISR, 7 bits */
+#define SPI_INT_TXEI			(1 << 0)
+#define SPI_INT_TXOI			(1 << 1)
+#define SPI_INT_RXUI			(1 << 2)
+#define SPI_INT_RXOI			(1 << 3)
+#define SPI_INT_RXFI			(1 << 4)
+#define SPI_INT_MSTI			(1 << 5)
+
+/* TX RX interrupt level threshhold, max can be 256 */
+#define SPI_INT_THRESHOLD		32
+
+enum dw_ssi_type {
+	SSI_MOTO_SPI = 0,
+	SSI_TI_SSP,
+	SSI_NS_MICROWIRE,
+};
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+	u32	dr;		/* Currently oper as 32 bits,
+				though only low 16 bits matters */
+} __packed;
+
+struct dw_spi {
+	struct spi_master	*master;
+	struct spi_device	*cur_dev;
+	struct device		*parent_dev;
+	enum dw_ssi_type	type;
+
+	void __iomem		*regs;
+	unsigned long		paddr;
+	u32			iolen;
+	int			irq;
+	u32			max_freq;	/* max bus freq supported */
+
+	u16			bus_num;
+	u16			num_cs;		/* supported slave numbers */
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct	pump_messages;
+	spinlock_t		lock;
+	struct list_head	queue;
+	int			busy;
+	int			run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct	pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message	*cur_msg;
+	struct spi_transfer	*cur_transfer;
+	struct chip_data	*cur_chip;
+	struct chip_data	*prev_chip;
+	size_t			len;
+	void			*tx;
+	void			*tx_end;
+	void			*rx;
+	void			*rx_end;
+	int			dma_mapped;
+	dma_addr_t		rx_dma;
+	dma_addr_t		tx_dma;
+	size_t			rx_map_len;
+	size_t			tx_map_len;
+	u8			n_bytes;	/* current is a 1/2 bytes op */
+	u8			max_bits_per_word;	/* maxim is 16b */
+	u32			dma_width;
+	int			cs_change;
+	int			(*write)(struct dw_spi *dws);
+	int			(*read)(struct dw_spi *dws);
+	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
+	void			(*cs_control)(u32 command);
+
+	/* Dma info */
+	int			dma_inited;
+	struct dma_chan		*txchan;
+	struct dma_chan		*rxchan;
+	int			txdma_done;
+	int			rxdma_done;
+	u64			tx_param;
+	u64			rx_param;
+	struct device		*dma_dev;
+	dma_addr_t		dma_addr;
+
+	/* Bus interface info */
+	void			*priv;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+};
+
+#define dw_readl(dw, name) \
+	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+
+static inline void spi_enable_chip(struct dw_spi *dws, int enable)
+{
+	dw_writel(dws, ssienr, (enable ? 1 : 0));
+}
+
+static inline void spi_set_clk(struct dw_spi *dws, u16 div)
+{
+	dw_writel(dws, baudr, div);
+}
+
+static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+{
+	if (cs > dws->num_cs)
+		return;
+	dw_writel(dws, ser, 1 << cs);
+}
+
+/* Disable IRQ bits */
+static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) & ~mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/* Enable IRQ bits */
+static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) | mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the "controller_data" member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+	u8 poll_mode;	/* 0 for contoller polling mode */
+	u8 type;	/* SPI/SSP/Micrwire */
+	u8 enable_dma;
+	void (*cs_control)(u32 command);
+};
+
+extern int dw_spi_add_host(struct dw_spi *dws);
+extern void dw_spi_remove_host(struct dw_spi *dws);
+extern int dw_spi_suspend_host(struct dw_spi *dws);
+extern int dw_spi_resume_host(struct dw_spi *dws);
+#endif /* DW_SPI_HEADER_H */
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 10709cbe..c2786f2 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -28,9 +28,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-
 /*
  * Enable RPC debugging/profiling.
  */
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h
index 87b895d..b78f16b 100644
--- a/include/linux/sunrpc/rpc_rdma.h
+++ b/include/linux/sunrpc/rpc_rdma.h
@@ -40,6 +40,8 @@
 #ifndef _LINUX_SUNRPC_RPC_RDMA_H
 #define _LINUX_SUNRPC_RPC_RDMA_H
 
+#include <linux/types.h>
+
 struct rpcrdma_segment {
 	__be32 rs_handle;	/* Registered memory handle */
 	__be32 rs_length;	/* Length of the chunk in bytes */
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 1906782..7bc7fd5 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -173,7 +173,8 @@
 #define RPC_PRIORITY_LOW	(-1)
 #define RPC_PRIORITY_NORMAL	(0)
 #define RPC_PRIORITY_HIGH	(1)
-#define RPC_NR_PRIORITY		(1 + RPC_PRIORITY_HIGH - RPC_PRIORITY_LOW)
+#define RPC_PRIORITY_PRIVILEGED	(2)
+#define RPC_NR_PRIORITY		(1 + RPC_PRIORITY_PRIVILEGED - RPC_PRIORITY_LOW)
 
 struct rpc_timer {
 	struct timer_list timer;
@@ -229,6 +230,7 @@
 void		rpc_wake_up(struct rpc_wait_queue *);
 struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
 void		rpc_wake_up_status(struct rpc_wait_queue *, int);
+int		rpc_queue_empty(struct rpc_wait_queue *);
 void		rpc_delay(struct rpc_task *, unsigned long);
 void *		rpc_malloc(struct rpc_task *, size_t);
 void		rpc_free(void *);
@@ -254,6 +256,16 @@
 	return __rpc_wait_for_completion_task(task, NULL);
 }
 
+static inline void rpc_task_set_priority(struct rpc_task *task, unsigned char prio)
+{
+	task->tk_priority = prio - RPC_PRIORITY_LOW;
+}
+
+static inline int rpc_task_has_priority(struct rpc_task *task, unsigned char prio)
+{
+	return (task->tk_priority + RPC_PRIORITY_LOW == prio);
+}
+
 #ifdef RPC_DEBUG
 static inline const char * rpc_qname(struct rpc_wait_queue *q)
 {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 52e8cb0..5a3085b 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -29,7 +29,6 @@
 	unsigned long	packets;
 	unsigned long	sockets_queued;
 	unsigned long	threads_woken;
-	unsigned long	overloads_avoided;
 	unsigned long	threads_timedout;
 };
 
@@ -50,7 +49,6 @@
 	struct list_head	sp_sockets;	/* pending sockets */
 	unsigned int		sp_nrthreads;	/* # of threads in pool */
 	struct list_head	sp_all_threads;	/* all server threads */
-	int			sp_nwaking;	/* number of threads woken but not yet active */
 	struct svc_pool_stats	sp_stats;	/* statistics on pool operation */
 } ____cacheline_aligned_in_smp;
 
@@ -275,16 +273,11 @@
 	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
-						 * to report (real or virtual)
-						 */
 	int			rq_splice_ok;   /* turned off in gss privacy
 						 * to prevent encrypting page
 						 * cache pages */
 	wait_queue_head_t	rq_wait;	/* synchronization */
 	struct task_struct	*rq_task;	/* service thread */
-	int			rq_waking;	/* 1 if thread is being woken */
 };
 
 /*
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 939a6150..65793e9 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -102,12 +102,10 @@
 #ifdef CONFIG_EVENT_PROFILE
 
 #define TRACE_SYS_ENTER_PROFILE_INIT(sname)				       \
-	.profile_count = ATOMIC_INIT(-1),				       \
 	.profile_enable = prof_sysenter_enable,				       \
 	.profile_disable = prof_sysenter_disable,
 
 #define TRACE_SYS_EXIT_PROFILE_INIT(sname)				       \
-	.profile_count = ATOMIC_INIT(-1),				       \
 	.profile_enable = prof_sysexit_enable,				       \
 	.profile_disable = prof_sysexit_disable,
 #else
@@ -145,7 +143,7 @@
 		.name                   = "sys_enter"#sname,		\
 		.system                 = "syscalls",			\
 		.event                  = &enter_syscall_print_##sname,	\
-		.raw_init		= init_syscall_trace,		\
+		.raw_init		= trace_event_raw_init,		\
 		.show_format		= syscall_enter_format,		\
 		.define_fields		= syscall_enter_define_fields,	\
 		.regfunc		= reg_event_syscall_enter,	\
@@ -167,7 +165,7 @@
 		.name                   = "sys_exit"#sname,		\
 		.system                 = "syscalls",			\
 		.event                  = &exit_syscall_print_##sname,	\
-		.raw_init		= init_syscall_trace,		\
+		.raw_init		= trace_event_raw_init,		\
 		.show_format		= syscall_exit_format,		\
 		.define_fields		= syscall_exit_define_fields,	\
 		.regfunc		= reg_event_syscall_exit,	\
diff --git a/include/linux/timb_gpio.h b/include/linux/timb_gpio.h
new file mode 100644
index 0000000..ce456ea
--- /dev/null
+++ b/include/linux/timb_gpio.h
@@ -0,0 +1,37 @@
+/*
+ * timb_gpio.h timberdale FPGA GPIO driver, platform data definition
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 _LINUX_TIMB_GPIO_H
+#define _LINUX_TIMB_GPIO_H
+
+/**
+ * struct timbgpio_platform_data - Platform data of the Timberdale GPIO driver
+ * @gpio_base		The number of the first GPIO pin, set to -1 for
+ *			dynamic number allocation.
+ * @nr_pins		Number of pins that is supported by the hardware (1-32)
+ * @irq_base		If IRQ is supported by the hardware, this is the base
+ *			number of IRQ:s. One IRQ per pin will be used. Set to
+ *			-1 if IRQ:s is not supported.
+ */
+struct timbgpio_platform_data {
+	int gpio_base;
+	int nr_pins;
+	int irq_base;
+};
+
+#endif
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 1eb44a9..10db010 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -134,6 +134,13 @@
  */
 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
 {
+	if (step) {
+		siginfo_t info;
+		user_single_step_siginfo(current, regs, &info);
+		force_sig_info(SIGTRAP, &info, current);
+		return;
+	}
+
 	ptrace_report_syscall(regs);
 }
 
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index 79b9837..cf97b5b 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -1,4 +1,4 @@
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/module.h>
 
 /* Simply sanity version stamp for modules. */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 32b9229..d4962a7 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -294,6 +294,7 @@
 
 /* Grey formats */
 #define V4L2_PIX_FMT_GREY    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
+#define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
 /* Palette formats */
@@ -329,7 +330,11 @@
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
 #define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
 #define V4L2_PIX_FMT_SGRBG8  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
-#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */
+#define V4L2_PIX_FMT_SRGGB8  v4l2_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10  BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
 	/* 10bit raw bayer DPCM compressed to 8 bits */
 #define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
 	/*
@@ -732,6 +737,99 @@
 };
 
 /*
+ *	V I D E O	T I M I N G S	D V	P R E S E T
+ */
+struct v4l2_dv_preset {
+	__u32	preset;
+	__u32	reserved[4];
+};
+
+/*
+ *	D V	P R E S E T S	E N U M E R A T I O N
+ */
+struct v4l2_dv_enum_preset {
+	__u32	index;
+	__u32	preset;
+	__u8	name[32]; /* Name of the preset timing */
+	__u32	width;
+	__u32	height;
+	__u32	reserved[4];
+};
+
+/*
+ * 	D V	P R E S E T	V A L U E S
+ */
+#define		V4L2_DV_INVALID		0
+#define		V4L2_DV_480P59_94	1 /* BT.1362 */
+#define		V4L2_DV_576P50		2 /* BT.1362 */
+#define		V4L2_DV_720P24		3 /* SMPTE 296M */
+#define		V4L2_DV_720P25		4 /* SMPTE 296M */
+#define		V4L2_DV_720P30		5 /* SMPTE 296M */
+#define		V4L2_DV_720P50		6 /* SMPTE 296M */
+#define		V4L2_DV_720P59_94	7 /* SMPTE 274M */
+#define		V4L2_DV_720P60		8 /* SMPTE 274M/296M */
+#define		V4L2_DV_1080I29_97	9 /* BT.1120/ SMPTE 274M */
+#define		V4L2_DV_1080I30		10 /* BT.1120/ SMPTE 274M */
+#define		V4L2_DV_1080I25		11 /* BT.1120 */
+#define		V4L2_DV_1080I50		12 /* SMPTE 296M */
+#define		V4L2_DV_1080I60		13 /* SMPTE 296M */
+#define		V4L2_DV_1080P24		14 /* SMPTE 296M */
+#define		V4L2_DV_1080P25		15 /* SMPTE 296M */
+#define		V4L2_DV_1080P30		16 /* SMPTE 296M */
+#define		V4L2_DV_1080P50		17 /* BT.1120 */
+#define		V4L2_DV_1080P60		18 /* BT.1120 */
+
+/*
+ *	D V 	B T	T I M I N G S
+ */
+
+/* BT.656/BT.1120 timing data */
+struct v4l2_bt_timings {
+	__u32	width;		/* width in pixels */
+	__u32	height;		/* height in lines */
+	__u32	interlaced;	/* Interlaced or progressive */
+	__u32	polarities;	/* Positive or negative polarity */
+	__u64	pixelclock;	/* Pixel clock in HZ. Ex. 74.25MHz->74250000 */
+	__u32	hfrontporch;	/* Horizpontal front porch in pixels */
+	__u32	hsync;		/* Horizontal Sync length in pixels */
+	__u32	hbackporch;	/* Horizontal back porch in pixels */
+	__u32	vfrontporch;	/* Vertical front porch in pixels */
+	__u32	vsync;		/* Vertical Sync length in lines */
+	__u32	vbackporch;	/* Vertical back porch in lines */
+	__u32	il_vfrontporch;	/* Vertical front porch for bottom field of
+				 * interlaced field formats
+				 */
+	__u32	il_vsync;	/* Vertical sync length for bottom field of
+				 * interlaced field formats
+				 */
+	__u32	il_vbackporch;	/* Vertical back porch for bottom field of
+				 * interlaced field formats
+				 */
+	__u32	reserved[16];
+} __attribute__ ((packed));
+
+/* Interlaced or progressive format */
+#define	V4L2_DV_PROGRESSIVE	0
+#define	V4L2_DV_INTERLACED	1
+
+/* Polarities. If bit is not set, it is assumed to be negative polarity */
+#define V4L2_DV_VSYNC_POS_POL	0x00000001
+#define V4L2_DV_HSYNC_POS_POL	0x00000002
+
+
+/* DV timings */
+struct v4l2_dv_timings {
+	__u32 type;
+	union {
+		struct v4l2_bt_timings	bt;
+		__u32	reserved[32];
+	};
+} __attribute__ ((packed));
+
+/* Values for the type field */
+#define V4L2_DV_BT_656_1120	0	/* BT.656/1120 timing type */
+
+/*
  *	V I D E O   I N P U T S
  */
 struct v4l2_input {
@@ -742,7 +840,8 @@
 	__u32        tuner;             /*  Associated tuner */
 	v4l2_std_id  std;
 	__u32	     status;
-	__u32	     reserved[4];
+	__u32	     capabilities;
+	__u32	     reserved[3];
 };
 
 /*  Values for the 'type' field */
@@ -773,6 +872,11 @@
 #define V4L2_IN_ST_NO_ACCESS   0x02000000  /* Conditional access denied */
 #define V4L2_IN_ST_VTR         0x04000000  /* VTR time constant */
 
+/* capabilities flags */
+#define V4L2_IN_CAP_PRESETS		0x00000001 /* Supports S_DV_PRESET */
+#define V4L2_IN_CAP_CUSTOM_TIMINGS	0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_IN_CAP_STD			0x00000004 /* Supports S_STD */
+
 /*
  *	V I D E O   O U T P U T S
  */
@@ -783,13 +887,19 @@
 	__u32	     audioset;		/*  Associated audios (bitfield) */
 	__u32	     modulator;         /*  Associated modulator */
 	v4l2_std_id  std;
-	__u32	     reserved[4];
+	__u32	     capabilities;
+	__u32	     reserved[3];
 };
 /*  Values for the 'type' field */
 #define V4L2_OUTPUT_TYPE_MODULATOR		1
 #define V4L2_OUTPUT_TYPE_ANALOG			2
 #define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY	3
 
+/* capabilities flags */
+#define V4L2_OUT_CAP_PRESETS		0x00000001 /* Supports S_DV_PRESET */
+#define V4L2_OUT_CAP_CUSTOM_TIMINGS	0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_OUT_CAP_STD		0x00000004 /* Supports S_STD */
+
 /*
  *	C O N T R O L S
  */
@@ -1624,6 +1734,13 @@
 #endif
 
 #define VIDIOC_S_HW_FREQ_SEEK	 _IOW('V', 82, struct v4l2_hw_freq_seek)
+#define	VIDIOC_ENUM_DV_PRESETS	_IOWR('V', 83, struct v4l2_dv_enum_preset)
+#define	VIDIOC_S_DV_PRESET	_IOWR('V', 84, struct v4l2_dv_preset)
+#define	VIDIOC_G_DV_PRESET	_IOWR('V', 85, struct v4l2_dv_preset)
+#define	VIDIOC_QUERY_DV_PRESET	_IOR('V',  86, struct v4l2_dv_preset)
+#define	VIDIOC_S_DV_TIMINGS	_IOWR('V', 87, struct v4l2_dv_timings)
+#define	VIDIOC_G_DV_TIMINGS	_IOWR('V', 88, struct v4l2_dv_timings)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
diff --git a/include/linux/vt.h b/include/linux/vt.h
index 3fb9944..d5dd0bc 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -84,6 +84,8 @@
 
 #define VT_SETACTIVATE	0x560F	/* Activate and set the mode of a console */
 
+#ifdef __KERNEL__
+
 #ifdef CONFIG_VT_CONSOLE
 
 extern int vt_kmsg_redirect(int new);
@@ -97,6 +99,8 @@
 
 #endif
 
+#endif /* __KERNEL__ */
+
 #define vt_get_kmsg_redirect() vt_kmsg_redirect(-1)
 
 #endif /* _LINUX_VT_H */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 705f01f..c18c008 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -79,8 +79,7 @@
 static inline void wait_on_inode(struct inode *inode)
 {
 	might_sleep();
-	wait_on_bit(&inode->i_state, __I_LOCK, inode_wait,
-							TASK_UNINTERRUPTIBLE);
+	wait_on_bit(&inode->i_state, __I_NEW, inode_wait, TASK_UNINTERRUPTIBLE);
 }
 static inline void inode_sync_wait(struct inode *inode)
 {
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 5c84af8..fb9b7e6 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -38,12 +38,13 @@
 
 struct xattr_handler {
 	char *prefix;
-	size_t (*list)(struct inode *inode, char *list, size_t list_size,
-		       const char *name, size_t name_len);
-	int (*get)(struct inode *inode, const char *name, void *buffer,
-		   size_t size);
-	int (*set)(struct inode *inode, const char *name, const void *buffer,
-		   size_t size, int flags);
+	int flags;	/* fs private flags passed back to the handlers */
+	size_t (*list)(struct dentry *dentry, char *list, size_t list_size,
+		       const char *name, size_t name_len, int handler_flags);
+	int (*get)(struct dentry *dentry, const char *name, void *buffer,
+		   size_t size, int handler_flags);
+	int (*set)(struct dentry *dentry, const char *name, const void *buffer,
+		   size_t size, int flags, int handler_flags);
 };
 
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index e41a99e..2c6af24 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -26,26 +26,7 @@
 #include <linux/input.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
-#include <linux/spinlock.h>
-
-extern int media_ir_debug;    /* media_ir_debug level (0,1,2) */
-#define IR_dprintk(level, fmt, arg...)	if (media_ir_debug >= level) \
-	printk(KERN_DEBUG "%s: " fmt , __func__, ## arg)
-
-#define IR_TYPE_RC5     1
-#define IR_TYPE_PD      2 /* Pulse distance encoded IR */
-#define IR_TYPE_OTHER  99
-
-struct ir_scancode {
-	u16	scancode;
-	u32	keycode;
-};
-
-struct ir_scancode_table {
-	struct ir_scancode *scan;
-	int size;
-	spinlock_t lock;
-};
+#include <media/ir-core.h>
 
 #define RC5_START(x)	(((x)>>12)&3)
 #define RC5_TOGGLE(x)	(((x)>>11)&1)
@@ -56,8 +37,6 @@
 	/* configuration */
 	int                ir_type;
 
-	struct ir_scancode_table keytable;
-
 	/* key info */
 	u32                ir_key;      /* ir scancode */
 	u32                keycode;     /* linux key code */
@@ -105,7 +84,7 @@
 /* Routines from ir-functions.c */
 
 int ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
-		   int ir_type, struct ir_scancode_table *ir_codes);
+		   int ir_type);
 void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir);
 void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
 		      u32 ir_key);
@@ -118,19 +97,6 @@
 void ir_rc5_timer_end(unsigned long data);
 void ir_rc5_timer_keyup(unsigned long data);
 
-/* Routines from ir-keytable.c */
-
-u32 ir_g_keycode_from_table(struct input_dev *input_dev,
-			    u32 scancode);
-
-int ir_set_keycode_table(struct input_dev *input_dev,
-			 struct ir_scancode_table *rc_tab);
-
-int ir_roundup_tablesize(int n_elems);
-int ir_copy_table(struct ir_scancode_table *destin,
-		 const struct ir_scancode_table *origin);
-void ir_input_free(struct input_dev *input_dev);
-
 /* scancode->keycode map tables from ir-keymaps.c */
 
 extern struct ir_scancode_table ir_codes_empty_table;
@@ -195,4 +161,5 @@
 extern struct ir_scancode_table ir_codes_terratec_cinergy_xs_table;
 extern struct ir_scancode_table ir_codes_videomate_s350_table;
 extern struct ir_scancode_table ir_codes_gadmei_rm008z_table;
+extern struct ir_scancode_table ir_codes_nec_terratec_cinergy_xs_table;
 #endif
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
new file mode 100644
index 0000000..299d201
--- /dev/null
+++ b/include/media/ir-core.h
@@ -0,0 +1,62 @@
+/*
+ * Remote Controller core header
+ *
+ * This program is free software; 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.
+ */
+
+#ifndef _IR_CORE
+#define _IR_CORE
+
+#include <linux/input.h>
+#include <linux/spinlock.h>
+
+extern int ir_core_debug;
+#define IR_dprintk(level, fmt, arg...)	if (ir_core_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt , __func__, ## arg)
+
+enum ir_type {
+	IR_TYPE_UNKNOWN	= 0,
+	IR_TYPE_RC5	= 1,
+	IR_TYPE_PD	= 2,		 /* Pulse distance encoded IR */
+	IR_TYPE_NEC	= 3,
+	IR_TYPE_OTHER	= 99,
+};
+
+struct ir_scancode {
+	u16	scancode;
+	u32	keycode;
+};
+
+struct ir_scancode_table {
+	struct ir_scancode	*scan;
+	int			size;
+	enum			ir_type ir_type;
+	spinlock_t		lock;
+};
+
+struct ir_input_dev {
+	struct input_dev		*dev;
+	struct ir_scancode_table	rc_tab;
+};
+
+/* Routines from ir-keytable.c */
+
+u32 ir_g_keycode_from_table(struct input_dev *input_dev,
+			    u32 scancode);
+
+int ir_set_keycode_table(struct input_dev *input_dev,
+			 struct ir_scancode_table *rc_tab);
+
+int ir_roundup_tablesize(int n_elems);
+int ir_input_register(struct input_dev *dev,
+		      struct ir_scancode_table *ir_codes);
+void ir_input_unregister(struct input_dev *input_dev);
+
+#endif
diff --git a/include/media/mt9t112.h b/include/media/mt9t112.h
new file mode 100644
index 0000000..a43c74a
--- /dev/null
+++ b/include/media/mt9t112.h
@@ -0,0 +1,30 @@
+/* mt9t112 Camera
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.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 __MT9T112_H__
+#define __MT9T112_H__
+
+#define MT9T112_FLAG_PCLK_RISING_EDGE	(1 << 0)
+#define MT9T112_FLAG_DATAWIDTH_8	(1 << 1) /* default width is 10 */
+
+struct mt9t112_pll_divider {
+	u8 m, n;
+	u8 p1, p2, p3, p4, p5, p6, p7;
+};
+
+/*
+ * mt9t112 camera info
+ */
+struct mt9t112_camera_info {
+	u32 flags;
+	struct mt9t112_pll_divider divider;
+};
+
+#endif /* __MT9T112_H__ */
diff --git a/include/media/ov772x.h b/include/media/ov772x.h
index 30d9629..14c77ef 100644
--- a/include/media/ov772x.h
+++ b/include/media/ov772x.h
@@ -1,4 +1,5 @@
-/* ov772x Camera
+/*
+ * ov772x Camera
  *
  * Copyright (C) 2008 Renesas Solutions Corp.
  * Kuninori Morimoto <morimoto.kuninori@renesas.com>
@@ -54,7 +55,6 @@
 struct ov772x_camera_info {
 	unsigned long          buswidth;
 	unsigned long          flags;
-	struct soc_camera_link link;
 	struct ov772x_edge_ctrl edgectrl;
 };
 
diff --git a/include/media/rj54n1cb0c.h b/include/media/rj54n1cb0c.h
new file mode 100644
index 0000000..8ae3288
--- /dev/null
+++ b/include/media/rj54n1cb0c.h
@@ -0,0 +1,19 @@
+/*
+ * RJ54N1CB0C Private data
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __RJ54N1CB0C_H__
+#define __RJ54N1CB0C_H__
+
+struct rj54n1_pdata {
+	unsigned int	mclk_freq;
+	bool		ioctl_high;
+};
+
+#endif
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index eed5fcc..4aeff96 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -108,8 +108,6 @@
 
 struct saa7146_vv
 {
-	int vbi_minor;
-
 	/* vbi capture */
 	struct saa7146_dmaqueue		vbi_q;
 	/* vbi workaround interrupt queue */
@@ -117,8 +115,6 @@
 	int				vbi_fieldcount;
 	struct saa7146_fh		*vbi_streaming;
 
-	int video_minor;
-
 	int				video_status;
 	struct saa7146_fh		*video_fh;
 
diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h
index 0f3524c..b677478 100644
--- a/include/media/sh_mobile_ceu.h
+++ b/include/media/sh_mobile_ceu.h
@@ -3,6 +3,8 @@
 
 #define SH_CEU_FLAG_USE_8BIT_BUS	(1 << 0) /* use  8bit bus width */
 #define SH_CEU_FLAG_USE_16BIT_BUS	(1 << 1) /* use 16bit bus width */
+#define SH_CEU_FLAG_HSYNC_LOW		(1 << 2) /* default High if possible */
+#define SH_CEU_FLAG_VSYNC_LOW		(1 << 3) /* default High if possible */
 
 struct sh_mobile_ceu_info {
 	unsigned long flags;
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 3d74e60..dcc5b86 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -24,18 +24,13 @@
 	struct device *pdev;		/* Platform device */
 	s32 user_width;
 	s32 user_height;
-	unsigned short width_min;
-	unsigned short height_min;
-	unsigned short y_skip_top;	/* Lines to skip at the top */
+	enum v4l2_colorspace colorspace;
 	unsigned char iface;		/* Host number */
 	unsigned char devnum;		/* Device number per host */
-	unsigned char buswidth;		/* See comment in .c */
 	struct soc_camera_sense *sense;	/* See comment in struct definition */
 	struct soc_camera_ops *ops;
 	struct video_device *vdev;
-	const struct soc_camera_data_format *current_fmt;
-	const struct soc_camera_data_format *formats;
-	int num_formats;
+	const struct soc_camera_format_xlate *current_fmt;
 	struct soc_camera_format_xlate *user_formats;
 	int num_user_formats;
 	enum v4l2_field field;		/* Preserve field over close() */
@@ -107,6 +102,8 @@
 	int i2c_adapter_id;
 	struct i2c_board_info *board_info;
 	const char *module_name;
+	void *priv;
+
 	/*
 	 * For non-I2C devices platform platform has to provide methods to
 	 * add a device to the system and to remove
@@ -162,23 +159,13 @@
 int soc_camera_host_register(struct soc_camera_host *ici);
 void soc_camera_host_unregister(struct soc_camera_host *ici);
 
-const struct soc_camera_data_format *soc_camera_format_by_fourcc(
-	struct soc_camera_device *icd, unsigned int fourcc);
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
 	struct soc_camera_device *icd, unsigned int fourcc);
 
-struct soc_camera_data_format {
-	const char *name;
-	unsigned int depth;
-	__u32 fourcc;
-	enum v4l2_colorspace colorspace;
-};
-
 /**
  * struct soc_camera_format_xlate - match between host and sensor formats
- * @cam_fmt: sensor format provided by the sensor
- * @host_fmt: host format after host translation from cam_fmt
- * @buswidth: bus width for this format
+ * @code: code of a sensor provided format
+ * @host_fmt: host format after host translation from code
  *
  * Host and sensor translation structure. Used in table of host and sensor
  * formats matchings in soc_camera_device. A host can override the generic list
@@ -186,9 +173,8 @@
  * format setup.
  */
 struct soc_camera_format_xlate {
-	const struct soc_camera_data_format *cam_fmt;
-	const struct soc_camera_data_format *host_fmt;
-	unsigned char buswidth;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *host_fmt;
 };
 
 struct soc_camera_ops {
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
index bb70401..0ecefe2 100644
--- a/include/media/soc_camera_platform.h
+++ b/include/media/soc_camera_platform.h
@@ -19,11 +19,10 @@
 struct soc_camera_platform_info {
 	const char *format_name;
 	unsigned long format_depth;
-	struct v4l2_pix_format format;
+	struct v4l2_mbus_framefmt format;
 	unsigned long bus_param;
 	struct device *dev;
 	int (*set_capture)(struct soc_camera_platform_info *info, int enable);
-	struct soc_camera_link link;
 };
 
 #endif /* __SOC_CAMERA_H__ */
diff --git a/include/media/soc_mediabus.h b/include/media/soc_mediabus.h
new file mode 100644
index 0000000..037cd7b
--- /dev/null
+++ b/include/media/soc_mediabus.h
@@ -0,0 +1,65 @@
+/*
+ * SoC-camera Media Bus API extensions
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef SOC_MEDIABUS_H
+#define SOC_MEDIABUS_H
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-mediabus.h>
+
+/**
+ * enum soc_mbus_packing - data packing types on the media-bus
+ * @SOC_MBUS_PACKING_NONE:	no packing, bit-for-bit transfer to RAM
+ * @SOC_MBUS_PACKING_2X8_PADHI:	16 bits transferred in 2 8-bit samples, in the
+ *				possibly incomplete byte high bits are padding
+ * @SOC_MBUS_PACKING_2X8_PADLO:	as above, but low bits are padding
+ * @SOC_MBUS_PACKING_EXTEND16:	sample width (e.g., 10 bits) has to be extended
+ *				to 16 bits
+ */
+enum soc_mbus_packing {
+	SOC_MBUS_PACKING_NONE,
+	SOC_MBUS_PACKING_2X8_PADHI,
+	SOC_MBUS_PACKING_2X8_PADLO,
+	SOC_MBUS_PACKING_EXTEND16,
+};
+
+/**
+ * enum soc_mbus_order - sample order on the media bus
+ * @SOC_MBUS_ORDER_LE:		least significant sample first
+ * @SOC_MBUS_ORDER_BE:		most significant sample first
+ */
+enum soc_mbus_order {
+	SOC_MBUS_ORDER_LE,
+	SOC_MBUS_ORDER_BE,
+};
+
+/**
+ * struct soc_mbus_pixelfmt - Data format on the media bus
+ * @name:		Name of the format
+ * @fourcc:		Fourcc code, that will be obtained if the data is
+ *			stored in memory in the following way:
+ * @packing:		Type of sample-packing, that has to be used
+ * @order:		Sample order when storing in memory
+ * @bits_per_sample:	How many bits the bridge has to sample
+ */
+struct soc_mbus_pixelfmt {
+	const char		*name;
+	u32			fourcc;
+	enum soc_mbus_packing	packing;
+	enum soc_mbus_order	order;
+	u8			bits_per_sample;
+};
+
+const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
+	enum v4l2_mbus_pixelcode code);
+s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf);
+
+#endif
diff --git a/include/media/tw9910.h b/include/media/tw9910.h
index 73231e7..5e2895a 100644
--- a/include/media/tw9910.h
+++ b/include/media/tw9910.h
@@ -32,7 +32,6 @@
 struct tw9910_video_info {
 	unsigned long          buswidth;
 	enum tw9910_mpout_pin  mpout;
-	struct soc_camera_link link;
 };
 
 
diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
index 91942db..6cc107d 100644
--- a/include/media/v4l2-chip-ident.h
+++ b/include/media/v4l2-chip-ident.h
@@ -267,6 +267,8 @@
 	V4L2_IDENT_MT9V022IX7ATC	= 45010, /* No way to detect "normal" I77ATx */
 	V4L2_IDENT_MT9V022IX7ATM	= 45015, /* and "lead free" IA7ATx chips */
 	V4L2_IDENT_MT9T031		= 45020,
+	V4L2_IDENT_MT9T111		= 45021,
+	V4L2_IDENT_MT9T112		= 45022,
 	V4L2_IDENT_MT9V111		= 45031,
 	V4L2_IDENT_MT9V112		= 45032,
 
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 1c25b10..1c7b259 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -212,5 +212,5 @@
 			   unsigned int *h, unsigned int hmin,
 			   unsigned int hmax, unsigned int halign,
 			   unsigned int salign);
-
+int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info);
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 73c9867..2dee938 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -28,10 +28,10 @@
 struct video_device;
 struct v4l2_device;
 
-/* Flag to mark the video_device struct as unregistered.
-   Drivers can set this flag if they want to block all future
-   device access. It is set by video_unregister_device. */
-#define V4L2_FL_UNREGISTERED	(0)
+/* Flag to mark the video_device struct as registered.
+   Drivers can clear this flag if they want to block all future
+   device access. It is cleared by video_unregister_device. */
+#define V4L2_FL_REGISTERED	(0)
 
 struct v4l2_file_operations {
 	struct module *owner;
@@ -96,9 +96,7 @@
 /* Register video devices. Note that if video_register_device fails,
    the release() callback of the video_device structure is *not* called, so
    the caller is responsible for freeing any data. Usually that means that
-   you call video_device_release() on failure.
-
-   Also note that vdev->minor is set to -1 if the registration failed. */
+   you call video_device_release() on failure. */
 int __must_check video_register_device(struct video_device *vdev, int type, int nr);
 
 /* Same as video_register_device, but no warning is issued if the desired
@@ -106,7 +104,7 @@
 int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr);
 
 /* Unregister video devices. Will do nothing if vdev == NULL or
-   vdev->minor < 0. */
+   video_is_registered() returns false. */
 void video_unregister_device(struct video_device *vdev);
 
 /* helper functions to alloc/release struct video_device, the
@@ -141,9 +139,14 @@
 	return video_get_drvdata(video_devdata(file));
 }
 
-static inline int video_is_unregistered(struct video_device *vdev)
+static inline const char *video_device_node_name(struct video_device *vdev)
 {
-	return test_bit(V4L2_FL_UNREGISTERED, &vdev->flags);
+	return dev_name(&vdev->dev);
+}
+
+static inline int video_is_registered(struct video_device *vdev)
+{
+	return test_bit(V4L2_FL_REGISTERED, &vdev->flags);
 }
 
 #endif /* _V4L2_DEV_H */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 7a4529d..e8ba0f2 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -239,6 +239,21 @@
 	int (*vidioc_enum_frameintervals) (struct file *file, void *fh,
 					   struct v4l2_frmivalenum *fival);
 
+	/* DV Timings IOCTLs */
+	int (*vidioc_enum_dv_presets) (struct file *file, void *fh,
+				       struct v4l2_dv_enum_preset *preset);
+
+	int (*vidioc_s_dv_preset) (struct file *file, void *fh,
+				   struct v4l2_dv_preset *preset);
+	int (*vidioc_g_dv_preset) (struct file *file, void *fh,
+				   struct v4l2_dv_preset *preset);
+	int (*vidioc_query_dv_preset) (struct file *file, void *fh,
+					struct v4l2_dv_preset *qpreset);
+	int (*vidioc_s_dv_timings) (struct file *file, void *fh,
+				    struct v4l2_dv_timings *timings);
+	int (*vidioc_g_dv_timings) (struct file *file, void *fh,
+				    struct v4l2_dv_timings *timings);
+
 	/* For other private ioctls */
 	long (*vidioc_default)	       (struct file *file, void *fh,
 					int cmd, void *arg);
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
new file mode 100644
index 0000000..0dbe02a
--- /dev/null
+++ b/include/media/v4l2-mediabus.h
@@ -0,0 +1,61 @@
+/*
+ * Media Bus API header
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef V4L2_MEDIABUS_H
+#define V4L2_MEDIABUS_H
+
+/*
+ * These pixel codes uniquely identify data formats on the media bus. Mostly
+ * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
+ * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
+ * data format is fixed. Additionally, "2X8" means that one pixel is transferred
+ * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
+ * transferred over the bus: "LE" means that the least significant bits are
+ * transferred first, "BE" means that the most significant bits are transferred
+ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+ * incomplete high byte, are filled with padding bits.
+ */
+enum v4l2_mbus_pixelcode {
+	V4L2_MBUS_FMT_FIXED = 1,
+	V4L2_MBUS_FMT_YUYV8_2X8_LE,
+	V4L2_MBUS_FMT_YVYU8_2X8_LE,
+	V4L2_MBUS_FMT_YUYV8_2X8_BE,
+	V4L2_MBUS_FMT_YVYU8_2X8_BE,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
+	V4L2_MBUS_FMT_RGB565_2X8_BE,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_GREY8_1X8,
+	V4L2_MBUS_FMT_Y10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
+	V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
+};
+
+/**
+ * struct v4l2_mbus_framefmt - frame format on the media bus
+ * @width:	frame width
+ * @height:	frame height
+ * @code:	data format code
+ * @field:	used interlacing type
+ * @colorspace:	colorspace of the data
+ */
+struct v4l2_mbus_framefmt {
+	__u32				width;
+	__u32				height;
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_field			field;
+	enum v4l2_colorspace		colorspace;
+};
+
+#endif
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 00bf176..9ba99cd 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -22,6 +22,7 @@
 #define _V4L2_SUBDEV_H
 
 #include <media/v4l2-common.h>
+#include <media/v4l2-mediabus.h>
 
 /* generic v4l2_device notify callback notification values */
 #define V4L2_SUBDEV_IR_RX_NOTIFY		_IOW('v', 0, u32)
@@ -207,7 +208,7 @@
    s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
 	video input devices.
 
-  s_crystal_freq: sets the frequency of the crystal used to generate the
+   s_crystal_freq: sets the frequency of the crystal used to generate the
 	clocks in Hz. An extra flags field allows device specific configuration
 	regarding clock frequency dividers, etc. If not used, then set flags
 	to 0. If the frequency is not supported, then -EINVAL is returned.
@@ -217,6 +218,26 @@
 
    s_routing: see s_routing in audio_ops, except this version is for video
 	devices.
+
+   s_dv_preset: set dv (Digital Video) preset in the sub device. Similar to
+	s_std()
+
+   query_dv_preset: query dv preset in the sub device. This is similar to
+	querystd()
+
+   s_dv_timings(): Set custom dv timings in the sub device. This is used
+	when sub device is capable of setting detailed timing information
+	in the hardware to generate/detect the video signal.
+
+   g_dv_timings(): Get custom dv timings in the sub device.
+
+   enum_mbus_fmt: enumerate pixel formats, provided by a video data source
+
+   g_mbus_fmt: get the current pixel format, provided by a video data source
+
+   try_mbus_fmt: try to set a pixel format on a video data source
+
+   s_mbus_fmt: set a pixel format on a video data source
  */
 struct v4l2_subdev_video_ops {
 	int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -240,6 +261,33 @@
 	int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
 	int (*enum_framesizes)(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
 	int (*enum_frameintervals)(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
+	int (*s_dv_preset)(struct v4l2_subdev *sd,
+			struct v4l2_dv_preset *preset);
+	int (*query_dv_preset)(struct v4l2_subdev *sd,
+			struct v4l2_dv_preset *preset);
+	int (*s_dv_timings)(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings *timings);
+	int (*g_dv_timings)(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings *timings);
+	int (*enum_mbus_fmt)(struct v4l2_subdev *sd, int index,
+			     enum v4l2_mbus_pixelcode *code);
+	int (*g_mbus_fmt)(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *fmt);
+	int (*try_mbus_fmt)(struct v4l2_subdev *sd,
+			    struct v4l2_mbus_framefmt *fmt);
+	int (*s_mbus_fmt)(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *fmt);
+};
+
+/**
+ * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations
+ * @g_skip_top_lines: number of lines at the top of the image to be skipped.
+ *		      This is needed for some sensors, which always corrupt
+ *		      several top lines of the output image, or which send their
+ *		      metadata in them.
+ */
+struct v4l2_subdev_sensor_ops {
+	int (*g_skip_top_lines)(struct v4l2_subdev *sd, u32 *lines);
 };
 
 /*
@@ -326,11 +374,12 @@
 };
 
 struct v4l2_subdev_ops {
-	const struct v4l2_subdev_core_ops  *core;
-	const struct v4l2_subdev_tuner_ops *tuner;
-	const struct v4l2_subdev_audio_ops *audio;
-	const struct v4l2_subdev_video_ops *video;
-	const struct v4l2_subdev_ir_ops    *ir;
+	const struct v4l2_subdev_core_ops	*core;
+	const struct v4l2_subdev_tuner_ops	*tuner;
+	const struct v4l2_subdev_audio_ops	*audio;
+	const struct v4l2_subdev_video_ops	*video;
+	const struct v4l2_subdev_ir_ops		*ir;
+	const struct v4l2_subdev_sensor_ops	*sensor;
 };
 
 #define V4L2_SUBDEV_NAME_SIZE 32
diff --git a/include/net/dst.h b/include/net/dst.h
index 387cb3c..39c4a59 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -113,7 +113,7 @@
 static inline u32
 dst_feature(const struct dst_entry *dst, u32 feature)
 {
-	return (dst ? dst_metric(dst, RTAX_FEATURES) & feature : 0);
+	return dst_metric(dst, RTAX_FEATURES) & feature;
 }
 
 static inline u32 dst_mtu(const struct dst_entry *dst)
diff --git a/include/net/ip.h b/include/net/ip.h
index e6b9d12..85108cf 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -337,6 +337,7 @@
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
 	IP_DEFRAG_CONNTRACK_OUT,
+	IP_DEFRAG_CONNTRACK_BRIDGE_IN,
 	IP_DEFRAG_VS_IN,
 	IP_DEFRAG_VS_OUT,
 	IP_DEFRAG_VS_FWD
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 92db861..ccab594 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -350,8 +350,16 @@
 
 struct inet_frag_queue;
 
+enum ip6_defrag_users {
+	IP6_DEFRAG_LOCAL_DELIVER,
+	IP6_DEFRAG_CONNTRACK_IN,
+	IP6_DEFRAG_CONNTRACK_OUT,
+	IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
+};
+
 struct ip6_create_arg {
 	__be32 id;
+	u32 user;
 	struct in6_addr *src;
 	struct in6_addr *dst;
 };
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index abc55ad..1ee717e 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -9,7 +9,7 @@
 
 extern int nf_ct_frag6_init(void);
 extern void nf_ct_frag6_cleanup(void);
-extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb);
+extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
 extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
 			       struct net_device *in,
 			       struct net_device *out,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 1b6f7d3..34f5cc2 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -408,8 +408,7 @@
 extern void			tcp_parse_options(struct sk_buff *skb,
 						  struct tcp_options_received *opt_rx,
 						  u8 **hvpp,
-						  int estab,
-						  struct dst_entry *dst);
+						  int estab);
 
 extern u8			*tcp_parse_md5sig_option(struct tcphdr *th);
 
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
index 483057b..fa0d52b 100644
--- a/include/rdma/ib_addr.h
+++ b/include/rdma/ib_addr.h
@@ -36,6 +36,7 @@
 
 #include <linux/in.h>
 #include <linux/in6.h>
+#include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/socket.h>
 #include <rdma/ib_verbs.h>
@@ -60,8 +61,8 @@
 	unsigned char src_dev_addr[MAX_ADDR_LEN];
 	unsigned char dst_dev_addr[MAX_ADDR_LEN];
 	unsigned char broadcast[MAX_ADDR_LEN];
-	enum rdma_node_type dev_type;
-	struct net_device *src_dev;
+	unsigned short dev_type;
+	int bound_dev_if;
 };
 
 /**
@@ -121,40 +122,29 @@
 	memcpy(gid, dev_addr->broadcast + 4, sizeof *gid);
 }
 
-static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
+static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)
 {
-	memcpy(gid, dev_addr->src_dev_addr + 4, sizeof *gid);
+	return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
 }
 
-static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
+static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-	memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid);
+	memcpy(gid, dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr), sizeof *gid);
 }
 
-static inline void ib_addr_get_dgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
+static inline void rdma_addr_set_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-	memcpy(gid, dev_addr->dst_dev_addr + 4, sizeof *gid);
+	memcpy(dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);
 }
 
-static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
+static inline void rdma_addr_get_dgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-	memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid);
+	memcpy(gid, dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), sizeof *gid);
 }
 
-static inline void iw_addr_get_sgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
+static inline void rdma_addr_set_dgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-	memcpy(gid, dev_addr->src_dev_addr, sizeof *gid);
-}
-
-static inline void iw_addr_get_dgid(struct rdma_dev_addr *dev_addr,
-				    union ib_gid *gid)
-{
-	memcpy(gid, dev_addr->dst_dev_addr, sizeof *gid);
+	memcpy(dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);
 }
 
 #endif /* IB_ADDR_H */
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 3841c1a..1082afa 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -379,4 +379,10 @@
 			 struct ib_sa_path_rec *rec,
 			 struct ib_ah_attr *ah_attr);
 
+/**
+ * ib_sa_unpack_path - Convert a path record from MAD format to struct
+ * ib_sa_path_rec.
+ */
+void ib_sa_unpack_path(void *attribute, struct ib_sa_path_rec *rec);
+
 #endif /* IB_SA_H */
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
index 6591201..cfc7c9b 100644
--- a/include/rdma/ib_user_sa.h
+++ b/include/rdma/ib_user_sa.h
@@ -35,6 +35,22 @@
 
 #include <linux/types.h>
 
+enum {
+	IB_PATH_GMP		= 1,
+	IB_PATH_PRIMARY		= (1<<1),
+	IB_PATH_ALTERNATE	= (1<<2),
+	IB_PATH_OUTBOUND	= (1<<3),
+	IB_PATH_INBOUND		= (1<<4),
+	IB_PATH_INBOUND_REVERSE = (1<<5),
+	IB_PATH_BIDIRECTIONAL	= IB_PATH_OUTBOUND | IB_PATH_INBOUND_REVERSE
+};
+
+struct ib_path_rec_data {
+	__u32	flags;
+	__u32	reserved;
+	__u32	path_rec[16];
+};
+
 struct ib_user_path_rec {
 	__u8	dgid[16];
 	__u8	sgid[16];
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c179318..09509ed 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1425,6 +1425,11 @@
  * @send_wr: A list of work requests to post on the send queue.
  * @bad_send_wr: On an immediate failure, this parameter will reference
  *   the work request that failed to be posted on the QP.
+ *
+ * While IBA Vol. 1 section 11.4.1.1 specifies that if an immediate
+ * error is returned, the QP state shall not be affected,
+ * ib_post_send() will return an immediate error after queueing any
+ * earlier work requests in the list.
  */
 static inline int ib_post_send(struct ib_qp *qp,
 			       struct ib_send_wr *send_wr,
diff --git a/include/rdma/rdma_user_cm.h b/include/rdma/rdma_user_cm.h
index c557054..1d16502 100644
--- a/include/rdma/rdma_user_cm.h
+++ b/include/rdma/rdma_user_cm.h
@@ -215,12 +215,14 @@
 
 /* Option levels */
 enum {
-	RDMA_OPTION_ID		= 0
+	RDMA_OPTION_ID		= 0,
+	RDMA_OPTION_IB		= 1
 };
 
 /* Option details */
 enum {
-	RDMA_OPTION_ID_TOS	= 0
+	RDMA_OPTION_ID_TOS	= 0,
+	RDMA_OPTION_IB_PATH	= 1
 };
 
 struct rdma_ucm_set_option {
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 39d6d10..a8f3701 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -142,6 +142,7 @@
 	struct _osd_io_info {
 		struct bio *bio;
 		u64 total_bytes;
+		u64 residual;
 		struct request *req;
 		struct _osd_req_data_segment *last_seg;
 		u8 *pad_buff;
@@ -150,12 +151,14 @@
 	gfp_t alloc_flags;
 	unsigned timeout;
 	unsigned retries;
+	unsigned sense_len;
 	u8 sense[OSD_MAX_SENSE_LEN];
 	enum osd_attributes_mode attributes_mode;
 
 	osd_req_done_fn *async_done;
 	void *async_private;
 	int async_error;
+	int req_errors;
 };
 
 static inline bool osd_req_is_ver1(struct osd_request *or)
@@ -297,8 +300,6 @@
 };
 
 struct osd_sense_info {
-	u64 out_resid;		/* Zero on success otherwise out residual */
-	u64 in_resid;		/* Zero on success otherwise in residual */
 	enum osd_err_priority osd_err_pri;
 
 	int key;		/* one of enum scsi_sense_keys */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index d1b3de9..73523151 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -436,10 +436,6 @@
 	struct ftrace_raw_##call field;					\
 	int ret;							\
 									\
-	ret = trace_define_common_fields(event_call);			\
-	if (ret)							\
-		return ret;						\
-									\
 	tstruct;							\
 									\
 	return ret;							\
@@ -559,13 +555,7 @@
  *
  * static int ftrace_reg_event_<call>(struct ftrace_event_call *unused)
  * {
- *	int ret;
- *
- *	ret = register_trace_<call>(ftrace_event_<call>);
- *	if (!ret)
- *		pr_info("event trace: Could not activate trace point "
- *			"probe to  <call>");
- *	return ret;
+ *	return register_trace_<call>(ftrace_event_<call>);
  * }
  *
  * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused)
@@ -623,23 +613,12 @@
  *	.trace			= ftrace_raw_output_<call>, <-- stage 2
  * };
  *
- * static int ftrace_raw_init_event_<call>(struct ftrace_event_call *unused)
- * {
- *	int id;
- *
- *	id = register_ftrace_event(&ftrace_event_type_<call>);
- *	if (!id)
- *		return -ENODEV;
- *	event_<call>.id = id;
- *	return 0;
- * }
- *
  * static struct ftrace_event_call __used
  * __attribute__((__aligned__(4)))
  * __attribute__((section("_ftrace_events"))) event_<call> = {
  *	.name			= "<call>",
  *	.system			= "<system>",
- *	.raw_init		= ftrace_raw_init_event_<call>,
+ *	.raw_init		= trace_event_raw_init,
  *	.regfunc		= ftrace_reg_event_<call>,
  *	.unregfunc		= ftrace_unreg_event_<call>,
  *	.show_format		= ftrace_format_<call>,
@@ -647,13 +626,9 @@
  *
  */
 
-#undef TP_FMT
-#define TP_FMT(fmt, args...)	fmt "\n", ##args
-
 #ifdef CONFIG_EVENT_PROFILE
 
 #define _TRACE_PROFILE_INIT(call)					\
-	.profile_count = ATOMIC_INIT(-1),				\
 	.profile_enable = ftrace_profile_enable_##call,			\
 	.profile_disable = ftrace_profile_disable_##call,
 
@@ -728,13 +703,7 @@
 									\
 static int ftrace_raw_reg_event_##call(struct ftrace_event_call *unused)\
 {									\
-	int ret;							\
-									\
-	ret = register_trace_##call(ftrace_raw_event_##call);		\
-	if (ret)							\
-		pr_info("event trace: Could not activate trace point "	\
-			"probe to " #call "\n");			\
-	return ret;							\
+	return register_trace_##call(ftrace_raw_event_##call);		\
 }									\
 									\
 static void ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused)\
@@ -744,19 +713,7 @@
 									\
 static struct trace_event ftrace_event_type_##call = {			\
 	.trace			= ftrace_raw_output_##call,		\
-};									\
-									\
-static int ftrace_raw_init_event_##call(struct ftrace_event_call *unused)\
-{									\
-	int id;								\
-									\
-	id = register_ftrace_event(&ftrace_event_type_##call);		\
-	if (!id)							\
-		return -ENODEV;						\
-	event_##call.id = id;						\
-	INIT_LIST_HEAD(&event_##call.fields);				\
-	return 0;							\
-}
+};
 
 #undef DEFINE_EVENT_PRINT
 #define DEFINE_EVENT_PRINT(template, name, proto, args, print)	\
@@ -776,7 +733,7 @@
 	.name			= #call,				\
 	.system			= __stringify(TRACE_SYSTEM),		\
 	.event			= &ftrace_event_type_##call,		\
-	.raw_init		= ftrace_raw_init_event_##call,		\
+	.raw_init		= trace_event_raw_init,			\
 	.regfunc		= ftrace_raw_reg_event_##call,		\
 	.unregfunc		= ftrace_raw_unreg_event_##call,	\
 	.show_format		= ftrace_format_##template,		\
@@ -793,7 +750,7 @@
 	.name			= #call,				\
 	.system			= __stringify(TRACE_SYSTEM),		\
 	.event			= &ftrace_event_type_##call,		\
-	.raw_init		= ftrace_raw_init_event_##call,		\
+	.raw_init		= trace_event_raw_init,			\
 	.regfunc		= ftrace_raw_reg_event_##call,		\
 	.unregfunc		= ftrace_raw_unreg_event_##call,	\
 	.show_format		= ftrace_format_##call,			\
@@ -953,7 +910,6 @@
 	perf_swevent_put_recursion_context(rctx);			\
 end_recursion:								\
 	local_irq_restore(irq_flags);					\
-									\
 }
 
 #undef DEFINE_EVENT
diff --git a/include/video/da8xx-fb.h b/include/video/da8xx-fb.h
index c051a50..89d43b3 100644
--- a/include/video/da8xx-fb.h
+++ b/include/video/da8xx-fb.h
@@ -38,6 +38,7 @@
 	const char manu_name[10];
 	void *controller_data;
 	const char type[25];
+	void (*panel_power_ctrl)(int);
 };
 
 struct lcd_ctrl_config {
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 25144ab..2882054 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -50,6 +50,8 @@
 	void *board_data;
 	int (*setup_sys)(void *board_data, void *sys_ops_handle,
 			 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
+	void (*start_transfer)(void *board_data, void *sys_ops_handle,
+			       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 	void (*display_on)(void *board_data);
 	void (*display_off)(void *board_data);
 };
diff --git a/init/Makefile b/init/Makefile
index 4a243df..0bf677a 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -15,12 +15,8 @@
 mounts-$(CONFIG_BLK_DEV_INITRD)	+= do_mounts_initrd.o
 mounts-$(CONFIG_BLK_DEV_MD)	+= do_mounts_md.o
 
-# files to be removed upon make clean
-clean-files := ../include/linux/compile.h
-
 # dependencies on generated files need to be listed explicitly
-
-$(obj)/version.o: include/linux/compile.h
+$(obj)/version.o: include/generated/compile.h
 
 # compile.h changes depending on hostname, generation number, etc,
 # so we regenerate it always.
@@ -30,7 +26,7 @@
        chk_compile.h = :
  quiet_chk_compile.h = echo '  CHK     $@'
 silent_chk_compile.h = :
-include/linux/compile.h: FORCE
+include/generated/compile.h: FORCE
 	@$($(quiet)chk_compile.h)
 	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
 	"$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
diff --git a/init/version.c b/init/version.c
index 52a8b98..adff586 100644
--- a/init/version.c
+++ b/init/version.c
@@ -6,11 +6,11 @@
  *  May be freely distributed as part of Linux.
  */
 
-#include <linux/compile.h>
+#include <generated/compile.h>
 #include <linux/module.h>
 #include <linux/uts.h>
 #include <linux/utsname.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/version.h>
 
 #ifndef CONFIG_KALLSYMS
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index ee9d697..c79bd57 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -32,7 +32,6 @@
 #include <linux/nsproxy.h>
 #include <linux/pid.h>
 #include <linux/ipc_namespace.h>
-#include <linux/ima.h>
 
 #include <net/sock.h>
 #include "util.h"
@@ -734,7 +733,6 @@
 		error = PTR_ERR(filp);
 		goto out_putfd;
 	}
-	ima_counts_get(filp);
 
 	fd_install(fd, filp);
 	goto out_upsem;
diff --git a/ipc/msg.c b/ipc/msg.c
index 085bd58..af42ef8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -125,6 +125,7 @@
 void msg_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &msg_ids(ns), freeque);
+	idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
 }
 #endif
 
diff --git a/ipc/sem.c b/ipc/sem.c
index 87c2b64..dbef95b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -129,6 +129,7 @@
 void sem_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &sem_ids(ns), freeary);
+	idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr);
 }
 #endif
 
@@ -240,6 +241,7 @@
 	key_t key = params->key;
 	int nsems = params->u.nsems;
 	int semflg = params->flg;
+	int i;
 
 	if (!nsems)
 		return -EINVAL;
@@ -272,6 +274,11 @@
 	ns->used_sems += nsems;
 
 	sma->sem_base = (struct sem *) &sma[1];
+
+	for (i = 0; i < nsems; i++)
+		INIT_LIST_HEAD(&sma->sem_base[i].sem_pending);
+
+	sma->complex_count = 0;
 	INIT_LIST_HEAD(&sma->sem_pending);
 	INIT_LIST_HEAD(&sma->list_id);
 	sma->sem_nsems = nsems;
@@ -397,63 +404,109 @@
 	return result;
 }
 
-/* Go through the pending queue for the indicated semaphore
- * looking for tasks that can be completed.
+/*
+ * Wake up a process waiting on the sem queue with a given error.
+ * The queue is invalid (may not be accessed) after the function returns.
  */
-static void update_queue (struct sem_array * sma)
+static void wake_up_sem_queue(struct sem_queue *q, int error)
 {
-	int error;
-	struct sem_queue * q;
+	/*
+	 * Hold preempt off so that we don't get preempted and have the
+	 * wakee busy-wait until we're scheduled back on. We're holding
+	 * locks here so it may not strictly be needed, however if the
+	 * locks become preemptible then this prevents such a problem.
+	 */
+	preempt_disable();
+	q->status = IN_WAKEUP;
+	wake_up_process(q->sleeper);
+	/* hands-off: q can disappear immediately after writing q->status. */
+	smp_wmb();
+	q->status = error;
+	preempt_enable();
+}
 
-	q = list_entry(sma->sem_pending.next, struct sem_queue, list);
-	while (&q->list != &sma->sem_pending) {
+static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
+{
+	list_del(&q->list);
+	if (q->nsops == 1)
+		list_del(&q->simple_list);
+	else
+		sma->complex_count--;
+}
+
+
+/**
+ * update_queue(sma, semnum): Look for tasks that can be completed.
+ * @sma: semaphore array.
+ * @semnum: semaphore that was modified.
+ *
+ * update_queue must be called after a semaphore in a semaphore array
+ * was modified. If multiple semaphore were modified, then @semnum
+ * must be set to -1.
+ */
+static void update_queue(struct sem_array *sma, int semnum)
+{
+	struct sem_queue *q;
+	struct list_head *walk;
+	struct list_head *pending_list;
+	int offset;
+
+	/* if there are complex operations around, then knowing the semaphore
+	 * that was modified doesn't help us. Assume that multiple semaphores
+	 * were modified.
+	 */
+	if (sma->complex_count)
+		semnum = -1;
+
+	if (semnum == -1) {
+		pending_list = &sma->sem_pending;
+		offset = offsetof(struct sem_queue, list);
+	} else {
+		pending_list = &sma->sem_base[semnum].sem_pending;
+		offset = offsetof(struct sem_queue, simple_list);
+	}
+
+again:
+	walk = pending_list->next;
+	while (walk != pending_list) {
+		int error, alter;
+
+		q = (struct sem_queue *)((char *)walk - offset);
+		walk = walk->next;
+
+		/* If we are scanning the single sop, per-semaphore list of
+		 * one semaphore and that semaphore is 0, then it is not
+		 * necessary to scan the "alter" entries: simple increments
+		 * that affect only one entry succeed immediately and cannot
+		 * be in the  per semaphore pending queue, and decrements
+		 * cannot be successful if the value is already 0.
+		 */
+		if (semnum != -1 && sma->sem_base[semnum].semval == 0 &&
+				q->alter)
+			break;
+
 		error = try_atomic_semop(sma, q->sops, q->nsops,
 					 q->undo, q->pid);
 
 		/* Does q->sleeper still need to sleep? */
-		if (error <= 0) {
-			struct sem_queue *n;
+		if (error > 0)
+			continue;
 
-			/*
-			 * Continue scanning. The next operation
-			 * that must be checked depends on the type of the
-			 * completed operation:
-			 * - if the operation modified the array, then
-			 *   restart from the head of the queue and
-			 *   check for threads that might be waiting
-			 *   for semaphore values to become 0.
-			 * - if the operation didn't modify the array,
-			 *   then just continue.
-			 * The order of list_del() and reading ->next
-			 * is crucial: In the former case, the list_del()
-			 * must be done first [because we might be the
-			 * first entry in ->sem_pending], in the latter
-			 * case the list_del() must be done last
-			 * [because the list is invalid after the list_del()]
-			 */
-			if (q->alter) {
-				list_del(&q->list);
-				n = list_entry(sma->sem_pending.next,
-						struct sem_queue, list);
-			} else {
-				n = list_entry(q->list.next, struct sem_queue,
-						list);
-				list_del(&q->list);
-			}
+		unlink_queue(sma, q);
 
-			/* wake up the waiting thread */
-			q->status = IN_WAKEUP;
-
-			wake_up_process(q->sleeper);
-			/* hands-off: q will disappear immediately after
-			 * writing q->status.
-			 */
-			smp_wmb();
-			q->status = error;
-			q = n;
-		} else {
-			q = list_entry(q->list.next, struct sem_queue, list);
-		}
+		/*
+		 * The next operation that must be checked depends on the type
+		 * of the completed operation:
+		 * - if the operation modified the array, then restart from the
+		 *   head of the queue and check for threads that might be
+		 *   waiting for the new semaphore values.
+		 * - if the operation didn't modify the array, then just
+		 *   continue.
+		 */
+		alter = q->alter;
+		wake_up_sem_queue(q, error);
+		if (alter && !error)
+			goto again;
 	}
 }
 
@@ -533,12 +586,8 @@
 
 	/* Wake up all pending processes and let them fail with EIDRM. */
 	list_for_each_entry_safe(q, tq, &sma->sem_pending, list) {
-		list_del(&q->list);
-
-		q->status = IN_WAKEUP;
-		wake_up_process(q->sleeper); /* doesn't sleep */
-		smp_wmb();
-		q->status = -EIDRM;	/* hands-off q */
+		unlink_queue(sma, q);
+		wake_up_sem_queue(q, -EIDRM);
 	}
 
 	/* Remove the semaphore set from the IDR */
@@ -575,7 +624,7 @@
 static int semctl_nolock(struct ipc_namespace *ns, int semid,
 			 int cmd, int version, union semun arg)
 {
-	int err = -EINVAL;
+	int err;
 	struct sem_array *sma;
 
 	switch(cmd) {
@@ -652,7 +701,6 @@
 	default:
 		return -EINVAL;
 	}
-	return err;
 out_unlock:
 	sem_unlock(sma);
 	return err;
@@ -759,7 +807,7 @@
 		}
 		sma->sem_ctime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
-		update_queue(sma);
+		update_queue(sma, -1);
 		err = 0;
 		goto out_unlock;
 	}
@@ -801,7 +849,7 @@
 		curr->sempid = task_tgid_vnr(current);
 		sma->sem_ctime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
-		update_queue(sma);
+		update_queue(sma, semnum);
 		err = 0;
 		goto out_unlock;
 	}
@@ -961,17 +1009,31 @@
 	return 0;
 }
 
-static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
+static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
 {
-	struct sem_undo *walk;
+	struct sem_undo *un;
 
-	list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) {
-		if (walk->semid == semid)
-			return walk;
+	list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) {
+		if (un->semid == semid)
+			return un;
 	}
 	return NULL;
 }
 
+static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
+{
+	struct sem_undo *un;
+
+  	assert_spin_locked(&ulp->lock);
+
+	un = __lookup_undo(ulp, semid);
+	if (un) {
+		list_del_rcu(&un->list_proc);
+		list_add_rcu(&un->list_proc, &ulp->list_proc);
+	}
+	return un;
+}
+
 /**
  * find_alloc_undo - Lookup (and if not present create) undo array
  * @ns: namespace
@@ -1163,7 +1225,8 @@
 	error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current));
 	if (error <= 0) {
 		if (alter && error == 0)
-			update_queue (sma);
+			update_queue(sma, (nsops == 1) ? sops[0].sem_num : -1);
+
 		goto out_unlock_free;
 	}
 
@@ -1181,6 +1244,19 @@
 	else
 		list_add(&queue.list, &sma->sem_pending);
 
+	if (nsops == 1) {
+		struct sem *curr;
+		curr = &sma->sem_base[sops->sem_num];
+
+		if (alter)
+			list_add_tail(&queue.simple_list, &curr->sem_pending);
+		else
+			list_add(&queue.simple_list, &curr->sem_pending);
+	} else {
+		INIT_LIST_HEAD(&queue.simple_list);
+		sma->complex_count++;
+	}
+
 	queue.status = -EINTR;
 	queue.sleeper = current;
 	current->state = TASK_INTERRUPTIBLE;
@@ -1222,7 +1298,7 @@
 	 */
 	if (timeout && jiffies_left == 0)
 		error = -EAGAIN;
-	list_del(&queue.list);
+	unlink_queue(sma, &queue);
 
 out_unlock_free:
 	sem_unlock(sma);
@@ -1307,7 +1383,7 @@
 		if (IS_ERR(sma))
 			continue;
 
-		un = lookup_undo(ulp, semid);
+		un = __lookup_undo(ulp, semid);
 		if (un == NULL) {
 			/* exit_sem raced with IPC_RMID+semget() that created
 			 * exactly the same semid. Nothing to do.
@@ -1351,7 +1427,7 @@
 		}
 		sma->sem_otime = get_seconds();
 		/* maybe some queued-up processes were waiting for this */
-		update_queue(sma);
+		update_queue(sma, -1);
 		sem_unlock(sma);
 
 		call_rcu(&un->rcu, free_un);
@@ -1365,7 +1441,7 @@
 	struct sem_array *sma = it;
 
 	return seq_printf(s,
-			  "%10d %10d  %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
+			  "%10d %10d  %4o %10u %5u %5u %5u %5u %10lu %10lu\n",
 			  sma->sem_perm.key,
 			  sma->sem_perm.id,
 			  sma->sem_perm.mode,
diff --git a/ipc/shm.c b/ipc/shm.c
index 11bec62..92fe923 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -39,7 +39,6 @@
 #include <linux/nsproxy.h>
 #include <linux/mount.h>
 #include <linux/ipc_namespace.h>
-#include <linux/ima.h>
 
 #include <asm/uaccess.h>
 
@@ -101,6 +100,7 @@
 void shm_exit_ns(struct ipc_namespace *ns)
 {
 	free_ipcs(ns, &shm_ids(ns), do_shm_rmid);
+	idr_destroy(&ns->ids[IPC_SHM_IDS].ipcs_idr);
 }
 #endif
 
@@ -878,8 +878,8 @@
 	if (err)
 		goto out_unlock;
 
-	path.dentry = dget(shp->shm_file->f_path.dentry);
-	path.mnt    = shp->shm_file->f_path.mnt;
+	path = shp->shm_file->f_path;
+	path_get(&path);
 	shp->shm_nattch++;
 	size = i_size_read(path.dentry->d_inode);
 	shm_unlock(shp);
@@ -889,13 +889,12 @@
 	if (!sfd)
 		goto out_put_dentry;
 
-	file = alloc_file(path.mnt, path.dentry, f_mode,
-			is_file_hugepages(shp->shm_file) ?
+	file = alloc_file(&path, f_mode,
+			  is_file_hugepages(shp->shm_file) ?
 				&shm_file_operations_huge :
 				&shm_file_operations);
 	if (!file)
 		goto out_free;
-	ima_counts_get(file);
 
 	file->private_data = sfd;
 	file->f_mapping = shp->shm_file->f_mapping;
@@ -950,7 +949,7 @@
 out_free:
 	kfree(sfd);
 out_put_dentry:
-	dput(path.dentry);
+	path_put(&path);
 	goto out_nattch;
 }
 
diff --git a/kernel/bounds.c b/kernel/bounds.c
index 3c53013..98a51f2 100644
--- a/kernel/bounds.c
+++ b/kernel/bounds.c
@@ -12,7 +12,7 @@
 
 void foo(void)
 {
-	/* The enum constants to put into include/linux/bounds.h */
+	/* The enum constants to put into include/generated/bounds.h */
 	DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
 	DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
 	/* End of constants */
diff --git a/kernel/exit.c b/kernel/exit.c
index 5962d7c..546774a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -68,10 +68,10 @@
 		detach_pid(p, PIDTYPE_SID);
 
 		list_del_rcu(&p->tasks);
+		list_del_init(&p->sibling);
 		__get_cpu_var(process_counts)--;
 	}
 	list_del_rcu(&p->thread_group);
-	list_del_init(&p->sibling);
 }
 
 /*
@@ -736,12 +736,9 @@
 /*
 * Any that need to be release_task'd are put on the @dead list.
  */
-static void reparent_thread(struct task_struct *father, struct task_struct *p,
+static void reparent_leader(struct task_struct *father, struct task_struct *p,
 				struct list_head *dead)
 {
-	if (p->pdeath_signal)
-		group_send_sig_info(p->pdeath_signal, SEND_SIG_NOINFO, p);
-
 	list_move_tail(&p->sibling, &p->real_parent->children);
 
 	if (task_detached(p))
@@ -780,12 +777,18 @@
 	reaper = find_new_reaper(father);
 
 	list_for_each_entry_safe(p, n, &father->children, sibling) {
-		p->real_parent = reaper;
-		if (p->parent == father) {
-			BUG_ON(task_ptrace(p));
-			p->parent = p->real_parent;
-		}
-		reparent_thread(father, p, &dead_children);
+		struct task_struct *t = p;
+		do {
+			t->real_parent = reaper;
+			if (t->parent == father) {
+				BUG_ON(task_ptrace(t));
+				t->parent = t->real_parent;
+			}
+			if (t->pdeath_signal)
+				group_send_sig_info(t->pdeath_signal,
+						    SEND_SIG_NOINFO, t);
+		} while_each_thread(p, t);
+		reparent_leader(father, p, &dead_children);
 	}
 	write_unlock_irq(&tasklist_lock);
 
@@ -1551,14 +1554,9 @@
 	struct task_struct *p;
 
 	list_for_each_entry(p, &tsk->children, sibling) {
-		/*
-		 * Do not consider detached threads.
-		 */
-		if (!task_detached(p)) {
-			int ret = wait_consider_task(wo, 0, p);
-			if (ret)
-				return ret;
-		}
+		int ret = wait_consider_task(wo, 0, p);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
diff --git a/kernel/fork.c b/kernel/fork.c
index 9bd9144..5b2959b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1127,6 +1127,10 @@
 #ifdef CONFIG_DEBUG_MUTEXES
 	p->blocked_on = NULL; /* not blocked yet */
 #endif
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+	p->memcg_batch.do_batch = 0;
+	p->memcg_batch.memcg = NULL;
+#endif
 
 	p->bts = NULL;
 
@@ -1206,9 +1210,10 @@
 		p->sas_ss_sp = p->sas_ss_size = 0;
 
 	/*
-	 * Syscall tracing should be turned off in the child regardless
-	 * of CLONE_PTRACE.
+	 * Syscall tracing and stepping should be turned off in the
+	 * child regardless of CLONE_PTRACE.
 	 */
+	user_disable_single_step(p);
 	clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
 #ifdef TIF_SYSCALL_EMU
 	clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
@@ -1286,7 +1291,6 @@
 	}
 
 	if (likely(p->pid)) {
-		list_add_tail(&p->sibling, &p->real_parent->children);
 		tracehook_finish_clone(p, clone_flags, trace);
 
 		if (thread_group_leader(p)) {
@@ -1298,6 +1302,7 @@
 			p->signal->tty = tty_kref_get(current->signal->tty);
 			attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
 			attach_pid(p, PIDTYPE_SID, task_session(current));
+			list_add_tail(&p->sibling, &p->real_parent->children);
 			list_add_tail_rcu(&p->tasks, &init_task.tasks);
 			__get_cpu_var(process_counts)++;
 		}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index f336e21..a9a93d9 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -21,7 +21,7 @@
 #include <linux/hardirq.h>
 #include <linux/elf.h>
 #include <linux/elfcore.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/numa.h>
 #include <linux/suspend.h>
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/console.h>
 #include <linux/vmalloc.h>
+#include <linux/swap.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -1082,6 +1083,64 @@
 	}
 }
 
+size_t crash_get_memory_size(void)
+{
+	size_t size;
+	mutex_lock(&kexec_mutex);
+	size = crashk_res.end - crashk_res.start + 1;
+	mutex_unlock(&kexec_mutex);
+	return size;
+}
+
+static void free_reserved_phys_range(unsigned long begin, unsigned long end)
+{
+	unsigned long addr;
+
+	for (addr = begin; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
+		init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
+		free_page((unsigned long)__va(addr));
+		totalram_pages++;
+	}
+}
+
+int crash_shrink_memory(unsigned long new_size)
+{
+	int ret = 0;
+	unsigned long start, end;
+
+	mutex_lock(&kexec_mutex);
+
+	if (kexec_crash_image) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+	start = crashk_res.start;
+	end = crashk_res.end;
+
+	if (new_size >= end - start + 1) {
+		ret = -EINVAL;
+		if (new_size == end - start + 1)
+			ret = 0;
+		goto unlock;
+	}
+
+	start = roundup(start, PAGE_SIZE);
+	end = roundup(start + new_size, PAGE_SIZE);
+
+	free_reserved_phys_range(end, crashk_res.end);
+
+	if (start == end) {
+		crashk_res.end = end;
+		release_resource(&crashk_res);
+	} else
+		crashk_res.end = end - 1;
+
+unlock:
+	mutex_unlock(&kexec_mutex);
+	return ret;
+}
+
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
 			    size_t data_len)
 {
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 528dd78..3feaf5a 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -100,6 +100,26 @@
 }
 KERNEL_ATTR_RO(kexec_crash_loaded);
 
+static ssize_t kexec_crash_size_show(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%zu\n", crash_get_memory_size());
+}
+static ssize_t kexec_crash_size_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t count)
+{
+	unsigned long cnt;
+	int ret;
+
+	if (strict_strtoul(buf, 0, &cnt))
+		return -EINVAL;
+
+	ret = crash_shrink_memory(cnt);
+	return ret < 0 ? ret : count;
+}
+KERNEL_ATTR_RW(kexec_crash_size);
+
 static ssize_t vmcoreinfo_show(struct kobject *kobj,
 			       struct kobj_attribute *attr, char *buf)
 {
@@ -147,6 +167,7 @@
 #ifdef CONFIG_KEXEC
 	&kexec_loaded_attr.attr,
 	&kexec_crash_loaded_attr.attr,
+	&kexec_crash_size_attr.attr,
 	&vmcoreinfo_attr.attr,
 #endif
 	NULL
diff --git a/kernel/module.c b/kernel/module.c
index 12afc5a..e96b8ed 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -880,11 +880,23 @@
 }
 
 #ifdef CONFIG_MODVERSIONS
+/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
+static unsigned long maybe_relocated(unsigned long crc,
+				     const struct module *crc_owner)
+{
+#ifdef ARCH_RELOCATES_KCRCTAB
+	if (crc_owner == NULL)
+		return crc - (unsigned long)reloc_start;
+#endif
+	return crc;
+}
+
 static int check_version(Elf_Shdr *sechdrs,
 			 unsigned int versindex,
 			 const char *symname,
 			 struct module *mod, 
-			 const unsigned long *crc)
+			 const unsigned long *crc,
+			 const struct module *crc_owner)
 {
 	unsigned int i, num_versions;
 	struct modversion_info *versions;
@@ -905,10 +917,10 @@
 		if (strcmp(versions[i].name, symname) != 0)
 			continue;
 
-		if (versions[i].crc == *crc)
+		if (versions[i].crc == maybe_relocated(*crc, crc_owner))
 			return 1;
 		DEBUGP("Found checksum %lX vs module %lX\n",
-		       *crc, versions[i].crc);
+		       maybe_relocated(*crc, crc_owner), versions[i].crc);
 		goto bad_version;
 	}
 
@@ -931,7 +943,8 @@
 	if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
 			 &crc, true, false))
 		BUG();
-	return check_version(sechdrs, versindex, "module_layout", mod, crc);
+	return check_version(sechdrs, versindex, "module_layout", mod, crc,
+			     NULL);
 }
 
 /* First part is kernel version, which we ignore if module has crcs. */
@@ -949,7 +962,8 @@
 				unsigned int versindex,
 				const char *symname,
 				struct module *mod, 
-				const unsigned long *crc)
+				const unsigned long *crc,
+				const struct module *crc_owner)
 {
 	return 1;
 }
@@ -984,8 +998,8 @@
 	/* use_module can fail due to OOM,
 	   or module initialization or unloading */
 	if (sym) {
-		if (!check_version(sechdrs, versindex, name, mod, crc) ||
-		    !use_module(mod, owner))
+		if (!check_version(sechdrs, versindex, name, mod, crc, owner)
+		    || !use_module(mod, owner))
 			sym = NULL;
 	}
 	return sym;
@@ -1896,9 +1910,7 @@
 	unsigned int i;
 
 	/* only scan the sections containing data */
-	kmemleak_scan_area(mod->module_core, (unsigned long)mod -
-			   (unsigned long)mod->module_core,
-			   sizeof(struct module), GFP_KERNEL);
+	kmemleak_scan_area(mod, sizeof(struct module), GFP_KERNEL);
 
 	for (i = 1; i < hdr->e_shnum; i++) {
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -1907,8 +1919,7 @@
 		    && strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) != 0)
 			continue;
 
-		kmemleak_scan_area(mod->module_core, sechdrs[i].sh_addr -
-				   (unsigned long)mod->module_core,
+		kmemleak_scan_area((void *)sechdrs[i].sh_addr,
 				   sechdrs[i].sh_size, GFP_KERNEL);
 	}
 }
@@ -2236,6 +2247,12 @@
 					 "_ftrace_events",
 					 sizeof(*mod->trace_events),
 					 &mod->num_trace_events);
+	/*
+	 * This section contains pointers to allocated objects in the trace
+	 * code and not scanning it leads to false positives.
+	 */
+	kmemleak_scan_area(mod->trace_events, sizeof(*mod->trace_events) *
+			   mod->num_trace_events, GFP_KERNEL);
 #endif
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
 	/* sechdrs[0].sh_size is always zero */
diff --git a/kernel/panic.c b/kernel/panic.c
index 96b45d0..5827f7b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -10,6 +10,7 @@
  */
 #include <linux/debug_locks.h>
 #include <linux/interrupt.h>
+#include <linux/kmsg_dump.h>
 #include <linux/kallsyms.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
@@ -74,6 +75,7 @@
 	dump_stack();
 #endif
 
+	kmsg_dump(KMSG_DUMP_PANIC);
 	/*
 	 * If we have crashed and we have a crash kernel loaded let it handle
 	 * everything else.
@@ -339,6 +341,7 @@
 {
 	do_oops_enter_exit();
 	print_oops_end_marker();
+	kmsg_dump(KMSG_DUMP_OOPS);
 }
 
 #ifdef WANT_WARN_ON_SLOWPATH
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 9052d6c..8ab8698 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -782,6 +782,9 @@
 
 	add_event_to_ctx(event, ctx);
 
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		goto unlock;
+
 	/*
 	 * Don't put the event on if it is disabled or if
 	 * it is in a group and the group isn't on.
@@ -925,6 +928,9 @@
 		goto unlock;
 	__perf_event_mark_enabled(event, ctx);
 
+	if (event->cpu != -1 && event->cpu != smp_processor_id())
+		goto unlock;
+
 	/*
 	 * If the event is in a group and isn't the group leader,
 	 * then don't put it on unless the group is on.
@@ -1595,15 +1601,12 @@
 	unsigned long flags;
 	int err;
 
-	/*
-	 * If cpu is not a wildcard then this is a percpu event:
-	 */
-	if (cpu != -1) {
+	if (pid == -1 && cpu != -1) {
 		/* Must be root to operate on a CPU event: */
 		if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
 			return ERR_PTR(-EACCES);
 
-		if (cpu < 0 || cpu > num_possible_cpus())
+		if (cpu < 0 || cpu >= nr_cpumask_bits)
 			return ERR_PTR(-EINVAL);
 
 		/*
@@ -4564,7 +4567,7 @@
 	if (attr->type >= PERF_TYPE_MAX)
 		return -EINVAL;
 
-	if (attr->__reserved_1 || attr->__reserved_2 || attr->__reserved_3)
+	if (attr->__reserved_1 || attr->__reserved_2)
 		return -EINVAL;
 
 	if (attr->sample_type & ~(PERF_SAMPLE_MAX-1))
diff --git a/kernel/pid.c b/kernel/pid.c
index d3f722d..2e17c9c 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -141,11 +141,12 @@
 			 * installing it:
 			 */
 			spin_lock_irq(&pidmap_lock);
-			if (map->page)
-				kfree(page);
-			else
+			if (!map->page) {
 				map->page = page;
+				page = NULL;
+			}
 			spin_unlock_irq(&pidmap_lock);
+			kfree(page);
 			if (unlikely(!map->page))
 				break;
 		}
@@ -268,12 +269,11 @@
 	for (type = 0; type < PIDTYPE_MAX; ++type)
 		INIT_HLIST_HEAD(&pid->tasks[type]);
 
+	upid = pid->numbers + ns->level;
 	spin_lock_irq(&pidmap_lock);
-	for (i = ns->level; i >= 0; i--) {
-		upid = &pid->numbers[i];
+	for ( ; upid >= pid->numbers; --upid)
 		hlist_add_head_rcu(&upid->pid_chain,
 				&pid_hash[pid_hashfn(upid->nr, upid->ns)]);
-	}
 	spin_unlock_irq(&pidmap_lock);
 
 out:
diff --git a/kernel/printk.c b/kernel/printk.c
index b5ac4d9..17463ca 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -34,6 +34,7 @@
 #include <linux/syscalls.h>
 #include <linux/kexec.h>
 #include <linux/ratelimit.h>
+#include <linux/kmsg_dump.h>
 
 #include <asm/uaccess.h>
 
@@ -1405,4 +1406,122 @@
 	return false;
 }
 EXPORT_SYMBOL(printk_timed_ratelimit);
+
+static DEFINE_SPINLOCK(dump_list_lock);
+static LIST_HEAD(dump_list);
+
+/**
+ * kmsg_dump_register - register a kernel log dumper.
+ * @dumper: pointer to the kmsg_dumper structure
+ *
+ * Adds a kernel log dumper to the system. The dump callback in the
+ * structure will be called when the kernel oopses or panics and must be
+ * set. Returns zero on success and %-EINVAL or %-EBUSY otherwise.
+ */
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+	unsigned long flags;
+	int err = -EBUSY;
+
+	/* The dump callback needs to be set */
+	if (!dumper->dump)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dump_list_lock, flags);
+	/* Don't allow registering multiple times */
+	if (!dumper->registered) {
+		dumper->registered = 1;
+		list_add_tail(&dumper->list, &dump_list);
+		err = 0;
+	}
+	spin_unlock_irqrestore(&dump_list_lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_register);
+
+/**
+ * kmsg_dump_unregister - unregister a kmsg dumper.
+ * @dumper: pointer to the kmsg_dumper structure
+ *
+ * Removes a dump device from the system. Returns zero on success and
+ * %-EINVAL otherwise.
+ */
+int kmsg_dump_unregister(struct kmsg_dumper *dumper)
+{
+	unsigned long flags;
+	int err = -EINVAL;
+
+	spin_lock_irqsave(&dump_list_lock, flags);
+	if (dumper->registered) {
+		dumper->registered = 0;
+		list_del(&dumper->list);
+		err = 0;
+	}
+	spin_unlock_irqrestore(&dump_list_lock, flags);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
+
+static const char const *kmsg_reasons[] = {
+	[KMSG_DUMP_OOPS]	= "oops",
+	[KMSG_DUMP_PANIC]	= "panic",
+};
+
+static const char *kmsg_to_str(enum kmsg_dump_reason reason)
+{
+	if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0)
+		return "unknown";
+
+	return kmsg_reasons[reason];
+}
+
+/**
+ * kmsg_dump - dump kernel log to kernel message dumpers.
+ * @reason: the reason (oops, panic etc) for dumping
+ *
+ * Iterate through each of the dump devices and call the oops/panic
+ * callbacks with the log buffer.
+ */
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+	unsigned long end;
+	unsigned chars;
+	struct kmsg_dumper *dumper;
+	const char *s1, *s2;
+	unsigned long l1, l2;
+	unsigned long flags;
+
+	/* Theoretically, the log could move on after we do this, but
+	   there's not a lot we can do about that. The new messages
+	   will overwrite the start of what we dump. */
+	spin_lock_irqsave(&logbuf_lock, flags);
+	end = log_end & LOG_BUF_MASK;
+	chars = logged_chars;
+	spin_unlock_irqrestore(&logbuf_lock, flags);
+
+	if (logged_chars > end) {
+		s1 = log_buf + log_buf_len - logged_chars + end;
+		l1 = logged_chars - end;
+
+		s2 = log_buf;
+		l2 = end;
+	} else {
+		s1 = "";
+		l1 = 0;
+
+		s2 = log_buf + end - logged_chars;
+		l2 = logged_chars;
+	}
+
+	if (!spin_trylock_irqsave(&dump_list_lock, flags)) {
+		printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n",
+				kmsg_to_str(reason));
+		return;
+	}
+	list_for_each_entry(dumper, &dump_list, list)
+		dumper->dump(dumper, reason, s1, l1, s2, l2);
+	spin_unlock_irqrestore(&dump_list_lock, flags);
+}
 #endif
diff --git a/kernel/relay.c b/kernel/relay.c
index 760c262..c705a41 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1198,7 +1198,7 @@
 	relay_consume_bytes(rbuf, buf->private);
 }
 
-static struct pipe_buf_operations relay_pipe_buf_ops = {
+static const struct pipe_buf_operations relay_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
diff --git a/kernel/signal.c b/kernel/signal.c
index 6b982f2..1814e68 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -423,7 +423,7 @@
 		 */
 		info->si_signo = sig;
 		info->si_errno = 0;
-		info->si_code = 0;
+		info->si_code = SI_USER;
 		info->si_pid = 0;
 		info->si_uid = 0;
 	}
@@ -607,6 +607,17 @@
 	return 1;
 }
 
+static inline int is_si_special(const struct siginfo *info)
+{
+	return info <= SEND_SIG_FORCED;
+}
+
+static inline bool si_fromuser(const struct siginfo *info)
+{
+	return info == SEND_SIG_NOINFO ||
+		(!is_si_special(info) && SI_FROMUSER(info));
+}
+
 /*
  * Bad permissions for sending the signal
  * - the caller must hold at least the RCU read lock
@@ -621,7 +632,7 @@
 	if (!valid_signal(sig))
 		return -EINVAL;
 
-	if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
+	if (!si_fromuser(info))
 		return 0;
 
 	error = audit_signal_info(sig, t); /* Let audit system see the signal */
@@ -949,9 +960,8 @@
 	int from_ancestor_ns = 0;
 
 #ifdef CONFIG_PID_NS
-	if (!is_si_special(info) && SI_FROMUSER(info) &&
-			task_pid_nr_ns(current, task_active_pid_ns(t)) <= 0)
-		from_ancestor_ns = 1;
+	from_ancestor_ns = si_fromuser(info) &&
+			   !task_pid_nr_ns(current, task_active_pid_ns(t));
 #endif
 
 	return __send_signal(sig, info, t, group, from_ancestor_ns);
@@ -1052,12 +1062,6 @@
 	return ret;
 }
 
-void
-force_sig_specific(int sig, struct task_struct *t)
-{
-	force_sig_info(sig, SEND_SIG_FORCED, t);
-}
-
 /*
  * Nuke all other threads in the group.
  */
@@ -1186,8 +1190,7 @@
 		goto out_unlock;
 	}
 	pcred = __task_cred(p);
-	if ((info == SEND_SIG_NOINFO ||
-	     (!is_si_special(info) && SI_FROMUSER(info))) &&
+	if (si_fromuser(info) &&
 	    euid != pcred->suid && euid != pcred->uid &&
 	    uid  != pcred->suid && uid  != pcred->uid) {
 		ret = -EPERM;
@@ -1837,11 +1840,6 @@
 
 	for (;;) {
 		struct k_sigaction *ka;
-
-		if (unlikely(signal->group_stop_count > 0) &&
-		    do_signal_stop(0))
-			goto relock;
-
 		/*
 		 * Tracing can induce an artifical signal and choose sigaction.
 		 * The return value in @signr determines the default action,
@@ -1853,6 +1851,10 @@
 		if (unlikely(signr != 0))
 			ka = return_ka;
 		else {
+			if (unlikely(signal->group_stop_count > 0) &&
+			    do_signal_stop(0))
+				goto relock;
+
 			signr = dequeue_signal(current, &current->blocked,
 					       info);
 
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 45e4bef..6665761 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1131,7 +1131,7 @@
 		.data		= &sysctl_max_map_count,
 		.maxlen		= sizeof(sysctl_max_map_count),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= &zero,
 	},
 #else
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index b75dbf4..112533d 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1399,6 +1399,13 @@
 {
 	int i;
 
+	/*
+	 * CTL_KERN/KERN_VERSION is used by older glibc and cannot
+	 * ever go away.
+	 */
+	if (name[0] == CTL_KERN && name[1] == KERN_VERSION)
+		return;
+
 	if (printk_ratelimit()) {
 		printk(KERN_INFO
 			"warning: process `%s' used the deprecated sysctl "
diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
index 96ff643..12f5c55 100644
--- a/kernel/time/timecompare.c
+++ b/kernel/time/timecompare.c
@@ -89,7 +89,7 @@
 			 * source time
 			 */
 			sample.offset =
-				ktime_to_ns(ktime_add(end, start)) / 2 -
+				(ktime_to_ns(end) + ktime_to_ns(start)) / 2 -
 				ts;
 
 			/* simple insertion sort based on duration */
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index e51a1bc..7968762 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1724,7 +1724,7 @@
 	return ftrace_match(str, regex, len, type);
 }
 
-static void ftrace_match_records(char *buff, int len, int enable)
+static int ftrace_match_records(char *buff, int len, int enable)
 {
 	unsigned int search_len;
 	struct ftrace_page *pg;
@@ -1733,6 +1733,7 @@
 	char *search;
 	int type;
 	int not;
+	int found = 0;
 
 	flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
 	type = filter_parse_regex(buff, len, &search, &not);
@@ -1750,6 +1751,7 @@
 				rec->flags &= ~flag;
 			else
 				rec->flags |= flag;
+			found = 1;
 		}
 		/*
 		 * Only enable filtering if we have a function that
@@ -1759,6 +1761,8 @@
 			ftrace_filtered = 1;
 	} while_for_each_ftrace_rec();
 	mutex_unlock(&ftrace_lock);
+
+	return found;
 }
 
 static int
@@ -1780,7 +1784,7 @@
 		return 1;
 }
 
-static void ftrace_match_module_records(char *buff, char *mod, int enable)
+static int ftrace_match_module_records(char *buff, char *mod, int enable)
 {
 	unsigned search_len = 0;
 	struct ftrace_page *pg;
@@ -1789,6 +1793,7 @@
 	char *search = buff;
 	unsigned long flag;
 	int not = 0;
+	int found = 0;
 
 	flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
 
@@ -1819,12 +1824,15 @@
 				rec->flags &= ~flag;
 			else
 				rec->flags |= flag;
+			found = 1;
 		}
 		if (enable && (rec->flags & FTRACE_FL_FILTER))
 			ftrace_filtered = 1;
 
 	} while_for_each_ftrace_rec();
 	mutex_unlock(&ftrace_lock);
+
+	return found;
 }
 
 /*
@@ -1853,8 +1861,9 @@
 	if (!strlen(mod))
 		return -EINVAL;
 
-	ftrace_match_module_records(func, mod, enable);
-	return 0;
+	if (ftrace_match_module_records(func, mod, enable))
+		return 0;
+	return -EINVAL;
 }
 
 static struct ftrace_func_command ftrace_mod_cmd = {
@@ -2151,8 +2160,9 @@
 	func = strsep(&next, ":");
 
 	if (!next) {
-		ftrace_match_records(func, len, enable);
-		return 0;
+		if (ftrace_match_records(func, len, enable))
+			return 0;
+		return ret;
 	}
 
 	/* command found */
@@ -2198,10 +2208,9 @@
 	    !trace_parser_cont(parser)) {
 		ret = ftrace_process_regex(parser->buffer,
 					   parser->idx, enable);
+		trace_parser_clear(parser);
 		if (ret)
 			goto out_unlock;
-
-		trace_parser_clear(parser);
 	}
 
 	ret = read;
@@ -2543,10 +2552,9 @@
 					exists = true;
 					break;
 				}
-			if (!exists) {
+			if (!exists)
 				array[(*idx)++] = rec->ip;
-				found = 1;
-			}
+			found = 1;
 		}
 	} while_for_each_ftrace_rec();
 
diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c
index e06c6e3..9f4f565 100644
--- a/kernel/trace/power-traces.c
+++ b/kernel/trace/power-traces.c
@@ -14,7 +14,5 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/power.h>
 
-EXPORT_TRACEPOINT_SYMBOL_GPL(power_start);
-EXPORT_TRACEPOINT_SYMBOL_GPL(power_end);
 EXPORT_TRACEPOINT_SYMBOL_GPL(power_frequency);
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f58c9ad..2326b04 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -1193,9 +1193,6 @@
 	struct list_head *p;
 	unsigned i;
 
-	atomic_inc(&cpu_buffer->record_disabled);
-	synchronize_sched();
-
 	spin_lock_irq(&cpu_buffer->reader_lock);
 	rb_head_page_deactivate(cpu_buffer);
 
@@ -1211,12 +1208,9 @@
 		return;
 
 	rb_reset_cpu(cpu_buffer);
-	spin_unlock_irq(&cpu_buffer->reader_lock);
-
 	rb_check_pages(cpu_buffer);
 
-	atomic_dec(&cpu_buffer->record_disabled);
-
+	spin_unlock_irq(&cpu_buffer->reader_lock);
 }
 
 static void
@@ -1227,9 +1221,6 @@
 	struct list_head *p;
 	unsigned i;
 
-	atomic_inc(&cpu_buffer->record_disabled);
-	synchronize_sched();
-
 	spin_lock_irq(&cpu_buffer->reader_lock);
 	rb_head_page_deactivate(cpu_buffer);
 
@@ -1242,11 +1233,9 @@
 		list_add_tail(&bpage->list, cpu_buffer->pages);
 	}
 	rb_reset_cpu(cpu_buffer);
-	spin_unlock_irq(&cpu_buffer->reader_lock);
-
 	rb_check_pages(cpu_buffer);
 
-	atomic_dec(&cpu_buffer->record_disabled);
+	spin_unlock_irq(&cpu_buffer->reader_lock);
 }
 
 /**
@@ -1254,11 +1243,6 @@
  * @buffer: the buffer to resize.
  * @size: the new size.
  *
- * The tracer is responsible for making sure that the buffer is
- * not being used while changing the size.
- * Note: We may be able to change the above requirement by using
- *  RCU synchronizations.
- *
  * Minimum size is 2 * BUF_PAGE_SIZE.
  *
  * Returns -1 on failure.
@@ -1290,6 +1274,11 @@
 	if (size == buffer_size)
 		return size;
 
+	atomic_inc(&buffer->record_disabled);
+
+	/* Make sure all writers are done with this buffer. */
+	synchronize_sched();
+
 	mutex_lock(&buffer->mutex);
 	get_online_cpus();
 
@@ -1352,6 +1341,8 @@
 	put_online_cpus();
 	mutex_unlock(&buffer->mutex);
 
+	atomic_dec(&buffer->record_disabled);
+
 	return size;
 
  free_pages:
@@ -1361,6 +1352,7 @@
 	}
 	put_online_cpus();
 	mutex_unlock(&buffer->mutex);
+	atomic_dec(&buffer->record_disabled);
 	return -ENOMEM;
 
 	/*
@@ -1370,6 +1362,7 @@
  out_fail:
 	put_online_cpus();
 	mutex_unlock(&buffer->mutex);
+	atomic_dec(&buffer->record_disabled);
 	return -1;
 }
 EXPORT_SYMBOL_GPL(ring_buffer_resize);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index bb6b5e7..8b9f20a 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -12,7 +12,7 @@
  *  Copyright (C) 2004 William Lee Irwin III
  */
 #include <linux/ring_buffer.h>
-#include <linux/utsrelease.h>
+#include <generated/utsrelease.h>
 #include <linux/stacktrace.h>
 #include <linux/writeback.h>
 #include <linux/kallsyms.h>
@@ -313,7 +313,6 @@
 	"bin",
 	"block",
 	"stacktrace",
-	"sched-tree",
 	"trace_printk",
 	"ftrace_preempt",
 	"branch",
@@ -1151,6 +1150,22 @@
 	__ftrace_trace_stack(tr->buffer, flags, skip, pc);
 }
 
+/**
+ * trace_dump_stack - record a stack back trace in the trace buffer
+ */
+void trace_dump_stack(void)
+{
+	unsigned long flags;
+
+	if (tracing_disabled || tracing_selftest_running)
+		return;
+
+	local_save_flags(flags);
+
+	/* skipping 3 traces, seems to get us at the caller of this function */
+	__ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());
+}
+
 void
 ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
 {
@@ -2316,92 +2331,41 @@
 	.write		= tracing_cpumask_write,
 };
 
-static ssize_t
-tracing_trace_options_read(struct file *filp, char __user *ubuf,
-		       size_t cnt, loff_t *ppos)
+static int tracing_trace_options_show(struct seq_file *m, void *v)
 {
 	struct tracer_opt *trace_opts;
 	u32 tracer_flags;
-	int len = 0;
-	char *buf;
-	int r = 0;
 	int i;
 
-
-	/* calculate max size */
-	for (i = 0; trace_options[i]; i++) {
-		len += strlen(trace_options[i]);
-		len += 3; /* "no" and newline */
-	}
-
 	mutex_lock(&trace_types_lock);
 	tracer_flags = current_trace->flags->val;
 	trace_opts = current_trace->flags->opts;
 
-	/*
-	 * Increase the size with names of options specific
-	 * of the current tracer.
-	 */
-	for (i = 0; trace_opts[i].name; i++) {
-		len += strlen(trace_opts[i].name);
-		len += 3; /* "no" and newline */
-	}
-
-	/* +1 for \0 */
-	buf = kmalloc(len + 1, GFP_KERNEL);
-	if (!buf) {
-		mutex_unlock(&trace_types_lock);
-		return -ENOMEM;
-	}
-
 	for (i = 0; trace_options[i]; i++) {
 		if (trace_flags & (1 << i))
-			r += sprintf(buf + r, "%s\n", trace_options[i]);
+			seq_printf(m, "%s\n", trace_options[i]);
 		else
-			r += sprintf(buf + r, "no%s\n", trace_options[i]);
+			seq_printf(m, "no%s\n", trace_options[i]);
 	}
 
 	for (i = 0; trace_opts[i].name; i++) {
 		if (tracer_flags & trace_opts[i].bit)
-			r += sprintf(buf + r, "%s\n",
-				trace_opts[i].name);
+			seq_printf(m, "%s\n", trace_opts[i].name);
 		else
-			r += sprintf(buf + r, "no%s\n",
-				trace_opts[i].name);
+			seq_printf(m, "no%s\n", trace_opts[i].name);
 	}
 	mutex_unlock(&trace_types_lock);
 
-	WARN_ON(r >= len + 1);
-
-	r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
-
-	kfree(buf);
-	return r;
+	return 0;
 }
 
-/* Try to assign a tracer specific option */
-static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
+static int __set_tracer_option(struct tracer *trace,
+			       struct tracer_flags *tracer_flags,
+			       struct tracer_opt *opts, int neg)
 {
-	struct tracer_flags *tracer_flags = trace->flags;
-	struct tracer_opt *opts = NULL;
-	int ret = 0, i = 0;
-	int len;
+	int ret;
 
-	for (i = 0; tracer_flags->opts[i].name; i++) {
-		opts = &tracer_flags->opts[i];
-		len = strlen(opts->name);
-
-		if (strncmp(cmp, opts->name, len) == 0) {
-			ret = trace->set_flag(tracer_flags->val,
-				opts->bit, !neg);
-			break;
-		}
-	}
-	/* Not found */
-	if (!tracer_flags->opts[i].name)
-		return -EINVAL;
-
-	/* Refused to handle */
+	ret = trace->set_flag(tracer_flags->val, opts->bit, !neg);
 	if (ret)
 		return ret;
 
@@ -2409,10 +2373,27 @@
 		tracer_flags->val &= ~opts->bit;
 	else
 		tracer_flags->val |= opts->bit;
-
 	return 0;
 }
 
+/* Try to assign a tracer specific option */
+static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
+{
+	struct tracer_flags *tracer_flags = trace->flags;
+	struct tracer_opt *opts = NULL;
+	int i;
+
+	for (i = 0; tracer_flags->opts[i].name; i++) {
+		opts = &tracer_flags->opts[i];
+
+		if (strcmp(cmp, opts->name) == 0)
+			return __set_tracer_option(trace, trace->flags,
+						   opts, neg);
+	}
+
+	return -EINVAL;
+}
+
 static void set_tracer_flags(unsigned int mask, int enabled)
 {
 	/* do nothing if flag is already set */
@@ -2430,7 +2411,7 @@
 			size_t cnt, loff_t *ppos)
 {
 	char buf[64];
-	char *cmp = buf;
+	char *cmp;
 	int neg = 0;
 	int ret;
 	int i;
@@ -2442,16 +2423,15 @@
 		return -EFAULT;
 
 	buf[cnt] = 0;
+	cmp = strstrip(buf);
 
-	if (strncmp(buf, "no", 2) == 0) {
+	if (strncmp(cmp, "no", 2) == 0) {
 		neg = 1;
 		cmp += 2;
 	}
 
 	for (i = 0; trace_options[i]; i++) {
-		int len = strlen(trace_options[i]);
-
-		if (strncmp(cmp, trace_options[i], len) == 0) {
+		if (strcmp(cmp, trace_options[i]) == 0) {
 			set_tracer_flags(1 << i, !neg);
 			break;
 		}
@@ -2471,9 +2451,18 @@
 	return cnt;
 }
 
+static int tracing_trace_options_open(struct inode *inode, struct file *file)
+{
+	if (tracing_disabled)
+		return -ENODEV;
+	return single_open(file, tracing_trace_options_show, NULL);
+}
+
 static const struct file_operations tracing_iter_fops = {
-	.open		= tracing_open_generic,
-	.read		= tracing_trace_options_read,
+	.open		= tracing_trace_options_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
 	.write		= tracing_trace_options_write,
 };
 
@@ -3133,7 +3122,7 @@
 	__free_page(spd->pages[idx]);
 }
 
-static struct pipe_buf_operations tracing_pipe_buf_ops = {
+static const struct pipe_buf_operations tracing_pipe_buf_ops = {
 	.can_merge		= 0,
 	.map			= generic_pipe_buf_map,
 	.unmap			= generic_pipe_buf_unmap,
@@ -3392,21 +3381,18 @@
 	return cnt;
 }
 
-static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf,
-				  size_t cnt, loff_t *ppos)
+static int tracing_clock_show(struct seq_file *m, void *v)
 {
-	char buf[64];
-	int bufiter = 0;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(trace_clocks); i++)
-		bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter,
+		seq_printf(m,
 			"%s%s%s%s", i ? " " : "",
 			i == trace_clock_id ? "[" : "", trace_clocks[i].name,
 			i == trace_clock_id ? "]" : "");
-	bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, "\n");
+	seq_putc(m, '\n');
 
-	return simple_read_from_buffer(ubuf, cnt, ppos, buf, bufiter);
+	return 0;
 }
 
 static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
@@ -3448,6 +3434,13 @@
 	return cnt;
 }
 
+static int tracing_clock_open(struct inode *inode, struct file *file)
+{
+	if (tracing_disabled)
+		return -ENODEV;
+	return single_open(file, tracing_clock_show, NULL);
+}
+
 static const struct file_operations tracing_max_lat_fops = {
 	.open		= tracing_open_generic,
 	.read		= tracing_max_lat_read,
@@ -3486,8 +3479,10 @@
 };
 
 static const struct file_operations trace_clock_fops = {
-	.open		= tracing_open_generic,
-	.read		= tracing_clock_read,
+	.open		= tracing_clock_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
 	.write		= tracing_clock_write,
 };
 
@@ -3617,7 +3612,7 @@
 }
 
 /* Pipe buffer operations for a buffer. */
-static struct pipe_buf_operations buffer_pipe_buf_ops = {
+static const struct pipe_buf_operations buffer_pipe_buf_ops = {
 	.can_merge		= 0,
 	.map			= generic_pipe_buf_map,
 	.unmap			= generic_pipe_buf_unmap,
@@ -3948,39 +3943,16 @@
 	if (ret < 0)
 		return ret;
 
-	ret = 0;
-	switch (val) {
-	case 0:
-		/* do nothing if already cleared */
-		if (!(topt->flags->val & topt->opt->bit))
-			break;
-
-		mutex_lock(&trace_types_lock);
-		if (current_trace->set_flag)
-			ret = current_trace->set_flag(topt->flags->val,
-						      topt->opt->bit, 0);
-		mutex_unlock(&trace_types_lock);
-		if (ret)
-			return ret;
-		topt->flags->val &= ~topt->opt->bit;
-		break;
-	case 1:
-		/* do nothing if already set */
-		if (topt->flags->val & topt->opt->bit)
-			break;
-
-		mutex_lock(&trace_types_lock);
-		if (current_trace->set_flag)
-			ret = current_trace->set_flag(topt->flags->val,
-						      topt->opt->bit, 1);
-		mutex_unlock(&trace_types_lock);
-		if (ret)
-			return ret;
-		topt->flags->val |= topt->opt->bit;
-		break;
-
-	default:
+	if (val != 0 && val != 1)
 		return -EINVAL;
+
+	if (!!(topt->flags->val & topt->opt->bit) != val) {
+		mutex_lock(&trace_types_lock);
+		ret = __set_tracer_option(current_trace, topt->flags,
+					  topt->opt, val);
+		mutex_unlock(&trace_types_lock);
+		if (ret)
+			return ret;
 	}
 
 	*ppos += cnt;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index a52bed2..4df6a77 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -597,18 +597,17 @@
 	TRACE_ITER_BIN			= 0x40,
 	TRACE_ITER_BLOCK		= 0x80,
 	TRACE_ITER_STACKTRACE		= 0x100,
-	TRACE_ITER_SCHED_TREE		= 0x200,
-	TRACE_ITER_PRINTK		= 0x400,
-	TRACE_ITER_PREEMPTONLY		= 0x800,
-	TRACE_ITER_BRANCH		= 0x1000,
-	TRACE_ITER_ANNOTATE		= 0x2000,
-	TRACE_ITER_USERSTACKTRACE       = 0x4000,
-	TRACE_ITER_SYM_USEROBJ          = 0x8000,
-	TRACE_ITER_PRINTK_MSGONLY	= 0x10000,
-	TRACE_ITER_CONTEXT_INFO		= 0x20000, /* Print pid/cpu/time */
-	TRACE_ITER_LATENCY_FMT		= 0x40000,
-	TRACE_ITER_SLEEP_TIME		= 0x80000,
-	TRACE_ITER_GRAPH_TIME		= 0x100000,
+	TRACE_ITER_PRINTK		= 0x200,
+	TRACE_ITER_PREEMPTONLY		= 0x400,
+	TRACE_ITER_BRANCH		= 0x800,
+	TRACE_ITER_ANNOTATE		= 0x1000,
+	TRACE_ITER_USERSTACKTRACE       = 0x2000,
+	TRACE_ITER_SYM_USEROBJ          = 0x4000,
+	TRACE_ITER_PRINTK_MSGONLY	= 0x8000,
+	TRACE_ITER_CONTEXT_INFO		= 0x10000, /* Print pid/cpu/time */
+	TRACE_ITER_LATENCY_FMT		= 0x20000,
+	TRACE_ITER_SLEEP_TIME		= 0x40000,
+	TRACE_ITER_GRAPH_TIME		= 0x80000,
 };
 
 /*
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index d9c60f8..9e25573 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -25,7 +25,7 @@
 	char *buf;
 	int ret = -ENOMEM;
 
-	if (atomic_inc_return(&event->profile_count))
+	if (event->profile_count++ > 0)
 		return 0;
 
 	if (!total_profile_count) {
@@ -56,7 +56,7 @@
 		perf_trace_buf = NULL;
 	}
 fail_buf:
-	atomic_dec(&event->profile_count);
+	event->profile_count--;
 
 	return ret;
 }
@@ -83,7 +83,7 @@
 {
 	char *buf, *nmi_buf;
 
-	if (!atomic_add_negative(-1, &event->profile_count))
+	if (--event->profile_count > 0)
 		return;
 
 	event->profile_disable(event);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 1d18315..189b09b 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -78,7 +78,7 @@
 	if (ret)							\
 		return ret;
 
-int trace_define_common_fields(struct ftrace_event_call *call)
+static int trace_define_common_fields(struct ftrace_event_call *call)
 {
 	int ret;
 	struct trace_entry ent;
@@ -91,7 +91,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(trace_define_common_fields);
 
 void trace_destroy_fields(struct ftrace_event_call *call)
 {
@@ -105,9 +104,25 @@
 	}
 }
 
-static void ftrace_event_enable_disable(struct ftrace_event_call *call,
+int trace_event_raw_init(struct ftrace_event_call *call)
+{
+	int id;
+
+	id = register_ftrace_event(call->event);
+	if (!id)
+		return -ENODEV;
+	call->id = id;
+	INIT_LIST_HEAD(&call->fields);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(trace_event_raw_init);
+
+static int ftrace_event_enable_disable(struct ftrace_event_call *call,
 					int enable)
 {
+	int ret = 0;
+
 	switch (enable) {
 	case 0:
 		if (call->enabled) {
@@ -118,12 +133,20 @@
 		break;
 	case 1:
 		if (!call->enabled) {
-			call->enabled = 1;
 			tracing_start_cmdline_record();
-			call->regfunc(call);
+			ret = call->regfunc(call);
+			if (ret) {
+				tracing_stop_cmdline_record();
+				pr_info("event trace: Could not enable event "
+					"%s\n", call->name);
+				break;
+			}
+			call->enabled = 1;
 		}
 		break;
 	}
+
+	return ret;
 }
 
 static void ftrace_clear_events(void)
@@ -402,7 +425,7 @@
 	case 0:
 	case 1:
 		mutex_lock(&event_mutex);
-		ftrace_event_enable_disable(call, val);
+		ret = ftrace_event_enable_disable(call, val);
 		mutex_unlock(&event_mutex);
 		break;
 
@@ -412,7 +435,7 @@
 
 	*ppos += cnt;
 
-	return cnt;
+	return ret ? ret : cnt;
 }
 
 static ssize_t
@@ -913,7 +936,9 @@
 		 		  id);
 
 	if (call->define_fields) {
-		ret = call->define_fields(call);
+		ret = trace_define_common_fields(call);
+		if (!ret)
+			ret = call->define_fields(call);
 		if (ret < 0) {
 			pr_warning("Could not initialize trace point"
 				   " events/%s\n", call->name);
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index dff8c84..458e5bf 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -184,10 +184,6 @@
 	struct struct_name field;					\
 	int ret;							\
 									\
-	ret = trace_define_common_fields(event_call);			\
-	if (ret)							\
-		return ret;						\
-									\
 	tstruct;							\
 									\
 	return ret;							\
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 3aa7eaa..2974bc7 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -151,6 +151,8 @@
 		goto out_unlock;
 
 	trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc);
+	/* Skip 5 functions to get to the irq/preempt enable function */
+	__trace_stack(tr, flags, 5, pc);
 
 	if (data->critical_sequence != max_sequence)
 		goto out_unlock;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index b52d397..7ecab06 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1132,10 +1132,6 @@
 	struct kprobe_trace_entry field;
 	struct trace_probe *tp = (struct trace_probe *)event_call->data;
 
-	ret = trace_define_common_fields(event_call);
-	if (ret)
-		return ret;
-
 	DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
 	DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
 	/* Set argument names as fields */
@@ -1150,10 +1146,6 @@
 	struct kretprobe_trace_entry field;
 	struct trace_probe *tp = (struct trace_probe *)event_call->data;
 
-	ret = trace_define_common_fields(event_call);
-	if (ret)
-		return ret;
-
 	DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
 	DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
 	DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1);
@@ -1453,7 +1445,6 @@
 	call->unregfunc = probe_event_disable;
 
 #ifdef CONFIG_EVENT_PROFILE
-	atomic_set(&call->profile_count, -1);
 	call->profile_enable = probe_profile_enable;
 	call->profile_disable = probe_profile_disable;
 #endif
diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c
index acb87d4..faf37fa 100644
--- a/kernel/trace/trace_ksym.c
+++ b/kernel/trace/trace_ksym.c
@@ -236,7 +236,8 @@
 	mutex_lock(&ksym_tracer_mutex);
 
 	hlist_for_each_entry(entry, node, &ksym_filter_head, ksym_hlist) {
-		ret = trace_seq_printf(s, "%pS:", (void *)entry->attr.bp_addr);
+		ret = trace_seq_printf(s, "%pS:",
+				(void *)(unsigned long)entry->attr.bp_addr);
 		if (entry->attr.bp_type == HW_BREAKPOINT_R)
 			ret = trace_seq_puts(s, "r--\n");
 		else if (entry->attr.bp_type == HW_BREAKPOINT_W)
@@ -278,21 +279,20 @@
 {
 	struct trace_ksym *entry;
 	struct hlist_node *node;
-	char *input_string, *ksymname = NULL;
+	char *buf, *input_string, *ksymname = NULL;
 	unsigned long ksym_addr = 0;
 	int ret, op, changed = 0;
 
-	input_string = kzalloc(count + 1, GFP_KERNEL);
-	if (!input_string)
+	buf = kzalloc(count + 1, GFP_KERNEL);
+	if (!buf)
 		return -ENOMEM;
 
-	if (copy_from_user(input_string, buffer, count)) {
-		kfree(input_string);
-		return -EFAULT;
-	}
-	input_string[count] = '\0';
+	ret = -EFAULT;
+	if (copy_from_user(buf, buffer, count))
+		goto out;
 
-	strstrip(input_string);
+	buf[count] = '\0';
+	input_string = strstrip(buf);
 
 	/*
 	 * Clear all breakpoints if:
@@ -300,18 +300,16 @@
 	 * 2: echo 0 > ksym_trace_filter
 	 * 3: echo "*:---" > ksym_trace_filter
 	 */
-	if (!input_string[0] || !strcmp(input_string, "0") ||
-	    !strcmp(input_string, "*:---")) {
+	if (!buf[0] || !strcmp(buf, "0") ||
+	    !strcmp(buf, "*:---")) {
 		__ksym_trace_reset();
-		kfree(input_string);
-		return count;
+		ret = 0;
+		goto out;
 	}
 
 	ret = op = parse_ksym_trace_str(input_string, &ksymname, &ksym_addr);
-	if (ret < 0) {
-		kfree(input_string);
-		return ret;
-	}
+	if (ret < 0)
+		goto out;
 
 	mutex_lock(&ksym_tracer_mutex);
 
@@ -322,7 +320,7 @@
 			if (entry->attr.bp_type != op)
 				changed = 1;
 			else
-				goto out;
+				goto out_unlock;
 			break;
 		}
 	}
@@ -337,28 +335,24 @@
 			if (IS_ERR(entry->ksym_hbp))
 				ret = PTR_ERR(entry->ksym_hbp);
 			else
-				goto out;
+				goto out_unlock;
 		}
 		/* Error or "symbol:---" case: drop it */
 		ksym_filter_entry_count--;
 		hlist_del_rcu(&(entry->ksym_hlist));
 		synchronize_rcu();
 		kfree(entry);
-		goto out;
+		goto out_unlock;
 	} else {
 		/* Check for malformed request: (4) */
-		if (op == 0)
-			goto out;
-		ret = process_new_ksym_entry(ksymname, op, ksym_addr);
+		if (op)
+			ret = process_new_ksym_entry(ksymname, op, ksym_addr);
 	}
-out:
+out_unlock:
 	mutex_unlock(&ksym_tracer_mutex);
-
-	kfree(input_string);
-
-	if (!ret)
-		ret = count;
-	return ret;
+out:
+	kfree(buf);
+	return !ret ? count : ret;
 }
 
 static const struct file_operations ksym_tracing_fops = {
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 57501d9..75289f3 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -217,10 +217,6 @@
 	int i;
 	int offset = offsetof(typeof(trace), args);
 
-	ret = trace_define_common_fields(call);
-	if (ret)
-		return ret;
-
 	ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
 	if (ret)
 		return ret;
@@ -241,10 +237,6 @@
 	struct syscall_trace_exit trace;
 	int ret;
 
-	ret = trace_define_common_fields(call);
-	if (ret)
-		return ret;
-
 	ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
 	if (ret)
 		return ret;
@@ -333,10 +325,7 @@
 	mutex_lock(&syscall_trace_lock);
 	if (!sys_refcount_enter)
 		ret = register_trace_sys_enter(ftrace_syscall_enter);
-	if (ret) {
-		pr_info("event trace: Could not activate"
-				"syscall entry trace point");
-	} else {
+	if (!ret) {
 		set_bit(num, enabled_enter_syscalls);
 		sys_refcount_enter++;
 	}
@@ -370,10 +359,7 @@
 	mutex_lock(&syscall_trace_lock);
 	if (!sys_refcount_exit)
 		ret = register_trace_sys_exit(ftrace_syscall_exit);
-	if (ret) {
-		pr_info("event trace: Could not activate"
-				"syscall exit trace point");
-	} else {
+	if (!ret) {
 		set_bit(num, enabled_exit_syscalls);
 		sys_refcount_exit++;
 	}
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 8cf9938..25c3ed5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -360,6 +360,7 @@
 	select DEBUG_FS if SYSFS
 	select STACKTRACE if STACKTRACE_SUPPORT
 	select KALLSYMS
+	select CRC32
 	help
 	  Say Y here if you want to enable the memory leak
 	  detector. The memory allocation/freeing is traced in a way
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 7025658..11bf497 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -271,6 +271,87 @@
 }
 EXPORT_SYMBOL(__bitmap_weight);
 
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
+
+void bitmap_set(unsigned long *map, int start, int nr)
+{
+	unsigned long *p = map + BIT_WORD(start);
+	const int size = start + nr;
+	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
+	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
+
+	while (nr - bits_to_set >= 0) {
+		*p |= mask_to_set;
+		nr -= bits_to_set;
+		bits_to_set = BITS_PER_LONG;
+		mask_to_set = ~0UL;
+		p++;
+	}
+	if (nr) {
+		mask_to_set &= BITMAP_LAST_WORD_MASK(size);
+		*p |= mask_to_set;
+	}
+}
+EXPORT_SYMBOL(bitmap_set);
+
+void bitmap_clear(unsigned long *map, int start, int nr)
+{
+	unsigned long *p = map + BIT_WORD(start);
+	const int size = start + nr;
+	int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
+	unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
+
+	while (nr - bits_to_clear >= 0) {
+		*p &= ~mask_to_clear;
+		nr -= bits_to_clear;
+		bits_to_clear = BITS_PER_LONG;
+		mask_to_clear = ~0UL;
+		p++;
+	}
+	if (nr) {
+		mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
+		*p &= ~mask_to_clear;
+	}
+}
+EXPORT_SYMBOL(bitmap_clear);
+
+/*
+ * bitmap_find_next_zero_area - find a contiguous aligned zero area
+ * @map: The address to base the search on
+ * @size: The bitmap size in bits
+ * @start: The bitnumber to start searching at
+ * @nr: The number of zeroed bits we're looking for
+ * @align_mask: Alignment mask for zero area
+ *
+ * The @align_mask should be one less than a power of 2; the effect is that
+ * the bit offset of all zero areas this function finds is multiples of that
+ * power of 2. A @align_mask of 0 means no alignment is required.
+ */
+unsigned long bitmap_find_next_zero_area(unsigned long *map,
+					 unsigned long size,
+					 unsigned long start,
+					 unsigned int nr,
+					 unsigned long align_mask)
+{
+	unsigned long index, end, i;
+again:
+	index = find_next_zero_bit(map, size, start);
+
+	/* Align allocation */
+	index = __ALIGN_MASK(index, align_mask);
+
+	end = index + nr;
+	if (end > size)
+		return end;
+	i = find_next_bit(map, end, index);
+	if (i < end) {
+		start = i + 1;
+		goto again;
+	}
+	return index;
+}
+EXPORT_SYMBOL(bitmap_find_next_zero_area);
+
 /*
  * Bitmap printing & parsing functions: first version by Bill Irwin,
  * second version by Paul Jackson, third by Joe Korty.
diff --git a/lib/genalloc.c b/lib/genalloc.c
index eed2bdb..e67f974 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/bitmap.h>
 #include <linux/genalloc.h>
 
 
@@ -114,7 +115,7 @@
 	struct gen_pool_chunk *chunk;
 	unsigned long addr, flags;
 	int order = pool->min_alloc_order;
-	int nbits, bit, start_bit, end_bit;
+	int nbits, start_bit, end_bit;
 
 	if (size == 0)
 		return 0;
@@ -129,29 +130,19 @@
 		end_bit -= nbits + 1;
 
 		spin_lock_irqsave(&chunk->lock, flags);
-		bit = -1;
-		while (bit + 1 < end_bit) {
-			bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1);
-			if (bit >= end_bit)
-				break;
-
-			start_bit = bit;
-			if (nbits > 1) {
-				bit = find_next_bit(chunk->bits, bit + nbits,
-							bit + 1);
-				if (bit - start_bit < nbits)
-					continue;
-			}
-
-			addr = chunk->start_addr +
-					    ((unsigned long)start_bit << order);
-			while (nbits--)
-				__set_bit(start_bit++, chunk->bits);
+		start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
+						nbits, 0);
+		if (start_bit >= end_bit) {
 			spin_unlock_irqrestore(&chunk->lock, flags);
-			read_unlock(&pool->lock);
-			return addr;
+			continue;
 		}
+
+		addr = chunk->start_addr + ((unsigned long)start_bit << order);
+
+		bitmap_set(chunk->bits, start_bit, nbits);
 		spin_unlock_irqrestore(&chunk->lock, flags);
+		read_unlock(&pool->lock);
+		return addr;
 	}
 	read_unlock(&pool->lock);
 	return 0;
diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c
index 75dbda0..c0251f4 100644
--- a/lib/iommu-helper.c
+++ b/lib/iommu-helper.c
@@ -3,41 +3,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/bitops.h>
-
-static unsigned long find_next_zero_area(unsigned long *map,
-					 unsigned long size,
-					 unsigned long start,
-					 unsigned int nr,
-					 unsigned long align_mask)
-{
-	unsigned long index, end, i;
-again:
-	index = find_next_zero_bit(map, size, start);
-
-	/* Align allocation */
-	index = (index + align_mask) & ~align_mask;
-
-	end = index + nr;
-	if (end >= size)
-		return -1;
-	for (i = index; i < end; i++) {
-		if (test_bit(i, map)) {
-			start = i+1;
-			goto again;
-		}
-	}
-	return index;
-}
-
-void iommu_area_reserve(unsigned long *map, unsigned long i, int len)
-{
-	unsigned long end = i + len;
-	while (i < end) {
-		__set_bit(i, map);
-		i++;
-	}
-}
+#include <linux/bitmap.h>
 
 int iommu_is_span_boundary(unsigned int index, unsigned int nr,
 			   unsigned long shift,
@@ -55,31 +21,24 @@
 			       unsigned long align_mask)
 {
 	unsigned long index;
+
+	/* We don't want the last of the limit */
+	size -= 1;
 again:
-	index = find_next_zero_area(map, size, start, nr, align_mask);
-	if (index != -1) {
+	index = bitmap_find_next_zero_area(map, size, start, nr, align_mask);
+	if (index < size) {
 		if (iommu_is_span_boundary(index, nr, shift, boundary_size)) {
 			/* we could do more effectively */
 			start = index + 1;
 			goto again;
 		}
-		iommu_area_reserve(map, index, nr);
+		bitmap_set(map, index, nr);
+		return index;
 	}
-	return index;
+	return -1;
 }
 EXPORT_SYMBOL(iommu_area_alloc);
 
-void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
-{
-	unsigned long end = start + nr;
-
-	while (start < end) {
-		__clear_bit(start, map);
-		start++;
-	}
-}
-EXPORT_SYMBOL(iommu_area_free);
-
 unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
 			      unsigned long io_page_size)
 {
diff --git a/lib/lmb.c b/lib/lmb.c
index 0343c05..9cee171 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -263,7 +263,7 @@
 	return lmb_add_region(_rgn, base, size);
 }
 
-long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
+long lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size)
 {
 	unsigned long i;
 
@@ -493,6 +493,11 @@
 	return 0;
 }
 
+int lmb_is_region_reserved(u64 base, u64 size)
+{
+	return lmb_overlaps_region(&lmb.reserved, base, size);
+}
+
 /*
  * Given a <base, len>, find which memory regions belong to this range.
  * Adjust the request and return a contiguous chunk.
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 5bc0180..437eedb 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -549,7 +549,7 @@
 		dma_mask = hwdev->coherent_dma_mask;
 
 	ret = (void *)__get_free_pages(flags, order);
-	if (ret && swiotlb_virt_to_bus(hwdev, ret) + size > dma_mask) {
+	if (ret && swiotlb_virt_to_bus(hwdev, ret) + size - 1 > dma_mask) {
 		/*
 		 * The allocated memory isn't reachable by the device.
 		 */
@@ -571,7 +571,7 @@
 	dev_addr = swiotlb_virt_to_bus(hwdev, ret);
 
 	/* Confirm address can be DMA'd by device */
-	if (dev_addr + size > dma_mask) {
+	if (dev_addr + size - 1 > dma_mask) {
 		printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
 		       (unsigned long long)dma_mask,
 		       (unsigned long long)dev_addr);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 735343f..d4996cf 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1179,7 +1179,18 @@
  * %ps output the name of a text symbol without offset
  * %pF output the name of a function pointer with its offset
  * %pf output the name of a function pointer without its offset
- * %pR output the address range in a struct resource
+ * %pR output the address range in a struct resource with decoded flags
+ * %pr output the address range in a struct resource with raw flags
+ * %pM output a 6-byte MAC address with colons
+ * %pm output a 6-byte MAC address without colons
+ * %pI4 print an IPv4 address without leading zeros
+ * %pi4 print an IPv4 address with leading zeros
+ * %pI6 print an IPv6 address with colons
+ * %pi6 print an IPv6 address without colons
+ * %pI6c print an IPv6 address as specified by
+ *   http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt
+ * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
+ *   case.
  * %n is ignored
  *
  * The return value is the number of characters which would
diff --git a/mm/Kconfig b/mm/Kconfig
index 2310984..43ea8c3 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -251,8 +251,9 @@
 	  special hardware support and typically ECC memory.
 
 config HWPOISON_INJECT
-	tristate "Poison pages injector"
+	tristate "HWPoison pages injector"
 	depends on MEMORY_FAILURE && DEBUG_KERNEL
+	select PROC_PAGE_MONITOR
 
 config NOMMU_INITIAL_TRIM_EXCESS
 	int "Turn on mmap() excess space trimming before booting"
diff --git a/mm/Makefile b/mm/Makefile
index 82131d0..7a68d2a 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -22,7 +22,6 @@
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
-obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
diff --git a/mm/filemap.c b/mm/filemap.c
index 8b4d88f..96ac6b0 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2240,7 +2240,6 @@
 		size_t count, ssize_t written)
 {
 	struct file *file = iocb->ki_filp;
-	struct address_space *mapping = file->f_mapping;
 	ssize_t status;
 	struct iov_iter i;
 
@@ -2252,15 +2251,6 @@
 		*ppos = pos + status;
   	}
 	
-	/*
-	 * If we get here for O_DIRECT writes then we must have fallen through
-	 * to buffered writes (block instantiation inside i_size).  So we sync
-	 * the file data here, to try to honour O_DIRECT expectations.
-	 */
-	if (unlikely(file->f_flags & O_DIRECT) && written)
-		status = filemap_write_and_wait_range(mapping,
-					pos, pos + written - 1);
-
 	return written ? written : status;
 }
 EXPORT_SYMBOL(generic_file_buffered_write);
@@ -2359,10 +2349,7 @@
 		 * semantics.
 		 */
 		endbyte = pos + written_buffered - written - 1;
-		err = do_sync_mapping_range(file->f_mapping, pos, endbyte,
-					    SYNC_FILE_RANGE_WAIT_BEFORE|
-					    SYNC_FILE_RANGE_WRITE|
-					    SYNC_FILE_RANGE_WAIT_AFTER);
+		err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte);
 		if (err == 0) {
 			written = written_buffered;
 			invalidate_mapping_pages(mapping,
diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c
index e1d8513..10ea719 100644
--- a/mm/hwpoison-inject.c
+++ b/mm/hwpoison-inject.c
@@ -3,18 +3,68 @@
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/pagemap.h>
+#include "internal.h"
 
-static struct dentry *hwpoison_dir, *corrupt_pfn;
+static struct dentry *hwpoison_dir;
 
 static int hwpoison_inject(void *data, u64 val)
 {
+	unsigned long pfn = val;
+	struct page *p;
+	int err;
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	printk(KERN_INFO "Injecting memory failure at pfn %Lx\n", val);
-	return __memory_failure(val, 18, 0);
+
+	if (!hwpoison_filter_enable)
+		goto inject;
+	if (!pfn_valid(pfn))
+		return -ENXIO;
+
+	p = pfn_to_page(pfn);
+	/*
+	 * This implies unable to support free buddy pages.
+	 */
+	if (!get_page_unless_zero(p))
+		return 0;
+
+	if (!PageLRU(p))
+		shake_page(p, 0);
+	/*
+	 * This implies unable to support non-LRU pages.
+	 */
+	if (!PageLRU(p))
+		return 0;
+
+	/*
+	 * do a racy check with elevated page count, to make sure PG_hwpoison
+	 * will only be set for the targeted owner (or on a free page).
+	 * We temporarily take page lock for try_get_mem_cgroup_from_page().
+	 * __memory_failure() will redo the check reliably inside page lock.
+	 */
+	lock_page(p);
+	err = hwpoison_filter(p);
+	unlock_page(p);
+	if (err)
+		return 0;
+
+inject:
+	printk(KERN_INFO "Injecting memory failure at pfn %lx\n", pfn);
+	return __memory_failure(pfn, 18, MF_COUNT_INCREASED);
+}
+
+static int hwpoison_unpoison(void *data, u64 val)
+{
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	return unpoison_memory(val);
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(hwpoison_fops, NULL, hwpoison_inject, "%lli\n");
+DEFINE_SIMPLE_ATTRIBUTE(unpoison_fops, NULL, hwpoison_unpoison, "%lli\n");
 
 static void pfn_inject_exit(void)
 {
@@ -24,16 +74,63 @@
 
 static int pfn_inject_init(void)
 {
+	struct dentry *dentry;
+
 	hwpoison_dir = debugfs_create_dir("hwpoison", NULL);
 	if (hwpoison_dir == NULL)
 		return -ENOMEM;
-	corrupt_pfn = debugfs_create_file("corrupt-pfn", 0600, hwpoison_dir,
+
+	/*
+	 * Note that the below poison/unpoison interfaces do not involve
+	 * hardware status change, hence do not require hardware support.
+	 * They are mainly for testing hwpoison in software level.
+	 */
+	dentry = debugfs_create_file("corrupt-pfn", 0600, hwpoison_dir,
 					  NULL, &hwpoison_fops);
-	if (corrupt_pfn == NULL) {
-		pfn_inject_exit();
-		return -ENOMEM;
-	}
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_file("unpoison-pfn", 0600, hwpoison_dir,
+				     NULL, &unpoison_fops);
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_u32("corrupt-filter-enable", 0600,
+				    hwpoison_dir, &hwpoison_filter_enable);
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_u32("corrupt-filter-dev-major", 0600,
+				    hwpoison_dir, &hwpoison_filter_dev_major);
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_u32("corrupt-filter-dev-minor", 0600,
+				    hwpoison_dir, &hwpoison_filter_dev_minor);
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_u64("corrupt-filter-flags-mask", 0600,
+				    hwpoison_dir, &hwpoison_filter_flags_mask);
+	if (!dentry)
+		goto fail;
+
+	dentry = debugfs_create_u64("corrupt-filter-flags-value", 0600,
+				    hwpoison_dir, &hwpoison_filter_flags_value);
+	if (!dentry)
+		goto fail;
+
+#ifdef	CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+	dentry = debugfs_create_u64("corrupt-filter-memcg", 0600,
+				    hwpoison_dir, &hwpoison_filter_memcg);
+	if (!dentry)
+		goto fail;
+#endif
+
 	return 0;
+fail:
+	pfn_inject_exit();
+	return -ENOMEM;
 }
 
 module_init(pfn_inject_init);
diff --git a/mm/internal.h b/mm/internal.h
index 4fe67a1..6a697bb 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -50,6 +50,9 @@
  */
 extern void __free_pages_bootmem(struct page *page, unsigned int order);
 extern void prep_compound_page(struct page *page, unsigned long order);
+#ifdef CONFIG_MEMORY_FAILURE
+extern bool is_free_buddy_page(struct page *page);
+#endif
 
 
 /*
@@ -247,3 +250,12 @@
 #define ZONE_RECLAIM_SOME	0
 #define ZONE_RECLAIM_SUCCESS	1
 #endif
+
+extern int hwpoison_filter(struct page *p);
+
+extern u32 hwpoison_filter_dev_major;
+extern u32 hwpoison_filter_dev_minor;
+extern u64 hwpoison_filter_flags_mask;
+extern u64 hwpoison_filter_flags_value;
+extern u64 hwpoison_filter_memcg;
+extern u32 hwpoison_filter_enable;
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 13f33b3..5b069e4 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -93,6 +93,7 @@
 #include <linux/nodemask.h>
 #include <linux/mm.h>
 #include <linux/workqueue.h>
+#include <linux/crc32.h>
 
 #include <asm/sections.h>
 #include <asm/processor.h>
@@ -108,7 +109,6 @@
 #define MSECS_MIN_AGE		5000	/* minimum object age for reporting */
 #define SECS_FIRST_SCAN		60	/* delay before the first scan */
 #define SECS_SCAN_WAIT		600	/* subsequent auto scanning delay */
-#define GRAY_LIST_PASSES	25	/* maximum number of gray list scans */
 #define MAX_SCAN_SIZE		4096	/* maximum size of a scanned block */
 
 #define BYTES_PER_POINTER	sizeof(void *)
@@ -119,8 +119,8 @@
 /* scanning area inside a memory block */
 struct kmemleak_scan_area {
 	struct hlist_node node;
-	unsigned long offset;
-	size_t length;
+	unsigned long start;
+	size_t size;
 };
 
 #define KMEMLEAK_GREY	0
@@ -149,6 +149,8 @@
 	int min_count;
 	/* the total number of pointers found pointing to this object */
 	int count;
+	/* checksum for detecting modified objects */
+	u32 checksum;
 	/* memory ranges to be scanned inside an object (empty for all) */
 	struct hlist_head area_list;
 	unsigned long trace[MAX_TRACE];
@@ -164,8 +166,6 @@
 #define OBJECT_REPORTED		(1 << 1)
 /* flag set to not scan the object */
 #define OBJECT_NO_SCAN		(1 << 2)
-/* flag set on newly allocated objects */
-#define OBJECT_NEW		(1 << 3)
 
 /* number of bytes to print per line; must be 16 or 32 */
 #define HEX_ROW_SIZE		16
@@ -241,8 +241,6 @@
 	const void *ptr;		/* allocated/freed memory block */
 	size_t size;			/* memory block size */
 	int min_count;			/* minimum reference count */
-	unsigned long offset;		/* scan area offset */
-	size_t length;			/* scan area length */
 	unsigned long trace[MAX_TRACE];	/* stack trace */
 	unsigned int trace_len;		/* stack trace length */
 };
@@ -323,11 +321,6 @@
 		object->count >= object->min_count;
 }
 
-static bool color_black(const struct kmemleak_object *object)
-{
-	return object->min_count == KMEMLEAK_BLACK;
-}
-
 /*
  * Objects are considered unreferenced only if their color is white, they have
  * not be deleted and have a minimum age to avoid false positives caused by
@@ -335,7 +328,7 @@
  */
 static bool unreferenced_object(struct kmemleak_object *object)
 {
-	return (object->flags & OBJECT_ALLOCATED) && color_white(object) &&
+	return (color_white(object) && object->flags & OBJECT_ALLOCATED) &&
 		time_before_eq(object->jiffies + jiffies_min_age,
 			       jiffies_last_scan);
 }
@@ -348,11 +341,13 @@
 			       struct kmemleak_object *object)
 {
 	int i;
+	unsigned int msecs_age = jiffies_to_msecs(jiffies - object->jiffies);
 
 	seq_printf(seq, "unreferenced object 0x%08lx (size %zu):\n",
 		   object->pointer, object->size);
-	seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
-		   object->comm, object->pid, object->jiffies);
+	seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu (age %d.%03ds)\n",
+		   object->comm, object->pid, object->jiffies,
+		   msecs_age / 1000, msecs_age % 1000);
 	hex_dump_object(seq, object);
 	seq_printf(seq, "  backtrace:\n");
 
@@ -381,6 +376,7 @@
 	pr_notice("  min_count = %d\n", object->min_count);
 	pr_notice("  count = %d\n", object->count);
 	pr_notice("  flags = 0x%lx\n", object->flags);
+	pr_notice("  checksum = %d\n", object->checksum);
 	pr_notice("  backtrace:\n");
 	print_stack_trace(&trace, 4);
 }
@@ -522,12 +518,13 @@
 	INIT_HLIST_HEAD(&object->area_list);
 	spin_lock_init(&object->lock);
 	atomic_set(&object->use_count, 1);
-	object->flags = OBJECT_ALLOCATED | OBJECT_NEW;
+	object->flags = OBJECT_ALLOCATED;
 	object->pointer = ptr;
 	object->size = size;
 	object->min_count = min_count;
-	object->count = -1;			/* no color initially */
+	object->count = 0;			/* white color initially */
 	object->jiffies = jiffies;
+	object->checksum = 0;
 
 	/* task information */
 	if (in_irq()) {
@@ -720,14 +717,13 @@
  * Add a scanning area to the object. If at least one such area is added,
  * kmemleak will only scan these ranges rather than the whole memory block.
  */
-static void add_scan_area(unsigned long ptr, unsigned long offset,
-			  size_t length, gfp_t gfp)
+static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp)
 {
 	unsigned long flags;
 	struct kmemleak_object *object;
 	struct kmemleak_scan_area *area;
 
-	object = find_and_get_object(ptr, 0);
+	object = find_and_get_object(ptr, 1);
 	if (!object) {
 		kmemleak_warn("Adding scan area to unknown object at 0x%08lx\n",
 			      ptr);
@@ -741,7 +737,7 @@
 	}
 
 	spin_lock_irqsave(&object->lock, flags);
-	if (offset + length > object->size) {
+	if (ptr + size > object->pointer + object->size) {
 		kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
 		dump_object_info(object);
 		kmem_cache_free(scan_area_cache, area);
@@ -749,8 +745,8 @@
 	}
 
 	INIT_HLIST_NODE(&area->node);
-	area->offset = offset;
-	area->length = length;
+	area->start = ptr;
+	area->size = size;
 
 	hlist_add_head(&area->node, &object->area_list);
 out_unlock:
@@ -786,7 +782,7 @@
  * processed later once kmemleak is fully initialized.
  */
 static void __init log_early(int op_type, const void *ptr, size_t size,
-			     int min_count, unsigned long offset, size_t length)
+			     int min_count)
 {
 	unsigned long flags;
 	struct early_log *log;
@@ -808,8 +804,6 @@
 	log->ptr = ptr;
 	log->size = size;
 	log->min_count = min_count;
-	log->offset = offset;
-	log->length = length;
 	if (op_type == KMEMLEAK_ALLOC)
 		log->trace_len = __save_stack_trace(log->trace);
 	crt_early_log++;
@@ -858,7 +852,7 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		create_object((unsigned long)ptr, size, min_count, gfp);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_ALLOC, ptr, size, min_count, 0, 0);
+		log_early(KMEMLEAK_ALLOC, ptr, size, min_count);
 }
 EXPORT_SYMBOL_GPL(kmemleak_alloc);
 
@@ -873,7 +867,7 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		delete_object_full((unsigned long)ptr);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0);
+		log_early(KMEMLEAK_FREE, ptr, 0, 0);
 }
 EXPORT_SYMBOL_GPL(kmemleak_free);
 
@@ -888,7 +882,7 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		delete_object_part((unsigned long)ptr, size);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_FREE_PART, ptr, size, 0, 0, 0);
+		log_early(KMEMLEAK_FREE_PART, ptr, size, 0);
 }
 EXPORT_SYMBOL_GPL(kmemleak_free_part);
 
@@ -903,7 +897,7 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		make_gray_object((unsigned long)ptr);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_NOT_LEAK, ptr, 0, 0, 0, 0);
+		log_early(KMEMLEAK_NOT_LEAK, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_not_leak);
 
@@ -919,22 +913,21 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		make_black_object((unsigned long)ptr);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_IGNORE, ptr, 0, 0, 0, 0);
+		log_early(KMEMLEAK_IGNORE, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_ignore);
 
 /*
  * Limit the range to be scanned in an allocated memory block.
  */
-void __ref kmemleak_scan_area(const void *ptr, unsigned long offset,
-			      size_t length, gfp_t gfp)
+void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
 	pr_debug("%s(0x%p)\n", __func__, ptr);
 
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
-		add_scan_area((unsigned long)ptr, offset, length, gfp);
+		add_scan_area((unsigned long)ptr, size, gfp);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_SCAN_AREA, ptr, 0, 0, offset, length);
+		log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
 }
 EXPORT_SYMBOL(kmemleak_scan_area);
 
@@ -948,11 +941,25 @@
 	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
 		object_no_scan((unsigned long)ptr);
 	else if (atomic_read(&kmemleak_early_log))
-		log_early(KMEMLEAK_NO_SCAN, ptr, 0, 0, 0, 0);
+		log_early(KMEMLEAK_NO_SCAN, ptr, 0, 0);
 }
 EXPORT_SYMBOL(kmemleak_no_scan);
 
 /*
+ * Update an object's checksum and return true if it was modified.
+ */
+static bool update_checksum(struct kmemleak_object *object)
+{
+	u32 old_csum = object->checksum;
+
+	if (!kmemcheck_is_obj_initialized(object->pointer, object->size))
+		return false;
+
+	object->checksum = crc32(0, (void *)object->pointer, object->size);
+	return object->checksum != old_csum;
+}
+
+/*
  * Memory scanning is a long process and it needs to be interruptable. This
  * function checks whether such interrupt condition occured.
  */
@@ -1031,11 +1038,14 @@
 		 * added to the gray_list.
 		 */
 		object->count++;
-		if (color_gray(object))
+		if (color_gray(object)) {
 			list_add_tail(&object->gray_list, &gray_list);
-		else
-			put_object(object);
+			spin_unlock_irqrestore(&object->lock, flags);
+			continue;
+		}
+
 		spin_unlock_irqrestore(&object->lock, flags);
+		put_object(object);
 	}
 }
 
@@ -1075,14 +1085,47 @@
 		}
 	} else
 		hlist_for_each_entry(area, elem, &object->area_list, node)
-			scan_block((void *)(object->pointer + area->offset),
-				   (void *)(object->pointer + area->offset
-					    + area->length), object, 0);
+			scan_block((void *)area->start,
+				   (void *)(area->start + area->size),
+				   object, 0);
 out:
 	spin_unlock_irqrestore(&object->lock, flags);
 }
 
 /*
+ * Scan the objects already referenced (gray objects). More objects will be
+ * referenced and, if there are no memory leaks, all the objects are scanned.
+ */
+static void scan_gray_list(void)
+{
+	struct kmemleak_object *object, *tmp;
+
+	/*
+	 * The list traversal is safe for both tail additions and removals
+	 * from inside the loop. The kmemleak objects cannot be freed from
+	 * outside the loop because their use_count was incremented.
+	 */
+	object = list_entry(gray_list.next, typeof(*object), gray_list);
+	while (&object->gray_list != &gray_list) {
+		cond_resched();
+
+		/* may add new objects to the list */
+		if (!scan_should_stop())
+			scan_object(object);
+
+		tmp = list_entry(object->gray_list.next, typeof(*object),
+				 gray_list);
+
+		/* remove the object from the list and release it */
+		list_del(&object->gray_list);
+		put_object(object);
+
+		object = tmp;
+	}
+	WARN_ON(!list_empty(&gray_list));
+}
+
+/*
  * Scan data sections and all the referenced memory blocks allocated via the
  * kernel's standard allocators. This function must be called with the
  * scan_mutex held.
@@ -1090,10 +1133,9 @@
 static void kmemleak_scan(void)
 {
 	unsigned long flags;
-	struct kmemleak_object *object, *tmp;
+	struct kmemleak_object *object;
 	int i;
 	int new_leaks = 0;
-	int gray_list_pass = 0;
 
 	jiffies_last_scan = jiffies;
 
@@ -1114,7 +1156,6 @@
 #endif
 		/* reset the reference count (whiten the object) */
 		object->count = 0;
-		object->flags &= ~OBJECT_NEW;
 		if (color_gray(object) && get_object(object))
 			list_add_tail(&object->gray_list, &gray_list);
 
@@ -1172,62 +1213,36 @@
 
 	/*
 	 * Scan the objects already referenced from the sections scanned
-	 * above. More objects will be referenced and, if there are no memory
-	 * leaks, all the objects will be scanned. The list traversal is safe
-	 * for both tail additions and removals from inside the loop. The
-	 * kmemleak objects cannot be freed from outside the loop because their
-	 * use_count was increased.
+	 * above.
 	 */
-repeat:
-	object = list_entry(gray_list.next, typeof(*object), gray_list);
-	while (&object->gray_list != &gray_list) {
-		cond_resched();
-
-		/* may add new objects to the list */
-		if (!scan_should_stop())
-			scan_object(object);
-
-		tmp = list_entry(object->gray_list.next, typeof(*object),
-				 gray_list);
-
-		/* remove the object from the list and release it */
-		list_del(&object->gray_list);
-		put_object(object);
-
-		object = tmp;
-	}
-
-	if (scan_should_stop() || ++gray_list_pass >= GRAY_LIST_PASSES)
-		goto scan_end;
+	scan_gray_list();
 
 	/*
-	 * Check for new objects allocated during this scanning and add them
-	 * to the gray list.
+	 * Check for new or unreferenced objects modified since the previous
+	 * scan and color them gray until the next scan.
 	 */
 	rcu_read_lock();
 	list_for_each_entry_rcu(object, &object_list, object_list) {
 		spin_lock_irqsave(&object->lock, flags);
-		if ((object->flags & OBJECT_NEW) && !color_black(object) &&
-		    get_object(object)) {
-			object->flags &= ~OBJECT_NEW;
+		if (color_white(object) && (object->flags & OBJECT_ALLOCATED)
+		    && update_checksum(object) && get_object(object)) {
+			/* color it gray temporarily */
+			object->count = object->min_count;
 			list_add_tail(&object->gray_list, &gray_list);
 		}
 		spin_unlock_irqrestore(&object->lock, flags);
 	}
 	rcu_read_unlock();
 
-	if (!list_empty(&gray_list))
-		goto repeat;
-
-scan_end:
-	WARN_ON(!list_empty(&gray_list));
+	/*
+	 * Re-scan the gray list for modified unreferenced objects.
+	 */
+	scan_gray_list();
 
 	/*
-	 * If scanning was stopped or new objects were being allocated at a
-	 * higher rate than gray list scanning, do not report any new
-	 * unreferenced objects.
+	 * If scanning was stopped do not report any new unreferenced objects.
 	 */
-	if (scan_should_stop() || gray_list_pass >= GRAY_LIST_PASSES)
+	if (scan_should_stop())
 		return;
 
 	/*
@@ -1642,8 +1657,7 @@
 			kmemleak_ignore(log->ptr);
 			break;
 		case KMEMLEAK_SCAN_AREA:
-			kmemleak_scan_area(log->ptr, log->offset, log->length,
-					   GFP_KERNEL);
+			kmemleak_scan_area(log->ptr, log->size, GFP_KERNEL);
 			break;
 		case KMEMLEAK_NO_SCAN:
 			kmemleak_no_scan(log->ptr);
diff --git a/mm/madvise.c b/mm/madvise.c
index 35b1479..319528b 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -9,6 +9,7 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/mempolicy.h>
+#include <linux/page-isolation.h>
 #include <linux/hugetlb.h>
 #include <linux/sched.h>
 #include <linux/ksm.h>
@@ -222,7 +223,7 @@
 /*
  * Error injection support for memory error handling.
  */
-static int madvise_hwpoison(unsigned long start, unsigned long end)
+static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
 {
 	int ret = 0;
 
@@ -230,15 +231,21 @@
 		return -EPERM;
 	for (; start < end; start += PAGE_SIZE) {
 		struct page *p;
-		int ret = get_user_pages(current, current->mm, start, 1,
-						0, 0, &p, NULL);
+		int ret = get_user_pages_fast(start, 1, 0, &p);
 		if (ret != 1)
 			return ret;
+		if (bhv == MADV_SOFT_OFFLINE) {
+			printk(KERN_INFO "Soft offlining page %lx at %lx\n",
+				page_to_pfn(p), start);
+			ret = soft_offline_page(p, MF_COUNT_INCREASED);
+			if (ret)
+				break;
+			continue;
+		}
 		printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n",
 		       page_to_pfn(p), start);
 		/* Ignore return value for now */
-		__memory_failure(page_to_pfn(p), 0, 1);
-		put_page(p);
+		__memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
 	}
 	return ret;
 }
@@ -335,8 +342,8 @@
 	size_t len;
 
 #ifdef CONFIG_MEMORY_FAILURE
-	if (behavior == MADV_HWPOISON)
-		return madvise_hwpoison(start, start+len_in);
+	if (behavior == MADV_HWPOISON || behavior == MADV_SOFT_OFFLINE)
+		return madvise_hwpoison(behavior, start, start+len_in);
 #endif
 	if (!madvise_behavior_valid(behavior))
 		return error;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index e0c2066..488b644 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -38,6 +38,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm_inline.h>
 #include <linux/page_cgroup.h>
+#include <linux/cpu.h>
 #include "internal.h"
 
 #include <asm/uaccess.h>
@@ -54,7 +55,6 @@
 #define do_swap_account		(0)
 #endif
 
-static DEFINE_MUTEX(memcg_tasklist);	/* can be hold under cgroup_mutex */
 #define SOFTLIMIT_EVENTS_THRESH (1000)
 
 /*
@@ -66,7 +66,7 @@
 	 */
 	MEM_CGROUP_STAT_CACHE, 	   /* # of pages charged as cache */
 	MEM_CGROUP_STAT_RSS,	   /* # of pages charged as anon rss */
-	MEM_CGROUP_STAT_MAPPED_FILE,  /* # of pages charged as file rss */
+	MEM_CGROUP_STAT_FILE_MAPPED,  /* # of pages charged as file rss */
 	MEM_CGROUP_STAT_PGPGIN_COUNT,	/* # of pages paged in */
 	MEM_CGROUP_STAT_PGPGOUT_COUNT,	/* # of pages paged out */
 	MEM_CGROUP_STAT_EVENTS,	/* sum of pagein + pageout for internal use */
@@ -275,6 +275,7 @@
 static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
+static void drain_all_stock_async(void);
 
 static struct mem_cgroup_per_zone *
 mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
@@ -282,6 +283,11 @@
 	return &mem->info.nodeinfo[nid]->zoneinfo[zid];
 }
 
+struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
+{
+	return &mem->css;
+}
+
 static struct mem_cgroup_per_zone *
 page_cgroup_zoneinfo(struct page_cgroup *pc)
 {
@@ -758,7 +764,13 @@
 	task_unlock(task);
 	if (!curr)
 		return 0;
-	if (curr->use_hierarchy)
+	/*
+	 * We should check use_hierarchy of "mem" not "curr". Because checking
+	 * use_hierarchy of "curr" here make this function true if hierarchy is
+	 * enabled in "curr" and "curr" is a child of "mem" in *cgroup*
+	 * hierarchy(even if use_hierarchy is disabled in "mem").
+	 */
+	if (mem->use_hierarchy)
 		ret = css_is_ancestor(&curr->css, &mem->css);
 	else
 		ret = (curr == mem);
@@ -1007,7 +1019,7 @@
 	static char memcg_name[PATH_MAX];
 	int ret;
 
-	if (!memcg)
+	if (!memcg || !p)
 		return;
 
 
@@ -1137,6 +1149,8 @@
 		victim = mem_cgroup_select_victim(root_mem);
 		if (victim == root_mem) {
 			loop++;
+			if (loop >= 1)
+				drain_all_stock_async();
 			if (loop >= 2) {
 				/*
 				 * If we have not been able to reclaim
@@ -1223,7 +1237,7 @@
  * Currently used to update mapped file statistics, but the routine can be
  * generalized to update other statistics as well.
  */
-void mem_cgroup_update_mapped_file_stat(struct page *page, int val)
+void mem_cgroup_update_file_mapped(struct page *page, int val)
 {
 	struct mem_cgroup *mem;
 	struct mem_cgroup_stat *stat;
@@ -1231,9 +1245,6 @@
 	int cpu;
 	struct page_cgroup *pc;
 
-	if (!page_is_file_cache(page))
-		return;
-
 	pc = lookup_page_cgroup(page);
 	if (unlikely(!pc))
 		return;
@@ -1253,12 +1264,139 @@
 	stat = &mem->stat;
 	cpustat = &stat->cpustat[cpu];
 
-	__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE, val);
+	__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED, val);
 done:
 	unlock_page_cgroup(pc);
 }
 
 /*
+ * size of first charge trial. "32" comes from vmscan.c's magic value.
+ * TODO: maybe necessary to use big numbers in big irons.
+ */
+#define CHARGE_SIZE	(32 * PAGE_SIZE)
+struct memcg_stock_pcp {
+	struct mem_cgroup *cached; /* this never be root cgroup */
+	int charge;
+	struct work_struct work;
+};
+static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
+static atomic_t memcg_drain_count;
+
+/*
+ * Try to consume stocked charge on this cpu. If success, PAGE_SIZE is consumed
+ * from local stock and true is returned. If the stock is 0 or charges from a
+ * cgroup which is not current target, returns false. This stock will be
+ * refilled.
+ */
+static bool consume_stock(struct mem_cgroup *mem)
+{
+	struct memcg_stock_pcp *stock;
+	bool ret = true;
+
+	stock = &get_cpu_var(memcg_stock);
+	if (mem == stock->cached && stock->charge)
+		stock->charge -= PAGE_SIZE;
+	else /* need to call res_counter_charge */
+		ret = false;
+	put_cpu_var(memcg_stock);
+	return ret;
+}
+
+/*
+ * Returns stocks cached in percpu to res_counter and reset cached information.
+ */
+static void drain_stock(struct memcg_stock_pcp *stock)
+{
+	struct mem_cgroup *old = stock->cached;
+
+	if (stock->charge) {
+		res_counter_uncharge(&old->res, stock->charge);
+		if (do_swap_account)
+			res_counter_uncharge(&old->memsw, stock->charge);
+	}
+	stock->cached = NULL;
+	stock->charge = 0;
+}
+
+/*
+ * This must be called under preempt disabled or must be called by
+ * a thread which is pinned to local cpu.
+ */
+static void drain_local_stock(struct work_struct *dummy)
+{
+	struct memcg_stock_pcp *stock = &__get_cpu_var(memcg_stock);
+	drain_stock(stock);
+}
+
+/*
+ * Cache charges(val) which is from res_counter, to local per_cpu area.
+ * This will be consumed by consumt_stock() function, later.
+ */
+static void refill_stock(struct mem_cgroup *mem, int val)
+{
+	struct memcg_stock_pcp *stock = &get_cpu_var(memcg_stock);
+
+	if (stock->cached != mem) { /* reset if necessary */
+		drain_stock(stock);
+		stock->cached = mem;
+	}
+	stock->charge += val;
+	put_cpu_var(memcg_stock);
+}
+
+/*
+ * Tries to drain stocked charges in other cpus. This function is asynchronous
+ * and just put a work per cpu for draining localy on each cpu. Caller can
+ * expects some charges will be back to res_counter later but cannot wait for
+ * it.
+ */
+static void drain_all_stock_async(void)
+{
+	int cpu;
+	/* This function is for scheduling "drain" in asynchronous way.
+	 * The result of "drain" is not directly handled by callers. Then,
+	 * if someone is calling drain, we don't have to call drain more.
+	 * Anyway, WORK_STRUCT_PENDING check in queue_work_on() will catch if
+	 * there is a race. We just do loose check here.
+	 */
+	if (atomic_read(&memcg_drain_count))
+		return;
+	/* Notify other cpus that system-wide "drain" is running */
+	atomic_inc(&memcg_drain_count);
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
+		schedule_work_on(cpu, &stock->work);
+	}
+ 	put_online_cpus();
+	atomic_dec(&memcg_drain_count);
+	/* We don't wait for flush_work */
+}
+
+/* This is a synchronous drain interface. */
+static void drain_all_stock_sync(void)
+{
+	/* called when force_empty is called */
+	atomic_inc(&memcg_drain_count);
+	schedule_on_each_cpu(drain_local_stock);
+	atomic_dec(&memcg_drain_count);
+}
+
+static int __cpuinit memcg_stock_cpu_callback(struct notifier_block *nb,
+					unsigned long action,
+					void *hcpu)
+{
+	int cpu = (unsigned long)hcpu;
+	struct memcg_stock_pcp *stock;
+
+	if (action != CPU_DEAD)
+		return NOTIFY_OK;
+	stock = &per_cpu(memcg_stock, cpu);
+	drain_stock(stock);
+	return NOTIFY_OK;
+}
+
+/*
  * Unlike exported interface, "oom" parameter is added. if oom==true,
  * oom-killer can be invoked.
  */
@@ -1269,6 +1407,7 @@
 	struct mem_cgroup *mem, *mem_over_limit;
 	int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
 	struct res_counter *fail_res;
+	int csize = CHARGE_SIZE;
 
 	if (unlikely(test_thread_flag(TIF_MEMDIE))) {
 		/* Don't account this! */
@@ -1293,23 +1432,25 @@
 		return 0;
 
 	VM_BUG_ON(css_is_removed(&mem->css));
+	if (mem_cgroup_is_root(mem))
+		goto done;
 
 	while (1) {
 		int ret = 0;
 		unsigned long flags = 0;
 
-		if (mem_cgroup_is_root(mem))
-			goto done;
-		ret = res_counter_charge(&mem->res, PAGE_SIZE, &fail_res);
+		if (consume_stock(mem))
+			goto charged;
+
+		ret = res_counter_charge(&mem->res, csize, &fail_res);
 		if (likely(!ret)) {
 			if (!do_swap_account)
 				break;
-			ret = res_counter_charge(&mem->memsw, PAGE_SIZE,
-							&fail_res);
+			ret = res_counter_charge(&mem->memsw, csize, &fail_res);
 			if (likely(!ret))
 				break;
 			/* mem+swap counter fails */
-			res_counter_uncharge(&mem->res, PAGE_SIZE);
+			res_counter_uncharge(&mem->res, csize);
 			flags |= MEM_CGROUP_RECLAIM_NOSWAP;
 			mem_over_limit = mem_cgroup_from_res_counter(fail_res,
 									memsw);
@@ -1318,6 +1459,11 @@
 			mem_over_limit = mem_cgroup_from_res_counter(fail_res,
 									res);
 
+		/* reduce request size and retry */
+		if (csize > PAGE_SIZE) {
+			csize = PAGE_SIZE;
+			continue;
+		}
 		if (!(gfp_mask & __GFP_WAIT))
 			goto nomem;
 
@@ -1339,14 +1485,15 @@
 
 		if (!nr_retries--) {
 			if (oom) {
-				mutex_lock(&memcg_tasklist);
 				mem_cgroup_out_of_memory(mem_over_limit, gfp_mask);
-				mutex_unlock(&memcg_tasklist);
 				record_last_oom(mem_over_limit);
 			}
 			goto nomem;
 		}
 	}
+	if (csize > PAGE_SIZE)
+		refill_stock(mem, csize - PAGE_SIZE);
+charged:
 	/*
 	 * Insert ancestor (and ancestor's ancestors), to softlimit RB-tree.
 	 * if they exceeds softlimit.
@@ -1361,6 +1508,21 @@
 }
 
 /*
+ * Somemtimes we have to undo a charge we got by try_charge().
+ * This function is for that and do uncharge, put css's refcnt.
+ * gotten by try_charge().
+ */
+static void mem_cgroup_cancel_charge(struct mem_cgroup *mem)
+{
+	if (!mem_cgroup_is_root(mem)) {
+		res_counter_uncharge(&mem->res, PAGE_SIZE);
+		if (do_swap_account)
+			res_counter_uncharge(&mem->memsw, PAGE_SIZE);
+	}
+	css_put(&mem->css);
+}
+
+/*
  * A helper function to get mem_cgroup from ID. must be called under
  * rcu_read_lock(). The caller must check css_is_removed() or some if
  * it's concern. (dropping refcnt from swap can be called against removed
@@ -1379,25 +1541,22 @@
 	return container_of(css, struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page)
+struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *mem = NULL;
 	struct page_cgroup *pc;
 	unsigned short id;
 	swp_entry_t ent;
 
 	VM_BUG_ON(!PageLocked(page));
 
-	if (!PageSwapCache(page))
-		return NULL;
-
 	pc = lookup_page_cgroup(page);
 	lock_page_cgroup(pc);
 	if (PageCgroupUsed(pc)) {
 		mem = pc->mem_cgroup;
 		if (mem && !css_tryget(&mem->css))
 			mem = NULL;
-	} else {
+	} else if (PageSwapCache(page)) {
 		ent.val = page_private(page);
 		id = lookup_swap_cgroup(ent);
 		rcu_read_lock();
@@ -1426,12 +1585,7 @@
 	lock_page_cgroup(pc);
 	if (unlikely(PageCgroupUsed(pc))) {
 		unlock_page_cgroup(pc);
-		if (!mem_cgroup_is_root(mem)) {
-			res_counter_uncharge(&mem->res, PAGE_SIZE);
-			if (do_swap_account)
-				res_counter_uncharge(&mem->memsw, PAGE_SIZE);
-		}
-		css_put(&mem->css);
+		mem_cgroup_cancel_charge(mem);
 		return;
 	}
 
@@ -1464,27 +1618,22 @@
 }
 
 /**
- * mem_cgroup_move_account - move account of the page
+ * __mem_cgroup_move_account - move account of the page
  * @pc:	page_cgroup of the page.
  * @from: mem_cgroup which the page is moved from.
  * @to:	mem_cgroup which the page is moved to. @from != @to.
  *
  * The caller must confirm following.
  * - page is not on LRU (isolate_page() is useful.)
- *
- * returns 0 at success,
- * returns -EBUSY when lock is busy or "pc" is unstable.
+ * - the pc is locked, used, and ->mem_cgroup points to @from.
  *
  * This function does "uncharge" from old cgroup but doesn't do "charge" to
  * new cgroup. It should be done by a caller.
  */
 
-static int mem_cgroup_move_account(struct page_cgroup *pc,
+static void __mem_cgroup_move_account(struct page_cgroup *pc,
 	struct mem_cgroup *from, struct mem_cgroup *to)
 {
-	struct mem_cgroup_per_zone *from_mz, *to_mz;
-	int nid, zid;
-	int ret = -EBUSY;
 	struct page *page;
 	int cpu;
 	struct mem_cgroup_stat *stat;
@@ -1492,38 +1641,27 @@
 
 	VM_BUG_ON(from == to);
 	VM_BUG_ON(PageLRU(pc->page));
-
-	nid = page_cgroup_nid(pc);
-	zid = page_cgroup_zid(pc);
-	from_mz =  mem_cgroup_zoneinfo(from, nid, zid);
-	to_mz =  mem_cgroup_zoneinfo(to, nid, zid);
-
-	if (!trylock_page_cgroup(pc))
-		return ret;
-
-	if (!PageCgroupUsed(pc))
-		goto out;
-
-	if (pc->mem_cgroup != from)
-		goto out;
+	VM_BUG_ON(!PageCgroupLocked(pc));
+	VM_BUG_ON(!PageCgroupUsed(pc));
+	VM_BUG_ON(pc->mem_cgroup != from);
 
 	if (!mem_cgroup_is_root(from))
 		res_counter_uncharge(&from->res, PAGE_SIZE);
 	mem_cgroup_charge_statistics(from, pc, false);
 
 	page = pc->page;
-	if (page_is_file_cache(page) && page_mapped(page)) {
+	if (page_mapped(page) && !PageAnon(page)) {
 		cpu = smp_processor_id();
 		/* Update mapped_file data for mem_cgroup "from" */
 		stat = &from->stat;
 		cpustat = &stat->cpustat[cpu];
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE,
+		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED,
 						-1);
 
 		/* Update mapped_file data for mem_cgroup "to" */
 		stat = &to->stat;
 		cpustat = &stat->cpustat[cpu];
-		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_MAPPED_FILE,
+		__mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_FILE_MAPPED,
 						1);
 	}
 
@@ -1534,15 +1672,28 @@
 	css_get(&to->css);
 	pc->mem_cgroup = to;
 	mem_cgroup_charge_statistics(to, pc, true);
-	ret = 0;
-out:
-	unlock_page_cgroup(pc);
 	/*
 	 * We charges against "to" which may not have any tasks. Then, "to"
 	 * can be under rmdir(). But in current implementation, caller of
 	 * this function is just force_empty() and it's garanteed that
 	 * "to" is never removed. So, we don't check rmdir status here.
 	 */
+}
+
+/*
+ * check whether the @pc is valid for moving account and call
+ * __mem_cgroup_move_account()
+ */
+static int mem_cgroup_move_account(struct page_cgroup *pc,
+				struct mem_cgroup *from, struct mem_cgroup *to)
+{
+	int ret = -EINVAL;
+	lock_page_cgroup(pc);
+	if (PageCgroupUsed(pc) && pc->mem_cgroup == from) {
+		__mem_cgroup_move_account(pc, from, to);
+		ret = 0;
+	}
+	unlock_page_cgroup(pc);
 	return ret;
 }
 
@@ -1564,45 +1715,27 @@
 	if (!pcg)
 		return -EINVAL;
 
+	ret = -EBUSY;
+	if (!get_page_unless_zero(page))
+		goto out;
+	if (isolate_lru_page(page))
+		goto put;
 
 	parent = mem_cgroup_from_cont(pcg);
-
-
 	ret = __mem_cgroup_try_charge(NULL, gfp_mask, &parent, false, page);
 	if (ret || !parent)
-		return ret;
-
-	if (!get_page_unless_zero(page)) {
-		ret = -EBUSY;
-		goto uncharge;
-	}
-
-	ret = isolate_lru_page(page);
-
-	if (ret)
-		goto cancel;
+		goto put_back;
 
 	ret = mem_cgroup_move_account(pc, child, parent);
-
+	if (!ret)
+		css_put(&parent->css);	/* drop extra refcnt by try_charge() */
+	else
+		mem_cgroup_cancel_charge(parent);	/* does css_put */
+put_back:
 	putback_lru_page(page);
-	if (!ret) {
-		put_page(page);
-		/* drop extra refcnt by try_charge() */
-		css_put(&parent->css);
-		return 0;
-	}
-
-cancel:
+put:
 	put_page(page);
-uncharge:
-	/* drop extra refcnt by try_charge() */
-	css_put(&parent->css);
-	/* uncharge if move fails */
-	if (!mem_cgroup_is_root(parent)) {
-		res_counter_uncharge(&parent->res, PAGE_SIZE);
-		if (do_swap_account)
-			res_counter_uncharge(&parent->memsw, PAGE_SIZE);
-	}
+out:
 	return ret;
 }
 
@@ -1743,7 +1876,7 @@
 	 */
 	if (!PageSwapCache(page))
 		goto charge_cur_mm;
-	mem = try_get_mem_cgroup_from_swapcache(page);
+	mem = try_get_mem_cgroup_from_page(page);
 	if (!mem)
 		goto charge_cur_mm;
 	*ptr = mem;
@@ -1819,14 +1952,53 @@
 		return;
 	if (!mem)
 		return;
-	if (!mem_cgroup_is_root(mem)) {
-		res_counter_uncharge(&mem->res, PAGE_SIZE);
-		if (do_swap_account)
-			res_counter_uncharge(&mem->memsw, PAGE_SIZE);
-	}
-	css_put(&mem->css);
+	mem_cgroup_cancel_charge(mem);
 }
 
+static void
+__do_uncharge(struct mem_cgroup *mem, const enum charge_type ctype)
+{
+	struct memcg_batch_info *batch = NULL;
+	bool uncharge_memsw = true;
+	/* If swapout, usage of swap doesn't decrease */
+	if (!do_swap_account || ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT)
+		uncharge_memsw = false;
+	/*
+	 * do_batch > 0 when unmapping pages or inode invalidate/truncate.
+	 * In those cases, all pages freed continously can be expected to be in
+	 * the same cgroup and we have chance to coalesce uncharges.
+	 * But we do uncharge one by one if this is killed by OOM(TIF_MEMDIE)
+	 * because we want to do uncharge as soon as possible.
+	 */
+	if (!current->memcg_batch.do_batch || test_thread_flag(TIF_MEMDIE))
+		goto direct_uncharge;
+
+	batch = &current->memcg_batch;
+	/*
+	 * In usual, we do css_get() when we remember memcg pointer.
+	 * But in this case, we keep res->usage until end of a series of
+	 * uncharges. Then, it's ok to ignore memcg's refcnt.
+	 */
+	if (!batch->memcg)
+		batch->memcg = mem;
+	/*
+	 * In typical case, batch->memcg == mem. This means we can
+	 * merge a series of uncharges to an uncharge of res_counter.
+	 * If not, we uncharge res_counter ony by one.
+	 */
+	if (batch->memcg != mem)
+		goto direct_uncharge;
+	/* remember freed charge and uncharge it later */
+	batch->bytes += PAGE_SIZE;
+	if (uncharge_memsw)
+		batch->memsw_bytes += PAGE_SIZE;
+	return;
+direct_uncharge:
+	res_counter_uncharge(&mem->res, PAGE_SIZE);
+	if (uncharge_memsw)
+		res_counter_uncharge(&mem->memsw, PAGE_SIZE);
+	return;
+}
 
 /*
  * uncharge if !page_mapped(page)
@@ -1875,12 +2047,8 @@
 		break;
 	}
 
-	if (!mem_cgroup_is_root(mem)) {
-		res_counter_uncharge(&mem->res, PAGE_SIZE);
-		if (do_swap_account &&
-				(ctype != MEM_CGROUP_CHARGE_TYPE_SWAPOUT))
-			res_counter_uncharge(&mem->memsw, PAGE_SIZE);
-	}
+	if (!mem_cgroup_is_root(mem))
+		__do_uncharge(mem, ctype);
 	if (ctype == MEM_CGROUP_CHARGE_TYPE_SWAPOUT)
 		mem_cgroup_swap_statistics(mem, true);
 	mem_cgroup_charge_statistics(mem, pc, false);
@@ -1926,6 +2094,50 @@
 	__mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
 }
 
+/*
+ * Batch_start/batch_end is called in unmap_page_range/invlidate/trucate.
+ * In that cases, pages are freed continuously and we can expect pages
+ * are in the same memcg. All these calls itself limits the number of
+ * pages freed at once, then uncharge_start/end() is called properly.
+ * This may be called prural(2) times in a context,
+ */
+
+void mem_cgroup_uncharge_start(void)
+{
+	current->memcg_batch.do_batch++;
+	/* We can do nest. */
+	if (current->memcg_batch.do_batch == 1) {
+		current->memcg_batch.memcg = NULL;
+		current->memcg_batch.bytes = 0;
+		current->memcg_batch.memsw_bytes = 0;
+	}
+}
+
+void mem_cgroup_uncharge_end(void)
+{
+	struct memcg_batch_info *batch = &current->memcg_batch;
+
+	if (!batch->do_batch)
+		return;
+
+	batch->do_batch--;
+	if (batch->do_batch) /* If stacked, do nothing. */
+		return;
+
+	if (!batch->memcg)
+		return;
+	/*
+	 * This "batch->memcg" is valid without any css_get/put etc...
+	 * bacause we hide charges behind us.
+	 */
+	if (batch->bytes)
+		res_counter_uncharge(&batch->memcg->res, batch->bytes);
+	if (batch->memsw_bytes)
+		res_counter_uncharge(&batch->memcg->memsw, batch->memsw_bytes);
+	/* forget this pointer (for sanity check) */
+	batch->memcg = NULL;
+}
+
 #ifdef CONFIG_SWAP
 /*
  * called after __delete_from_swap_cache() and drop "page" account.
@@ -2101,7 +2313,6 @@
 				unsigned long long val)
 {
 	int retry_count;
-	int progress;
 	u64 memswlimit;
 	int ret = 0;
 	int children = mem_cgroup_count_children(memcg);
@@ -2145,8 +2356,7 @@
 		if (!ret)
 			break;
 
-		progress = mem_cgroup_hierarchical_reclaim(memcg, NULL,
-						GFP_KERNEL,
+		mem_cgroup_hierarchical_reclaim(memcg, NULL, GFP_KERNEL,
 						MEM_CGROUP_RECLAIM_SHRINK);
 		curusage = res_counter_read_u64(&memcg->res, RES_USAGE);
 		/* Usage is reduced ? */
@@ -2385,6 +2595,7 @@
 			goto out;
 		/* This is for making all *used* pages to be on LRU. */
 		lru_add_drain_all();
+		drain_all_stock_sync();
 		ret = 0;
 		for_each_node_state(node, N_HIGH_MEMORY) {
 			for (zid = 0; !ret && zid < MAX_NR_ZONES; zid++) {
@@ -2542,6 +2753,7 @@
 			val += idx_val;
 			mem_cgroup_get_recursive_idx_stat(mem,
 				MEM_CGROUP_STAT_SWAPOUT, &idx_val);
+			val += idx_val;
 			val <<= PAGE_SHIFT;
 		} else
 			val = res_counter_read_u64(&mem->memsw, name);
@@ -2661,7 +2873,7 @@
 enum {
 	MCS_CACHE,
 	MCS_RSS,
-	MCS_MAPPED_FILE,
+	MCS_FILE_MAPPED,
 	MCS_PGPGIN,
 	MCS_PGPGOUT,
 	MCS_SWAP,
@@ -2705,8 +2917,8 @@
 	s->stat[MCS_CACHE] += val * PAGE_SIZE;
 	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_RSS);
 	s->stat[MCS_RSS] += val * PAGE_SIZE;
-	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_MAPPED_FILE);
-	s->stat[MCS_MAPPED_FILE] += val * PAGE_SIZE;
+	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_FILE_MAPPED);
+	s->stat[MCS_FILE_MAPPED] += val * PAGE_SIZE;
 	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGIN_COUNT);
 	s->stat[MCS_PGPGIN] += val;
 	val = mem_cgroup_read_stat(&mem->stat, MEM_CGROUP_STAT_PGPGOUT_COUNT);
@@ -3098,11 +3310,18 @@
 
 	/* root ? */
 	if (cont->parent == NULL) {
+		int cpu;
 		enable_swap_cgroup();
 		parent = NULL;
 		root_mem_cgroup = mem;
 		if (mem_cgroup_soft_limit_tree_init())
 			goto free_out;
+		for_each_possible_cpu(cpu) {
+			struct memcg_stock_pcp *stock =
+						&per_cpu(memcg_stock, cpu);
+			INIT_WORK(&stock->work, drain_local_stock);
+		}
+		hotcpu_notifier(memcg_stock_cpu_callback, 0);
 
 	} else {
 		parent = mem_cgroup_from_cont(cont->parent);
@@ -3171,12 +3390,10 @@
 				struct task_struct *p,
 				bool threadgroup)
 {
-	mutex_lock(&memcg_tasklist);
 	/*
 	 * FIXME: It's better to move charges of this process from old
 	 * memcg to new memcg. But it's just on TODO-List now.
 	 */
-	mutex_unlock(&memcg_tasklist);
 }
 
 struct cgroup_subsys mem_cgroup_subsys = {
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 50d4f8d..6a0466e 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -34,12 +34,16 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/page-flags.h>
+#include <linux/kernel-page-flags.h>
 #include <linux/sched.h>
 #include <linux/ksm.h>
 #include <linux/rmap.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 #include <linux/backing-dev.h>
+#include <linux/migrate.h>
+#include <linux/page-isolation.h>
+#include <linux/suspend.h>
 #include "internal.h"
 
 int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -48,6 +52,120 @@
 
 atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0);
 
+u32 hwpoison_filter_enable = 0;
+u32 hwpoison_filter_dev_major = ~0U;
+u32 hwpoison_filter_dev_minor = ~0U;
+u64 hwpoison_filter_flags_mask;
+u64 hwpoison_filter_flags_value;
+EXPORT_SYMBOL_GPL(hwpoison_filter_enable);
+EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);
+EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);
+EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask);
+EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value);
+
+static int hwpoison_filter_dev(struct page *p)
+{
+	struct address_space *mapping;
+	dev_t dev;
+
+	if (hwpoison_filter_dev_major == ~0U &&
+	    hwpoison_filter_dev_minor == ~0U)
+		return 0;
+
+	/*
+	 * page_mapping() does not accept slab page
+	 */
+	if (PageSlab(p))
+		return -EINVAL;
+
+	mapping = page_mapping(p);
+	if (mapping == NULL || mapping->host == NULL)
+		return -EINVAL;
+
+	dev = mapping->host->i_sb->s_dev;
+	if (hwpoison_filter_dev_major != ~0U &&
+	    hwpoison_filter_dev_major != MAJOR(dev))
+		return -EINVAL;
+	if (hwpoison_filter_dev_minor != ~0U &&
+	    hwpoison_filter_dev_minor != MINOR(dev))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int hwpoison_filter_flags(struct page *p)
+{
+	if (!hwpoison_filter_flags_mask)
+		return 0;
+
+	if ((stable_page_flags(p) & hwpoison_filter_flags_mask) ==
+				    hwpoison_filter_flags_value)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+/*
+ * This allows stress tests to limit test scope to a collection of tasks
+ * by putting them under some memcg. This prevents killing unrelated/important
+ * processes such as /sbin/init. Note that the target task may share clean
+ * pages with init (eg. libc text), which is harmless. If the target task
+ * share _dirty_ pages with another task B, the test scheme must make sure B
+ * is also included in the memcg. At last, due to race conditions this filter
+ * can only guarantee that the page either belongs to the memcg tasks, or is
+ * a freed page.
+ */
+#ifdef	CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+u64 hwpoison_filter_memcg;
+EXPORT_SYMBOL_GPL(hwpoison_filter_memcg);
+static int hwpoison_filter_task(struct page *p)
+{
+	struct mem_cgroup *mem;
+	struct cgroup_subsys_state *css;
+	unsigned long ino;
+
+	if (!hwpoison_filter_memcg)
+		return 0;
+
+	mem = try_get_mem_cgroup_from_page(p);
+	if (!mem)
+		return -EINVAL;
+
+	css = mem_cgroup_css(mem);
+	/* root_mem_cgroup has NULL dentries */
+	if (!css->cgroup->dentry)
+		return -EINVAL;
+
+	ino = css->cgroup->dentry->d_inode->i_ino;
+	css_put(css);
+
+	if (ino != hwpoison_filter_memcg)
+		return -EINVAL;
+
+	return 0;
+}
+#else
+static int hwpoison_filter_task(struct page *p) { return 0; }
+#endif
+
+int hwpoison_filter(struct page *p)
+{
+	if (!hwpoison_filter_enable)
+		return 0;
+
+	if (hwpoison_filter_dev(p))
+		return -EINVAL;
+
+	if (hwpoison_filter_flags(p))
+		return -EINVAL;
+
+	if (hwpoison_filter_task(p))
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hwpoison_filter);
+
 /*
  * Send all the processes who have the page mapped an ``action optional''
  * signal.
@@ -83,6 +201,36 @@
 }
 
 /*
+ * When a unknown page type is encountered drain as many buffers as possible
+ * in the hope to turn the page into a LRU or free page, which we can handle.
+ */
+void shake_page(struct page *p, int access)
+{
+	if (!PageSlab(p)) {
+		lru_add_drain_all();
+		if (PageLRU(p))
+			return;
+		drain_all_pages();
+		if (PageLRU(p) || is_free_buddy_page(p))
+			return;
+	}
+
+	/*
+	 * Only all shrink_slab here (which would also
+	 * shrink other caches) if access is not potentially fatal.
+	 */
+	if (access) {
+		int nr;
+		do {
+			nr = shrink_slab(1000, GFP_KERNEL, 1000);
+			if (page_count(p) == 0)
+				break;
+		} while (nr > 10);
+	}
+}
+EXPORT_SYMBOL_GPL(shake_page);
+
+/*
  * Kill all processes that have a poisoned page mapped and then isolate
  * the page.
  *
@@ -177,7 +325,6 @@
 			 * In case something went wrong with munmapping
 			 * make sure the process doesn't catch the
 			 * signal and then access the memory. Just kill it.
-			 * the signal handlers
 			 */
 			if (fail || tk->addr_valid == 0) {
 				printk(KERN_ERR
@@ -314,34 +461,50 @@
  */
 
 enum outcome {
-	FAILED,		/* Error handling failed */
+	IGNORED,	/* Error: cannot be handled */
+	FAILED,		/* Error: handling failed */
 	DELAYED,	/* Will be handled later */
-	IGNORED,	/* Error safely ignored */
 	RECOVERED,	/* Successfully recovered */
 };
 
 static const char *action_name[] = {
+	[IGNORED] = "Ignored",
 	[FAILED] = "Failed",
 	[DELAYED] = "Delayed",
-	[IGNORED] = "Ignored",
 	[RECOVERED] = "Recovered",
 };
 
 /*
+ * XXX: It is possible that a page is isolated from LRU cache,
+ * and then kept in swap cache or failed to remove from page cache.
+ * The page count will stop it from being freed by unpoison.
+ * Stress tests should be aware of this memory leak problem.
+ */
+static int delete_from_lru_cache(struct page *p)
+{
+	if (!isolate_lru_page(p)) {
+		/*
+		 * Clear sensible page flags, so that the buddy system won't
+		 * complain when the page is unpoison-and-freed.
+		 */
+		ClearPageActive(p);
+		ClearPageUnevictable(p);
+		/*
+		 * drop the page count elevated by isolate_lru_page()
+		 */
+		page_cache_release(p);
+		return 0;
+	}
+	return -EIO;
+}
+
+/*
  * Error hit kernel page.
  * Do nothing, try to be lucky and not touch this instead. For a few cases we
  * could be more sophisticated.
  */
 static int me_kernel(struct page *p, unsigned long pfn)
 {
-	return DELAYED;
-}
-
-/*
- * Already poisoned page.
- */
-static int me_ignore(struct page *p, unsigned long pfn)
-{
 	return IGNORED;
 }
 
@@ -355,14 +518,6 @@
 }
 
 /*
- * Free memory
- */
-static int me_free(struct page *p, unsigned long pfn)
-{
-	return DELAYED;
-}
-
-/*
  * Clean (or cleaned) page cache page.
  */
 static int me_pagecache_clean(struct page *p, unsigned long pfn)
@@ -371,6 +526,8 @@
 	int ret = FAILED;
 	struct address_space *mapping;
 
+	delete_from_lru_cache(p);
+
 	/*
 	 * For anonymous pages we're done the only reference left
 	 * should be the one m_f() holds.
@@ -500,14 +657,20 @@
 	/* Trigger EIO in shmem: */
 	ClearPageUptodate(p);
 
-	return DELAYED;
+	if (!delete_from_lru_cache(p))
+		return DELAYED;
+	else
+		return FAILED;
 }
 
 static int me_swapcache_clean(struct page *p, unsigned long pfn)
 {
 	delete_from_swap_cache(p);
 
-	return RECOVERED;
+	if (!delete_from_lru_cache(p))
+		return RECOVERED;
+	else
+		return FAILED;
 }
 
 /*
@@ -550,7 +713,6 @@
 #define tail		(1UL << PG_tail)
 #define compound	(1UL << PG_compound)
 #define slab		(1UL << PG_slab)
-#define buddy		(1UL << PG_buddy)
 #define reserved	(1UL << PG_reserved)
 
 static struct page_state {
@@ -559,8 +721,11 @@
 	char *msg;
 	int (*action)(struct page *p, unsigned long pfn);
 } error_states[] = {
-	{ reserved,	reserved,	"reserved kernel",	me_ignore },
-	{ buddy,	buddy,		"free kernel",	me_free },
+	{ reserved,	reserved,	"reserved kernel",	me_kernel },
+	/*
+	 * free pages are specially detected outside this table:
+	 * PG_buddy pages only make a small fraction of all free pages.
+	 */
 
 	/*
 	 * Could in theory check if slab page is free or if we can drop
@@ -587,7 +752,6 @@
 
 	{ lru|dirty,	lru|dirty,	"LRU",		me_pagecache_dirty },
 	{ lru|dirty,	lru,		"clean LRU",	me_pagecache_clean },
-	{ swapbacked,	swapbacked,	"anonymous",	me_pagecache_clean },
 
 	/*
 	 * Catchall entry: must be at end.
@@ -595,20 +759,31 @@
 	{ 0,		0,		"unknown page state",	me_unknown },
 };
 
+#undef dirty
+#undef sc
+#undef unevict
+#undef mlock
+#undef writeback
+#undef lru
+#undef swapbacked
+#undef head
+#undef tail
+#undef compound
+#undef slab
+#undef reserved
+
 static void action_result(unsigned long pfn, char *msg, int result)
 {
-	struct page *page = NULL;
-	if (pfn_valid(pfn))
-		page = pfn_to_page(pfn);
+	struct page *page = pfn_to_page(pfn);
 
 	printk(KERN_ERR "MCE %#lx: %s%s page recovery: %s\n",
 		pfn,
-		page && PageDirty(page) ? "dirty " : "",
+		PageDirty(page) ? "dirty " : "",
 		msg, action_name[result]);
 }
 
 static int page_action(struct page_state *ps, struct page *p,
-			unsigned long pfn, int ref)
+			unsigned long pfn)
 {
 	int result;
 	int count;
@@ -616,18 +791,22 @@
 	result = ps->action(p, pfn);
 	action_result(pfn, ps->msg, result);
 
-	count = page_count(p) - 1 - ref;
-	if (count != 0)
+	count = page_count(p) - 1;
+	if (ps->action == me_swapcache_dirty && result == DELAYED)
+		count--;
+	if (count != 0) {
 		printk(KERN_ERR
 		       "MCE %#lx: %s page still referenced by %d users\n",
 		       pfn, ps->msg, count);
+		result = FAILED;
+	}
 
 	/* Could do more checks here if page looks ok */
 	/*
 	 * Could adjust zone counters here to correct for the missing page.
 	 */
 
-	return result == RECOVERED ? 0 : -EBUSY;
+	return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
 }
 
 #define N_UNMAP_TRIES 5
@@ -636,7 +815,7 @@
  * Do all that is necessary to remove user space mappings. Unmap
  * the pages and send SIGBUS to the processes if the data was dirty.
  */
-static void hwpoison_user_mappings(struct page *p, unsigned long pfn,
+static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
 				  int trapno)
 {
 	enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
@@ -646,15 +825,18 @@
 	int i;
 	int kill = 1;
 
-	if (PageReserved(p) || PageCompound(p) || PageSlab(p) || PageKsm(p))
-		return;
+	if (PageReserved(p) || PageSlab(p))
+		return SWAP_SUCCESS;
 
 	/*
 	 * This check implies we don't kill processes if their pages
 	 * are in the swap cache early. Those are always late kills.
 	 */
 	if (!page_mapped(p))
-		return;
+		return SWAP_SUCCESS;
+
+	if (PageCompound(p) || PageKsm(p))
+		return SWAP_FAIL;
 
 	if (PageSwapCache(p)) {
 		printk(KERN_ERR
@@ -665,6 +847,8 @@
 	/*
 	 * Propagate the dirty bit from PTEs to struct page first, because we
 	 * need this to decide if we should kill or just drop the page.
+	 * XXX: the dirty test could be racy: set_page_dirty() may not always
+	 * be called inside page lock (it's recommended but not enforced).
 	 */
 	mapping = page_mapping(p);
 	if (!PageDirty(p) && mapping && mapping_cap_writeback_dirty(mapping)) {
@@ -716,11 +900,12 @@
 	 */
 	kill_procs_ao(&tokill, !!PageDirty(p), trapno,
 		      ret != SWAP_SUCCESS, pfn);
+
+	return ret;
 }
 
-int __memory_failure(unsigned long pfn, int trapno, int ref)
+int __memory_failure(unsigned long pfn, int trapno, int flags)
 {
-	unsigned long lru_flag;
 	struct page_state *ps;
 	struct page *p;
 	int res;
@@ -729,13 +914,15 @@
 		panic("Memory failure from trap %d on page %lx", trapno, pfn);
 
 	if (!pfn_valid(pfn)) {
-		action_result(pfn, "memory outside kernel control", IGNORED);
-		return -EIO;
+		printk(KERN_ERR
+		       "MCE %#lx: memory outside kernel control\n",
+		       pfn);
+		return -ENXIO;
 	}
 
 	p = pfn_to_page(pfn);
 	if (TestSetPageHWPoison(p)) {
-		action_result(pfn, "already hardware poisoned", IGNORED);
+		printk(KERN_ERR "MCE %#lx: already hardware poisoned\n", pfn);
 		return 0;
 	}
 
@@ -752,9 +939,15 @@
 	 * In fact it's dangerous to directly bump up page count from 0,
 	 * that may make page_freeze_refs()/page_unfreeze_refs() mismatch.
 	 */
-	if (!get_page_unless_zero(compound_head(p))) {
-		action_result(pfn, "free or high order kernel", IGNORED);
-		return PageBuddy(compound_head(p)) ? 0 : -EBUSY;
+	if (!(flags & MF_COUNT_INCREASED) &&
+		!get_page_unless_zero(compound_head(p))) {
+		if (is_free_buddy_page(p)) {
+			action_result(pfn, "free buddy", DELAYED);
+			return 0;
+		} else {
+			action_result(pfn, "high order kernel", IGNORED);
+			return -EBUSY;
+		}
 	}
 
 	/*
@@ -766,14 +959,19 @@
 	 * walked by the page reclaim code, however that's not a big loss.
 	 */
 	if (!PageLRU(p))
-		lru_add_drain_all();
-	lru_flag = p->flags & lru;
-	if (isolate_lru_page(p)) {
+		shake_page(p, 0);
+	if (!PageLRU(p)) {
+		/*
+		 * shake_page could have turned it free.
+		 */
+		if (is_free_buddy_page(p)) {
+			action_result(pfn, "free buddy, 2nd try", DELAYED);
+			return 0;
+		}
 		action_result(pfn, "non LRU", IGNORED);
 		put_page(p);
 		return -EBUSY;
 	}
-	page_cache_release(p);
 
 	/*
 	 * Lock the page and wait for writeback to finish.
@@ -781,26 +979,48 @@
 	 * and in many cases impossible, so we just avoid it here.
 	 */
 	lock_page_nosync(p);
+
+	/*
+	 * unpoison always clear PG_hwpoison inside page lock
+	 */
+	if (!PageHWPoison(p)) {
+		printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn);
+		res = 0;
+		goto out;
+	}
+	if (hwpoison_filter(p)) {
+		if (TestClearPageHWPoison(p))
+			atomic_long_dec(&mce_bad_pages);
+		unlock_page(p);
+		put_page(p);
+		return 0;
+	}
+
 	wait_on_page_writeback(p);
 
 	/*
 	 * Now take care of user space mappings.
+	 * Abort on fail: __remove_from_page_cache() assumes unmapped page.
 	 */
-	hwpoison_user_mappings(p, pfn, trapno);
+	if (hwpoison_user_mappings(p, pfn, trapno) != SWAP_SUCCESS) {
+		printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn);
+		res = -EBUSY;
+		goto out;
+	}
 
 	/*
 	 * Torn down by someone else?
 	 */
-	if ((lru_flag & lru) && !PageSwapCache(p) && p->mapping == NULL) {
+	if (PageLRU(p) && !PageSwapCache(p) && p->mapping == NULL) {
 		action_result(pfn, "already truncated LRU", IGNORED);
-		res = 0;
+		res = -EBUSY;
 		goto out;
 	}
 
 	res = -EBUSY;
 	for (ps = error_states;; ps++) {
-		if (((p->flags | lru_flag)& ps->mask) == ps->res) {
-			res = page_action(ps, p, pfn, ref);
+		if ((p->flags & ps->mask) == ps->res) {
+			res = page_action(ps, p, pfn);
 			break;
 		}
 	}
@@ -831,3 +1051,235 @@
 {
 	__memory_failure(pfn, trapno, 0);
 }
+
+/**
+ * unpoison_memory - Unpoison a previously poisoned page
+ * @pfn: Page number of the to be unpoisoned page
+ *
+ * Software-unpoison a page that has been poisoned by
+ * memory_failure() earlier.
+ *
+ * This is only done on the software-level, so it only works
+ * for linux injected failures, not real hardware failures
+ *
+ * Returns 0 for success, otherwise -errno.
+ */
+int unpoison_memory(unsigned long pfn)
+{
+	struct page *page;
+	struct page *p;
+	int freeit = 0;
+
+	if (!pfn_valid(pfn))
+		return -ENXIO;
+
+	p = pfn_to_page(pfn);
+	page = compound_head(p);
+
+	if (!PageHWPoison(p)) {
+		pr_debug("MCE: Page was already unpoisoned %#lx\n", pfn);
+		return 0;
+	}
+
+	if (!get_page_unless_zero(page)) {
+		if (TestClearPageHWPoison(p))
+			atomic_long_dec(&mce_bad_pages);
+		pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn);
+		return 0;
+	}
+
+	lock_page_nosync(page);
+	/*
+	 * This test is racy because PG_hwpoison is set outside of page lock.
+	 * That's acceptable because that won't trigger kernel panic. Instead,
+	 * the PG_hwpoison page will be caught and isolated on the entrance to
+	 * the free buddy page pool.
+	 */
+	if (TestClearPageHWPoison(p)) {
+		pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn);
+		atomic_long_dec(&mce_bad_pages);
+		freeit = 1;
+	}
+	unlock_page(page);
+
+	put_page(page);
+	if (freeit)
+		put_page(page);
+
+	return 0;
+}
+EXPORT_SYMBOL(unpoison_memory);
+
+static struct page *new_page(struct page *p, unsigned long private, int **x)
+{
+	int nid = page_to_nid(p);
+	return alloc_pages_exact_node(nid, GFP_HIGHUSER_MOVABLE, 0);
+}
+
+/*
+ * Safely get reference count of an arbitrary page.
+ * Returns 0 for a free page, -EIO for a zero refcount page
+ * that is not free, and 1 for any other page type.
+ * For 1 the page is returned with increased page count, otherwise not.
+ */
+static int get_any_page(struct page *p, unsigned long pfn, int flags)
+{
+	int ret;
+
+	if (flags & MF_COUNT_INCREASED)
+		return 1;
+
+	/*
+	 * The lock_system_sleep prevents a race with memory hotplug,
+	 * because the isolation assumes there's only a single user.
+	 * This is a big hammer, a better would be nicer.
+	 */
+	lock_system_sleep();
+
+	/*
+	 * Isolate the page, so that it doesn't get reallocated if it
+	 * was free.
+	 */
+	set_migratetype_isolate(p);
+	if (!get_page_unless_zero(compound_head(p))) {
+		if (is_free_buddy_page(p)) {
+			pr_debug("get_any_page: %#lx free buddy page\n", pfn);
+			/* Set hwpoison bit while page is still isolated */
+			SetPageHWPoison(p);
+			ret = 0;
+		} else {
+			pr_debug("get_any_page: %#lx: unknown zero refcount page type %lx\n",
+				pfn, p->flags);
+			ret = -EIO;
+		}
+	} else {
+		/* Not a free page */
+		ret = 1;
+	}
+	unset_migratetype_isolate(p);
+	unlock_system_sleep();
+	return ret;
+}
+
+/**
+ * soft_offline_page - Soft offline a page.
+ * @page: page to offline
+ * @flags: flags. Same as memory_failure().
+ *
+ * Returns 0 on success, otherwise negated errno.
+ *
+ * Soft offline a page, by migration or invalidation,
+ * without killing anything. This is for the case when
+ * a page is not corrupted yet (so it's still valid to access),
+ * but has had a number of corrected errors and is better taken
+ * out.
+ *
+ * The actual policy on when to do that is maintained by
+ * user space.
+ *
+ * This should never impact any application or cause data loss,
+ * however it might take some time.
+ *
+ * This is not a 100% solution for all memory, but tries to be
+ * ``good enough'' for the majority of memory.
+ */
+int soft_offline_page(struct page *page, int flags)
+{
+	int ret;
+	unsigned long pfn = page_to_pfn(page);
+
+	ret = get_any_page(page, pfn, flags);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		goto done;
+
+	/*
+	 * Page cache page we can handle?
+	 */
+	if (!PageLRU(page)) {
+		/*
+		 * Try to free it.
+		 */
+		put_page(page);
+		shake_page(page, 1);
+
+		/*
+		 * Did it turn free?
+		 */
+		ret = get_any_page(page, pfn, 0);
+		if (ret < 0)
+			return ret;
+		if (ret == 0)
+			goto done;
+	}
+	if (!PageLRU(page)) {
+		pr_debug("soft_offline: %#lx: unknown non LRU page type %lx\n",
+				pfn, page->flags);
+		return -EIO;
+	}
+
+	lock_page(page);
+	wait_on_page_writeback(page);
+
+	/*
+	 * Synchronized using the page lock with memory_failure()
+	 */
+	if (PageHWPoison(page)) {
+		unlock_page(page);
+		put_page(page);
+		pr_debug("soft offline: %#lx page already poisoned\n", pfn);
+		return -EBUSY;
+	}
+
+	/*
+	 * Try to invalidate first. This should work for
+	 * non dirty unmapped page cache pages.
+	 */
+	ret = invalidate_inode_page(page);
+	unlock_page(page);
+
+	/*
+	 * Drop count because page migration doesn't like raised
+	 * counts. The page could get re-allocated, but if it becomes
+	 * LRU the isolation will just fail.
+	 * RED-PEN would be better to keep it isolated here, but we
+	 * would need to fix isolation locking first.
+	 */
+	put_page(page);
+	if (ret == 1) {
+		ret = 0;
+		pr_debug("soft_offline: %#lx: invalidated\n", pfn);
+		goto done;
+	}
+
+	/*
+	 * Simple invalidation didn't work.
+	 * Try to migrate to a new page instead. migrate.c
+	 * handles a large number of cases for us.
+	 */
+	ret = isolate_lru_page(page);
+	if (!ret) {
+		LIST_HEAD(pagelist);
+
+		list_add(&page->lru, &pagelist);
+		ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
+		if (ret) {
+			pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+				pfn, ret, page->flags);
+			if (ret > 0)
+				ret = -EIO;
+		}
+	} else {
+		pr_debug("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
+				pfn, ret, page_count(page), page->flags);
+	}
+	if (ret)
+		return ret;
+
+done:
+	atomic_long_add(1, &mce_bad_pages);
+	SetPageHWPoison(page);
+	/* keep elevated page count for bad page */
+	return ret;
+}
diff --git a/mm/memory.c b/mm/memory.c
index a54b2c4..09e4b1b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -956,6 +956,7 @@
 		details = NULL;
 
 	BUG_ON(addr >= end);
+	mem_cgroup_uncharge_start();
 	tlb_start_vma(tlb, vma);
 	pgd = pgd_offset(vma->vm_mm, addr);
 	do {
@@ -968,6 +969,7 @@
 						zap_work, details);
 	} while (pgd++, addr = next, (addr != end && *zap_work > 0));
 	tlb_end_vma(tlb, vma);
+	mem_cgroup_uncharge_end();
 
 	return addr;
 }
@@ -2553,6 +2555,10 @@
 		ret = VM_FAULT_MAJOR;
 		count_vm_event(PGMAJFAULT);
 	} else if (PageHWPoison(page)) {
+		/*
+		 * hwpoisoned dirty swapcache pages are kept for killing
+		 * owner processes (which may be unknown at hwpoison time)
+		 */
 		ret = VM_FAULT_HWPOISON;
 		delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
 		goto out_release;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 492c986..f52481b 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -196,27 +196,46 @@
 /*
  * Determine the type of allocation constraint.
  */
-static inline enum oom_constraint constrained_alloc(struct zonelist *zonelist,
-						    gfp_t gfp_mask)
-{
 #ifdef CONFIG_NUMA
+static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
+				    gfp_t gfp_mask, nodemask_t *nodemask)
+{
 	struct zone *zone;
 	struct zoneref *z;
 	enum zone_type high_zoneidx = gfp_zone(gfp_mask);
-	nodemask_t nodes = node_states[N_HIGH_MEMORY];
 
-	for_each_zone_zonelist(zone, z, zonelist, high_zoneidx)
-		if (cpuset_zone_allowed_softwall(zone, gfp_mask))
-			node_clear(zone_to_nid(zone), nodes);
-		else
-			return CONSTRAINT_CPUSET;
+	/*
+	 * Reach here only when __GFP_NOFAIL is used. So, we should avoid
+	 * to kill current.We have to random task kill in this case.
+	 * Hopefully, CONSTRAINT_THISNODE...but no way to handle it, now.
+	 */
+	if (gfp_mask & __GFP_THISNODE)
+		return CONSTRAINT_NONE;
 
-	if (!nodes_empty(nodes))
+	/*
+	 * The nodemask here is a nodemask passed to alloc_pages(). Now,
+	 * cpuset doesn't use this nodemask for its hardwall/softwall/hierarchy
+	 * feature. mempolicy is an only user of nodemask here.
+	 * check mempolicy's nodemask contains all N_HIGH_MEMORY
+	 */
+	if (nodemask && !nodes_subset(node_states[N_HIGH_MEMORY], *nodemask))
 		return CONSTRAINT_MEMORY_POLICY;
-#endif
+
+	/* Check this allocation failure is caused by cpuset's wall function */
+	for_each_zone_zonelist_nodemask(zone, z, zonelist,
+			high_zoneidx, nodemask)
+		if (!cpuset_zone_allowed_softwall(zone, gfp_mask))
+			return CONSTRAINT_CPUSET;
 
 	return CONSTRAINT_NONE;
 }
+#else
+static enum oom_constraint constrained_alloc(struct zonelist *zonelist,
+				gfp_t gfp_mask, nodemask_t *nodemask)
+{
+	return CONSTRAINT_NONE;
+}
+#endif
 
 /*
  * Simple selection loop. We chose the process with the highest
@@ -337,7 +356,8 @@
 	} while_each_thread(g, p);
 }
 
-static void dump_header(gfp_t gfp_mask, int order, struct mem_cgroup *mem)
+static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
+							struct mem_cgroup *mem)
 {
 	pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
 		"oom_adj=%d\n",
@@ -346,12 +366,14 @@
 	cpuset_print_task_mems_allowed(current);
 	task_unlock(current);
 	dump_stack();
-	mem_cgroup_print_oom_info(mem, current);
+	mem_cgroup_print_oom_info(mem, p);
 	show_mem();
 	if (sysctl_oom_dump_tasks)
 		dump_tasks(mem);
 }
 
+#define K(x) ((x) << (PAGE_SHIFT-10))
+
 /*
  * Send SIGKILL to the selected  process irrespective of  CAP_SYS_RAW_IO
  * flag though it's unlikely that  we select a process with CAP_SYS_RAW_IO
@@ -365,15 +387,23 @@
 		return;
 	}
 
+	task_lock(p);
 	if (!p->mm) {
 		WARN_ON(1);
-		printk(KERN_WARNING "tried to kill an mm-less task!\n");
+		printk(KERN_WARNING "tried to kill an mm-less task %d (%s)!\n",
+			task_pid_nr(p), p->comm);
+		task_unlock(p);
 		return;
 	}
 
 	if (verbose)
-		printk(KERN_ERR "Killed process %d (%s)\n",
-				task_pid_nr(p), p->comm);
+		printk(KERN_ERR "Killed process %d (%s) "
+		       "vsz:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+		       task_pid_nr(p), p->comm,
+		       K(p->mm->total_vm),
+		       K(get_mm_counter(p->mm, anon_rss)),
+		       K(get_mm_counter(p->mm, file_rss)));
+	task_unlock(p);
 
 	/*
 	 * We give our sacrificial lamb high priority and access to
@@ -411,7 +441,7 @@
 	struct task_struct *c;
 
 	if (printk_ratelimit())
-		dump_header(gfp_mask, order, mem);
+		dump_header(p, gfp_mask, order, mem);
 
 	/*
 	 * If the task is already exiting, don't alarm the sysadmin or kill
@@ -547,7 +577,7 @@
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (!p) {
 		read_unlock(&tasklist_lock);
-		dump_header(gfp_mask, order, NULL);
+		dump_header(NULL, gfp_mask, order, NULL);
 		panic("Out of memory and no killable processes...\n");
 	}
 
@@ -603,7 +633,8 @@
  * OR try to be smart about which process to kill. Note that we
  * don't have to be perfect here, we just have to be good.
  */
-void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
+void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
+		int order, nodemask_t *nodemask)
 {
 	unsigned long freed = 0;
 	enum oom_constraint constraint;
@@ -614,7 +645,7 @@
 		return;
 
 	if (sysctl_panic_on_oom == 2) {
-		dump_header(gfp_mask, order, NULL);
+		dump_header(NULL, gfp_mask, order, NULL);
 		panic("out of memory. Compulsory panic_on_oom is selected.\n");
 	}
 
@@ -622,7 +653,7 @@
 	 * Check if there were limitations on the allocation (only relevant for
 	 * NUMA) that may require different handling.
 	 */
-	constraint = constrained_alloc(zonelist, gfp_mask);
+	constraint = constrained_alloc(zonelist, gfp_mask, nodemask);
 	read_lock(&tasklist_lock);
 
 	switch (constraint) {
@@ -633,7 +664,7 @@
 
 	case CONSTRAINT_NONE:
 		if (sysctl_panic_on_oom) {
-			dump_header(gfp_mask, order, NULL);
+			dump_header(NULL, gfp_mask, order, NULL);
 			panic("out of memory. panic_on_oom is selected\n");
 		}
 		/* Fall-through */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 59d2e88..74af449 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1654,12 +1654,22 @@
 	if (page)
 		goto out;
 
-	/* The OOM killer will not help higher order allocs */
-	if (order > PAGE_ALLOC_COSTLY_ORDER && !(gfp_mask & __GFP_NOFAIL))
-		goto out;
-
+	if (!(gfp_mask & __GFP_NOFAIL)) {
+		/* The OOM killer will not help higher order allocs */
+		if (order > PAGE_ALLOC_COSTLY_ORDER)
+			goto out;
+		/*
+		 * GFP_THISNODE contains __GFP_NORETRY and we never hit this.
+		 * Sanity check for bare calls of __GFP_THISNODE, not real OOM.
+		 * The caller should handle page allocation failure by itself if
+		 * it specifies __GFP_THISNODE.
+		 * Note: Hugepage uses it but will hit PAGE_ALLOC_COSTLY_ORDER.
+		 */
+		if (gfp_mask & __GFP_THISNODE)
+			goto out;
+	}
 	/* Exhausted what can be done so it's blamo time */
-	out_of_memory(zonelist, gfp_mask, order);
+	out_of_memory(zonelist, gfp_mask, order, nodemask);
 
 out:
 	clear_zonelist_oom(zonelist, gfp_mask);
@@ -3123,7 +3133,7 @@
 
 		if (percpu_pagelist_fraction)
 			setup_pagelist_highmark(zone_pcp(zone, cpu),
-			 	(zone->present_pages / percpu_pagelist_fraction));
+			    (zone->present_pages / percpu_pagelist_fraction));
 	}
 
 	return 0;
@@ -5081,3 +5091,24 @@
 	spin_unlock_irqrestore(&zone->lock, flags);
 }
 #endif
+
+#ifdef CONFIG_MEMORY_FAILURE
+bool is_free_buddy_page(struct page *page)
+{
+	struct zone *zone = page_zone(page);
+	unsigned long pfn = page_to_pfn(page);
+	unsigned long flags;
+	int order;
+
+	spin_lock_irqsave(&zone->lock, flags);
+	for (order = 0; order < MAX_ORDER; order++) {
+		struct page *page_head = page - (pfn & ((1 << order) - 1));
+
+		if (PageBuddy(page_head) && page_order(page_head) >= order)
+			break;
+	}
+	spin_unlock_irqrestore(&zone->lock, flags);
+
+	return order < MAX_ORDER;
+}
+#endif
diff --git a/mm/readahead.c b/mm/readahead.c
index aa1aa23..033bc13 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -547,5 +547,17 @@
 
 	/* do read-ahead */
 	ondemand_readahead(mapping, ra, filp, true, offset, req_size);
+
+#ifdef CONFIG_BLOCK
+	/*
+	 * Normally the current page is !uptodate and lock_page() will be
+	 * immediately called to implicitly unplug the device. However this
+	 * is not always true for RAID conifgurations, where data arrives
+	 * not strictly in their submission order. In this case we need to
+	 * explicitly kick off the IO.
+	 */
+	if (PageUptodate(page))
+		blk_run_backing_dev(mapping->backing_dev_info, NULL);
+#endif
 }
 EXPORT_SYMBOL_GPL(page_cache_async_readahead);
diff --git a/mm/rmap.c b/mm/rmap.c
index 98135db..278cd27 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -721,7 +721,7 @@
 {
 	if (atomic_inc_and_test(&page->_mapcount)) {
 		__inc_zone_page_state(page, NR_FILE_MAPPED);
-		mem_cgroup_update_mapped_file_stat(page, 1);
+		mem_cgroup_update_file_mapped(page, 1);
 	}
 }
 
@@ -753,8 +753,8 @@
 		__dec_zone_page_state(page, NR_ANON_PAGES);
 	} else {
 		__dec_zone_page_state(page, NR_FILE_MAPPED);
+		mem_cgroup_update_file_mapped(page, -1);
 	}
-	mem_cgroup_update_mapped_file_stat(page, -1);
 	/*
 	 * It would be tidy to reset the PageAnon mapping here,
 	 * but that might overwrite a racing page_add_anon_rmap
diff --git a/mm/shmem.c b/mm/shmem.c
index 4fb41c8..eef4ebe 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -29,7 +29,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/swap.h>
-#include <linux/ima.h>
 
 static struct vfsmount *shm_mnt;
 
@@ -42,6 +41,7 @@
 
 #include <linux/xattr.h>
 #include <linux/exportfs.h>
+#include <linux/posix_acl.h>
 #include <linux/generic_acl.h>
 #include <linux/mman.h>
 #include <linux/string.h>
@@ -810,7 +810,7 @@
 		error = inode_setattr(inode, attr);
 #ifdef CONFIG_TMPFS_POSIX_ACL
 	if (!error && (attr->ia_valid & ATTR_MODE))
-		error = generic_acl_chmod(inode, &shmem_acl_ops);
+		error = generic_acl_chmod(inode);
 #endif
 	if (page)
 		page_cache_release(page);
@@ -1824,11 +1824,15 @@
 				return error;
 			}
 		}
-		error = shmem_acl_init(inode, dir);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+		error = generic_acl_init(inode, dir);
 		if (error) {
 			iput(inode);
 			return error;
 		}
+#else
+		error = 0;
+#endif
 		if (dir->i_mode & S_ISGID) {
 			inode->i_gid = dir->i_gid;
 			if (S_ISDIR(mode))
@@ -2043,27 +2047,28 @@
  * filesystem level, though.
  */
 
-static size_t shmem_xattr_security_list(struct inode *inode, char *list,
+static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
 					size_t list_len, const char *name,
-					size_t name_len)
+					size_t name_len, int handler_flags)
 {
-	return security_inode_listsecurity(inode, list, list_len);
+	return security_inode_listsecurity(dentry->d_inode, list, list_len);
 }
 
-static int shmem_xattr_security_get(struct inode *inode, const char *name,
-				    void *buffer, size_t size)
+static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
+		void *buffer, size_t size, int handler_flags)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return xattr_getsecurity(inode, name, buffer, size);
+	return xattr_getsecurity(dentry->d_inode, name, buffer, size);
 }
 
-static int shmem_xattr_security_set(struct inode *inode, const char *name,
-				    const void *value, size_t size, int flags)
+static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
+		const void *value, size_t size, int flags, int handler_flags)
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return security_inode_setsecurity(inode, name, value, size, flags);
+	return security_inode_setsecurity(dentry->d_inode, name, value,
+					  size, flags);
 }
 
 static struct xattr_handler shmem_xattr_security_handler = {
@@ -2074,8 +2079,8 @@
 };
 
 static struct xattr_handler *shmem_xattr_handlers[] = {
-	&shmem_xattr_acl_access_handler,
-	&shmem_xattr_acl_default_handler,
+	&generic_acl_access_handler,
+	&generic_acl_default_handler,
 	&shmem_xattr_security_handler,
 	NULL
 };
@@ -2454,7 +2459,7 @@
 	.getxattr	= generic_getxattr,
 	.listxattr	= generic_listxattr,
 	.removexattr	= generic_removexattr,
-	.check_acl	= shmem_check_acl,
+	.check_acl	= generic_check_acl,
 #endif
 
 };
@@ -2477,7 +2482,7 @@
 	.getxattr	= generic_getxattr,
 	.listxattr	= generic_listxattr,
 	.removexattr	= generic_removexattr,
-	.check_acl	= shmem_check_acl,
+	.check_acl	= generic_check_acl,
 #endif
 };
 
@@ -2488,7 +2493,7 @@
 	.getxattr	= generic_getxattr,
 	.listxattr	= generic_listxattr,
 	.removexattr	= generic_removexattr,
-	.check_acl	= shmem_check_acl,
+	.check_acl	= generic_check_acl,
 #endif
 };
 
@@ -2626,7 +2631,8 @@
 	int error;
 	struct file *file;
 	struct inode *inode;
-	struct dentry *dentry, *root;
+	struct path path;
+	struct dentry *root;
 	struct qstr this;
 
 	if (IS_ERR(shm_mnt))
@@ -2643,38 +2649,35 @@
 	this.len = strlen(name);
 	this.hash = 0; /* will go */
 	root = shm_mnt->mnt_root;
-	dentry = d_alloc(root, &this);
-	if (!dentry)
+	path.dentry = d_alloc(root, &this);
+	if (!path.dentry)
 		goto put_memory;
-
-	error = -ENFILE;
-	file = get_empty_filp();
-	if (!file)
-		goto put_dentry;
+	path.mnt = mntget(shm_mnt);
 
 	error = -ENOSPC;
 	inode = shmem_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0, flags);
 	if (!inode)
-		goto close_file;
+		goto put_dentry;
 
-	d_instantiate(dentry, inode);
+	d_instantiate(path.dentry, inode);
 	inode->i_size = size;
 	inode->i_nlink = 0;	/* It is unlinked */
-	init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
-		  &shmem_file_operations);
-
 #ifndef CONFIG_MMU
 	error = ramfs_nommu_expand_for_mapping(inode, size);
 	if (error)
-		goto close_file;
+		goto put_dentry;
 #endif
-	ima_counts_get(file);
+
+	error = -ENFILE;
+	file = alloc_file(&path, FMODE_WRITE | FMODE_READ,
+		  &shmem_file_operations);
+	if (!file)
+		goto put_dentry;
+
 	return file;
 
-close_file:
-	put_filp(file);
 put_dentry:
-	dput(dentry);
+	path_put(&path);
 put_memory:
 	shmem_unacct_size(flags, size);
 	return ERR_PTR(error);
diff --git a/mm/shmem_acl.c b/mm/shmem_acl.c
deleted file mode 100644
index df2c87f..0000000
--- a/mm/shmem_acl.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * mm/shmem_acl.c
- *
- * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
- *
- * This file is released under the GPL.
- */
-
-#include <linux/fs.h>
-#include <linux/shmem_fs.h>
-#include <linux/xattr.h>
-#include <linux/generic_acl.h>
-
-/**
- * shmem_get_acl  -   generic_acl_operations->getacl() operation
- */
-static struct posix_acl *
-shmem_get_acl(struct inode *inode, int type)
-{
-	struct posix_acl *acl = NULL;
-
-	spin_lock(&inode->i_lock);
-	switch(type) {
-		case ACL_TYPE_ACCESS:
-			acl = posix_acl_dup(inode->i_acl);
-			break;
-
-		case ACL_TYPE_DEFAULT:
-			acl = posix_acl_dup(inode->i_default_acl);
-			break;
-	}
-	spin_unlock(&inode->i_lock);
-
-	return acl;
-}
-
-/**
- * shmem_set_acl  -   generic_acl_operations->setacl() operation
- */
-static void
-shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
-{
-	struct posix_acl *free = NULL;
-
-	spin_lock(&inode->i_lock);
-	switch(type) {
-		case ACL_TYPE_ACCESS:
-			free = inode->i_acl;
-			inode->i_acl = posix_acl_dup(acl);
-			break;
-
-		case ACL_TYPE_DEFAULT:
-			free = inode->i_default_acl;
-			inode->i_default_acl = posix_acl_dup(acl);
-			break;
-	}
-	spin_unlock(&inode->i_lock);
-	posix_acl_release(free);
-}
-
-struct generic_acl_operations shmem_acl_ops = {
-	.getacl = shmem_get_acl,
-	.setacl = shmem_set_acl,
-};
-
-/**
- * shmem_list_acl_access, shmem_get_acl_access, shmem_set_acl_access,
- * shmem_xattr_acl_access_handler  -  plumbing code to implement the
- * system.posix_acl_access xattr using the generic acl functions.
- */
-
-static size_t
-shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
-		      const char *name, size_t name_len)
-{
-	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
-				list, list_size);
-}
-
-static int
-shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
-		     size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
-			       size);
-}
-
-static int
-shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
-		     size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
-			       size);
-}
-
-struct xattr_handler shmem_xattr_acl_access_handler = {
-	.prefix = POSIX_ACL_XATTR_ACCESS,
-	.list	= shmem_list_acl_access,
-	.get	= shmem_get_acl_access,
-	.set	= shmem_set_acl_access,
-};
-
-/**
- * shmem_list_acl_default, shmem_get_acl_default, shmem_set_acl_default,
- * shmem_xattr_acl_default_handler  -  plumbing code to implement the
- * system.posix_acl_default xattr using the generic acl functions.
- */
-
-static size_t
-shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
-		       const char *name, size_t name_len)
-{
-	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
-				list, list_size);
-}
-
-static int
-shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
-		      size_t size)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
-			       size);
-}
-
-static int
-shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
-		      size_t size, int flags)
-{
-	if (strcmp(name, "") != 0)
-		return -EINVAL;
-	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
-			       size);
-}
-
-struct xattr_handler shmem_xattr_acl_default_handler = {
-	.prefix = POSIX_ACL_XATTR_DEFAULT,
-	.list	= shmem_list_acl_default,
-	.get	= shmem_get_acl_default,
-	.set	= shmem_set_acl_default,
-};
-
-/**
- * shmem_acl_init  -  Inizialize the acl(s) of a new inode
- */
-int
-shmem_acl_init(struct inode *inode, struct inode *dir)
-{
-	return generic_acl_init(inode, dir, &shmem_acl_ops);
-}
-
-/**
- * shmem_check_acl  -  check_acl() callback for generic_permission()
- */
-int
-shmem_check_acl(struct inode *inode, int mask)
-{
-	struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
-
-	if (acl) {
-		int error = posix_acl_permission(inode, acl, mask);
-		posix_acl_release(acl);
-		return error;
-	}
-	return -EAGAIN;
-}
diff --git a/mm/slab.c b/mm/slab.c
index 3f48229..e17cc2c 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2275,9 +2275,11 @@
 	/*
 	 * Determine if the slab management is 'on' or 'off' slab.
 	 * (bootstrapping cannot cope with offslab caches so don't do
-	 * it too early on.)
+	 * it too early on. Always use on-slab management when
+	 * SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
 	 */
-	if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)
+	if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init &&
+	    !(flags & SLAB_NOLEAKTRACE))
 		/*
 		 * Size is large, assume best to place the slab management obj
 		 * off-slab (should allow better packing of objs).
@@ -2596,8 +2598,8 @@
 		 * kmemleak does not treat the ->s_mem pointer as a reference
 		 * to the object. Otherwise we will not report the leak.
 		 */
-		kmemleak_scan_area(slabp, offsetof(struct slab, list),
-				   sizeof(struct list_head), local_flags);
+		kmemleak_scan_area(&slabp->list, sizeof(struct list_head),
+				   local_flags);
 		if (!slabp)
 			return NULL;
 	} else {
diff --git a/mm/truncate.c b/mm/truncate.c
index 2c147a7..342deee 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -272,6 +272,7 @@
 			pagevec_release(&pvec);
 			break;
 		}
+		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 
@@ -286,6 +287,7 @@
 			unlock_page(page);
 		}
 		pagevec_release(&pvec);
+		mem_cgroup_uncharge_end();
 	}
 }
 EXPORT_SYMBOL(truncate_inode_pages_range);
@@ -327,6 +329,7 @@
 	pagevec_init(&pvec, 0);
 	while (next <= end &&
 			pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 			pgoff_t index;
@@ -354,6 +357,7 @@
 				break;
 		}
 		pagevec_release(&pvec);
+		mem_cgroup_uncharge_end();
 		cond_resched();
 	}
 	return ret;
@@ -428,6 +432,7 @@
 	while (next <= end && !wrapped &&
 		pagevec_lookup(&pvec, mapping, next,
 			min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
+		mem_cgroup_uncharge_start();
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
 			pgoff_t page_index;
@@ -477,6 +482,7 @@
 			unlock_page(page);
 		}
 		pagevec_release(&pvec);
+		mem_cgroup_uncharge_end();
 		cond_resched();
 	}
 	return ret;
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 4dd873e..be1cb90 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -42,6 +42,8 @@
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
 
+#include <linux/syscalls.h> /* killme */
+
 #define P9_PORT 564
 #define MAX_SOCK_BUF (64*1024)
 #define MAXPOLLWADDR	2
@@ -788,24 +790,41 @@
 
 static int p9_socket_open(struct p9_client *client, struct socket *csocket)
 {
-	int fd, ret;
+	struct p9_trans_fd *p;
+	int ret, fd;
+
+	p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
 
 	csocket->sk->sk_allocation = GFP_NOIO;
 	fd = sock_map_fd(csocket, 0);
 	if (fd < 0) {
 		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
+		sock_release(csocket);
+		kfree(p);
 		return fd;
 	}
 
-	ret = p9_fd_open(client, fd, fd);
-	if (ret < 0) {
-		P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
+	get_file(csocket->file);
+	get_file(csocket->file);
+	p->wr = p->rd = csocket->file;
+	client->trans = p;
+	client->status = Connected;
+
+	sys_close(fd);	/* still racy */
+
+	p->rd->f_flags |= O_NONBLOCK;
+
+	p->conn = p9_conn_create(client);
+	if (IS_ERR(p->conn)) {
+		ret = PTR_ERR(p->conn);
+		p->conn = NULL;
+		kfree(p);
+		sockfd_put(csocket);
 		sockfd_put(csocket);
 		return ret;
 	}
-
-	((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK;
-
 	return 0;
 }
 
@@ -883,7 +902,6 @@
 	struct socket *csocket;
 	struct sockaddr_in sin_server;
 	struct p9_fd_opts opts;
-	struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
 
 	err = parse_opts(args, &opts);
 	if (err < 0)
@@ -897,12 +915,11 @@
 	sin_server.sin_family = AF_INET;
 	sin_server.sin_addr.s_addr = in_aton(addr);
 	sin_server.sin_port = htons(opts.port);
-	sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+	err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
 
-	if (!csocket) {
+	if (err) {
 		P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
-		err = -EIO;
-		goto error;
+		return err;
 	}
 
 	err = csocket->ops->connect(csocket,
@@ -912,30 +929,11 @@
 		P9_EPRINTK(KERN_ERR,
 			"p9_trans_tcp: problem connecting socket to %s\n",
 			addr);
-		goto error;
-	}
-
-	err = p9_socket_open(client, csocket);
-	if (err < 0)
-		goto error;
-
-	p = (struct p9_trans_fd *) client->trans;
-	p->conn = p9_conn_create(client);
-	if (IS_ERR(p->conn)) {
-		err = PTR_ERR(p->conn);
-		p->conn = NULL;
-		goto error;
-	}
-
-	return 0;
-
-error:
-	if (csocket)
 		sock_release(csocket);
+		return err;
+	}
 
-	kfree(p);
-
-	return err;
+	return p9_socket_open(client, csocket);
 }
 
 static int
@@ -944,49 +942,33 @@
 	int err;
 	struct socket *csocket;
 	struct sockaddr_un sun_server;
-	struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
 
 	csocket = NULL;
 
 	if (strlen(addr) > UNIX_PATH_MAX) {
 		P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
 			addr);
-		err = -ENAMETOOLONG;
-		goto error;
+		return -ENAMETOOLONG;
 	}
 
 	sun_server.sun_family = PF_UNIX;
 	strcpy(sun_server.sun_path, addr);
-	sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+	err = sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+	if (err < 0) {
+		P9_EPRINTK(KERN_ERR, "p9_trans_unix: problem creating socket\n");
+		return err;
+	}
 	err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
 			sizeof(struct sockaddr_un) - 1, 0);
 	if (err < 0) {
 		P9_EPRINTK(KERN_ERR,
 			"p9_trans_unix: problem connecting socket: %s: %d\n",
 			addr, err);
-		goto error;
-	}
-
-	err = p9_socket_open(client, csocket);
-	if (err < 0)
-		goto error;
-
-	p = (struct p9_trans_fd *) client->trans;
-	p->conn = p9_conn_create(client);
-	if (IS_ERR(p->conn)) {
-		err = PTR_ERR(p->conn);
-		p->conn = NULL;
-		goto error;
-	}
-
-	return 0;
-
-error:
-	if (csocket)
 		sock_release(csocket);
+		return err;
+	}
 
-	kfree(p);
-	return err;
+	return p9_socket_open(client, csocket);
 }
 
 static int
@@ -994,7 +976,7 @@
 {
 	int err;
 	struct p9_fd_opts opts;
-	struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
+	struct p9_trans_fd *p;
 
 	parse_opts(args, &opts);
 
@@ -1005,21 +987,19 @@
 
 	err = p9_fd_open(client, opts.rfd, opts.wfd);
 	if (err < 0)
-		goto error;
+		return err;
 
 	p = (struct p9_trans_fd *) client->trans;
 	p->conn = p9_conn_create(client);
 	if (IS_ERR(p->conn)) {
 		err = PTR_ERR(p->conn);
 		p->conn = NULL;
-		goto error;
+		fput(p->rd);
+		fput(p->wr);
+		return err;
 	}
 
 	return 0;
-
-error:
-	kfree(p);
-	return err;
 }
 
 static struct p9_trans_module p9_tcp_trans = {
diff --git a/net/core/dev.c b/net/core/dev.c
index 6fe7d73..be9924f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5035,6 +5035,11 @@
 		rollback_registered(dev);
 		dev->reg_state = NETREG_UNREGISTERED;
 	}
+	/*
+	 *	Prevent userspace races by waiting until the network
+	 *	device is fully setup before sending notifications.
+	 */
+	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
 
 out:
 	return ret;
@@ -5597,6 +5602,12 @@
 	/* Notify protocols, that a new device appeared. */
 	call_netdevice_notifiers(NETDEV_REGISTER, dev);
 
+	/*
+	 *	Prevent userspace races by waiting until the network
+	 *	device is fully setup before sending notifications.
+	 */
+	rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
+
 	synchronize_net();
 	err = 0;
 out:
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 33148a5..794bcb8 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1364,15 +1364,15 @@
 	case NETDEV_UNREGISTER:
 		rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
 		break;
-	case NETDEV_REGISTER:
-		rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
-		break;
 	case NETDEV_UP:
 	case NETDEV_DOWN:
 		rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
 		break;
+	case NETDEV_POST_INIT:
+	case NETDEV_REGISTER:
 	case NETDEV_CHANGE:
 	case NETDEV_GOING_DOWN:
+	case NETDEV_UNREGISTER_BATCH:
 		break;
 	default:
 		rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index bfa3e78..93c4e06 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -93,7 +93,7 @@
 
 
 /* Pipe buffer operations for a socket. */
-static struct pipe_buf_operations sock_pipe_buf_ops = {
+static const struct pipe_buf_operations sock_pipe_buf_ops = {
 	.can_merge = 0,
 	.map = generic_pipe_buf_map,
 	.unmap = generic_pipe_buf_unmap,
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 70491d9..0c94a1a 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -166,7 +166,7 @@
 
 	  If unsure, say Y. Note that if you want to use DHCP, a DHCP server
 	  must be operating on your network.  Read
-	  <file:Documentation/filesystems/nfsroot.txt> for details.
+	  <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
 
 config IP_PNP_BOOTP
 	bool "IP: BOOTP support"
@@ -181,7 +181,7 @@
 	  does BOOTP itself, providing all necessary information on the kernel
 	  command line, you can say N here. If unsure, say Y. Note that if you
 	  want to use BOOTP, a BOOTP server must be operating on your network.
-	  Read <file:Documentation/filesystems/nfsroot.txt> for details.
+	  Read <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
 
 config IP_PNP_RARP
 	bool "IP: RARP support"
@@ -194,7 +194,7 @@
 	  older protocol which is being obsoleted by BOOTP and DHCP), say Y
 	  here. Note that if you want to use RARP, a RARP server must be
 	  operating on your network. Read
-	  <file:Documentation/filesystems/nfsroot.txt> for details.
+	  <file:Documentation/filesystems/nfs/nfsroot.txt> for details.
 
 # not yet ready..
 #   bool '    IP: ARP support' CONFIG_IP_PNP_ARP
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 4e08b7f..10a6a60 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1446,7 +1446,7 @@
 
 /*
  *  Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
- *  command line parameter.  See Documentation/filesystems/nfsroot.txt.
+ *  command line parameter.  See Documentation/filesystems/nfs/nfsroot.txt.
  */
 static int __init ic_proto_name(char *name)
 {
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index fa2d6b6..331ead3 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -14,6 +14,7 @@
 #include <net/route.h>
 #include <net/ip.h>
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
 
@@ -34,6 +35,20 @@
 	return err;
 }
 
+static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
+					      struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP_DEFRAG_CONNTRACK_IN;
+	else
+		return IP_DEFRAG_CONNTRACK_OUT;
+}
+
 static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
 					  struct sk_buff *skb,
 					  const struct net_device *in,
@@ -50,10 +65,8 @@
 #endif
 	/* Gather fragments. */
 	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
-		if (nf_ct_ipv4_gather_frags(skb,
-					    hooknum == NF_INET_PRE_ROUTING ?
-					    IP_DEFRAG_CONNTRACK_IN :
-					    IP_DEFRAG_CONNTRACK_OUT))
+		enum ip_defrag_users user = nf_ct_defrag_user(hooknum, skb);
+		if (nf_ct_ipv4_gather_frags(skb, user))
 			return NF_STOLEN;
 	}
 	return NF_ACCEPT;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 26399ad..66fd80e 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -277,6 +277,13 @@
 
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV);
 
+	/* check for timestamp cookie support */
+	memset(&tcp_opt, 0, sizeof(tcp_opt));
+	tcp_parse_options(skb, &tcp_opt, &hash_location, 0);
+
+	if (tcp_opt.saw_tstamp)
+		cookie_check_timestamp(&tcp_opt);
+
 	ret = NULL;
 	req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */
 	if (!req)
@@ -292,6 +299,12 @@
 	ireq->loc_addr		= ip_hdr(skb)->daddr;
 	ireq->rmt_addr		= ip_hdr(skb)->saddr;
 	ireq->ecn_ok		= 0;
+	ireq->snd_wscale	= tcp_opt.snd_wscale;
+	ireq->rcv_wscale	= tcp_opt.rcv_wscale;
+	ireq->sack_ok		= tcp_opt.sack_ok;
+	ireq->wscale_ok		= tcp_opt.wscale_ok;
+	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
+	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
 
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -340,20 +353,6 @@
 		}
 	}
 
-	/* check for timestamp cookie support */
-	memset(&tcp_opt, 0, sizeof(tcp_opt));
-	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, &rt->u.dst);
-
-	if (tcp_opt.saw_tstamp)
-		cookie_check_timestamp(&tcp_opt);
-
-	ireq->snd_wscale        = tcp_opt.snd_wscale;
-	ireq->rcv_wscale        = tcp_opt.rcv_wscale;
-	ireq->sack_ok           = tcp_opt.sack_ok;
-	ireq->wscale_ok         = tcp_opt.wscale_ok;
-	ireq->tstamp_ok         = tcp_opt.saw_tstamp;
-	req->ts_recent          = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
-
 	/* Try to redo what tcp_v4_send_synack did. */
 	req->window_clamp = tp->window_clamp ? :dst_metric(&rt->u.dst, RTAX_WINDOW);
 
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 12cab7d..28e0296 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3727,7 +3727,7 @@
  * the fast version below fails.
  */
 void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
-		       u8 **hvpp, int estab,  struct dst_entry *dst)
+		       u8 **hvpp, int estab)
 {
 	unsigned char *ptr;
 	struct tcphdr *th = tcp_hdr(skb);
@@ -3766,8 +3766,7 @@
 				break;
 			case TCPOPT_WINDOW:
 				if (opsize == TCPOLEN_WINDOW && th->syn &&
-				    !estab && sysctl_tcp_window_scaling &&
-				    !dst_feature(dst, RTAX_FEATURE_NO_WSCALE)) {
+				    !estab && sysctl_tcp_window_scaling) {
 					__u8 snd_wscale = *(__u8 *)ptr;
 					opt_rx->wscale_ok = 1;
 					if (snd_wscale > 14) {
@@ -3783,8 +3782,7 @@
 			case TCPOPT_TIMESTAMP:
 				if ((opsize == TCPOLEN_TIMESTAMP) &&
 				    ((estab && opt_rx->tstamp_ok) ||
-				     (!estab && sysctl_tcp_timestamps &&
-				      !dst_feature(dst, RTAX_FEATURE_NO_TSTAMP)))) {
+				     (!estab && sysctl_tcp_timestamps))) {
 					opt_rx->saw_tstamp = 1;
 					opt_rx->rcv_tsval = get_unaligned_be32(ptr);
 					opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
@@ -3792,8 +3790,7 @@
 				break;
 			case TCPOPT_SACK_PERM:
 				if (opsize == TCPOLEN_SACK_PERM && th->syn &&
-				    !estab && sysctl_tcp_sack &&
-				    !dst_feature(dst, RTAX_FEATURE_NO_SACK)) {
+				    !estab && sysctl_tcp_sack) {
 					opt_rx->sack_ok = 1;
 					tcp_sack_reset(opt_rx);
 				}
@@ -3878,7 +3875,7 @@
 		if (tcp_parse_aligned_timestamp(tp, th))
 			return 1;
 	}
-	tcp_parse_options(skb, &tp->rx_opt, hvpp, 1, NULL);
+	tcp_parse_options(skb, &tp->rx_opt, hvpp, 1);
 	return 1;
 }
 
@@ -4133,10 +4130,8 @@
 static void tcp_dsack_set(struct sock *sk, u32 seq, u32 end_seq)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
 
-	if (tcp_is_sack(tp) && sysctl_tcp_dsack &&
-	    !dst_feature(dst, RTAX_FEATURE_NO_DSACK)) {
+	if (tcp_is_sack(tp) && sysctl_tcp_dsack) {
 		int mib_idx;
 
 		if (before(seq, tp->rcv_nxt))
@@ -4165,15 +4160,13 @@
 static void tcp_send_dupack(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
 
 	if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
 	    before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
 		tcp_enter_quickack_mode(sk);
 
-		if (tcp_is_sack(tp) && sysctl_tcp_dsack &&
-		    !dst_feature(dst, RTAX_FEATURE_NO_DSACK)) {
+		if (tcp_is_sack(tp) && sysctl_tcp_dsack) {
 			u32 end_seq = TCP_SKB_CB(skb)->end_seq;
 
 			if (after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt))
@@ -5428,11 +5421,10 @@
 	u8 *hash_location;
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
 	struct tcp_cookie_values *cvp = tp->cookie_values;
 	int saved_clamp = tp->rx_opt.mss_clamp;
 
-	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0, dst);
+	tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0);
 
 	if (th->ack) {
 		/* rfc793:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 15e9603..65b8ebf 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1262,20 +1262,10 @@
 	tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
 #endif
 
-	ireq = inet_rsk(req);
-	ireq->loc_addr = daddr;
-	ireq->rmt_addr = saddr;
-	ireq->no_srccheck = inet_sk(sk)->transparent;
-	ireq->opt = tcp_v4_save_options(sk, skb);
-
-	dst = inet_csk_route_req(sk, req);
-	if(!dst)
-		goto drop_and_free;
-
 	tcp_clear_options(&tmp_opt);
 	tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
 	tmp_opt.user_mss  = tp->rx_opt.user_mss;
-	tcp_parse_options(skb, &tmp_opt, &hash_location, 0, dst);
+	tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
 
 	if (tmp_opt.cookie_plus > 0 &&
 	    tmp_opt.saw_tstamp &&
@@ -1319,8 +1309,14 @@
 	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
 	tcp_openreq_init(req, &tmp_opt, skb);
 
+	ireq = inet_rsk(req);
+	ireq->loc_addr = daddr;
+	ireq->rmt_addr = saddr;
+	ireq->no_srccheck = inet_sk(sk)->transparent;
+	ireq->opt = tcp_v4_save_options(sk, skb);
+
 	if (security_inet_conn_request(sk, skb, req))
-		goto drop_and_release;
+		goto drop_and_free;
 
 	if (!want_cookie)
 		TCP_ECN_create_request(req, tcp_hdr(skb));
@@ -1345,6 +1341,7 @@
 		 */
 		if (tmp_opt.saw_tstamp &&
 		    tcp_death_row.sysctl_tw_recycle &&
+		    (dst = inet_csk_route_req(sk, req)) != NULL &&
 		    (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
 		    peer->v4daddr == saddr) {
 			if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 87accec..f206ee5 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -95,9 +95,9 @@
 	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
 	int paws_reject = 0;
 
+	tmp_opt.saw_tstamp = 0;
 	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
-		tmp_opt.tstamp_ok = 1;
-		tcp_parse_options(skb, &tmp_opt, &hash_location, 1, NULL);
+		tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
 
 		if (tmp_opt.saw_tstamp) {
 			tmp_opt.ts_recent	= tcptw->tw_ts_recent;
@@ -526,9 +526,9 @@
 	__be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
 	int paws_reject = 0;
 
-	if ((th->doff > (sizeof(*th) >> 2)) && (req->ts_recent)) {
-		tmp_opt.tstamp_ok = 1;
-		tcp_parse_options(skb, &tmp_opt, &hash_location, 1, NULL);
+	tmp_opt.saw_tstamp = 0;
+	if (th->doff > (sizeof(struct tcphdr)>>2)) {
+		tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
 
 		if (tmp_opt.saw_tstamp) {
 			tmp_opt.ts_recent = req->ts_recent;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 93316a9..383ce23 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -553,7 +553,6 @@
 				struct tcp_md5sig_key **md5) {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcp_cookie_values *cvp = tp->cookie_values;
-	struct dst_entry *dst = __sk_dst_get(sk);
 	unsigned remaining = MAX_TCP_OPTION_SPACE;
 	u8 cookie_size = (!tp->rx_opt.cookie_out_never && cvp != NULL) ?
 			 tcp_cookie_size_check(cvp->cookie_desired) :
@@ -581,22 +580,18 @@
 	opts->mss = tcp_advertise_mss(sk);
 	remaining -= TCPOLEN_MSS_ALIGNED;
 
-	if (likely(sysctl_tcp_timestamps &&
-		   !dst_feature(dst, RTAX_FEATURE_NO_TSTAMP) &&
-		   *md5 == NULL)) {
+	if (likely(sysctl_tcp_timestamps && *md5 == NULL)) {
 		opts->options |= OPTION_TS;
 		opts->tsval = TCP_SKB_CB(skb)->when;
 		opts->tsecr = tp->rx_opt.ts_recent;
 		remaining -= TCPOLEN_TSTAMP_ALIGNED;
 	}
-	if (likely(sysctl_tcp_window_scaling &&
-		   !dst_feature(dst, RTAX_FEATURE_NO_WSCALE))) {
+	if (likely(sysctl_tcp_window_scaling)) {
 		opts->ws = tp->rx_opt.rcv_wscale;
 		opts->options |= OPTION_WSCALE;
 		remaining -= TCPOLEN_WSCALE_ALIGNED;
 	}
-	if (likely(sysctl_tcp_sack &&
-		   !dst_feature(dst, RTAX_FEATURE_NO_SACK))) {
+	if (likely(sysctl_tcp_sack)) {
 		opts->options |= OPTION_SACK_ADVERTISE;
 		if (unlikely(!(OPTION_TS & opts->options)))
 			remaining -= TCPOLEN_SACKPERM_ALIGNED;
@@ -2527,9 +2522,7 @@
 	 * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
 	 */
 	tp->tcp_header_len = sizeof(struct tcphdr) +
-		(sysctl_tcp_timestamps &&
-		(!dst_feature(dst, RTAX_FEATURE_NO_TSTAMP) ?
-		  TCPOLEN_TSTAMP_ALIGNED : 0));
+		(sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
 
 #ifdef CONFIG_TCP_MD5SIG
 	if (tp->af_specific->md5_lookup(sk, sk) != NULL)
@@ -2555,8 +2548,7 @@
 				  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
 				  &tp->rcv_wnd,
 				  &tp->window_clamp,
-				  (sysctl_tcp_window_scaling &&
-				   !dst_feature(dst, RTAX_FEATURE_NO_WSCALE)),
+				  sysctl_tcp_window_scaling,
 				  &rcv_wscale);
 
 	tp->rx_opt.rcv_wscale = rcv_wscale;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1f95348..f0126fd 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -216,9 +216,8 @@
 		 * force rand to be an odd multiple of UDP_HTABLE_SIZE
 		 */
 		rand = (rand | 1) * (udptable->mask + 1);
-		for (last = first + udptable->mask + 1;
-		     first != last;
-		     first++) {
+		last = first + udptable->mask + 1;
+		do {
 			hslot = udp_hashslot(udptable, net, first);
 			bitmap_zero(bitmap, PORTS_PER_CHAIN);
 			spin_lock_bh(&hslot->lock);
@@ -238,7 +237,7 @@
 				snum += rand;
 			} while (snum != first);
 			spin_unlock_bh(&hslot->lock);
-		}
+		} while (++first != last);
 		goto fail;
 	} else {
 		hslot = udp_hashslot(udptable, net, snum);
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 5f2ec20..0956eba 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -20,6 +20,7 @@
 #include <net/ipv6.h>
 #include <net/inet_frag.h>
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
@@ -187,6 +188,21 @@
 	return nf_conntrack_confirm(skb);
 }
 
+static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
+						struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+	if (skb->nf_bridge &&
+	    skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+		return IP6_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+	if (hooknum == NF_INET_PRE_ROUTING)
+		return IP6_DEFRAG_CONNTRACK_IN;
+	else
+		return IP6_DEFRAG_CONNTRACK_OUT;
+
+}
+
 static unsigned int ipv6_defrag(unsigned int hooknum,
 				struct sk_buff *skb,
 				const struct net_device *in,
@@ -199,8 +215,7 @@
 	if (skb->nfct)
 		return NF_ACCEPT;
 
-	reasm = nf_ct_frag6_gather(skb);
-
+	reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
 	/* queued */
 	if (reasm == NULL)
 		return NF_STOLEN;
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index e0b9424..312c20ad 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -168,13 +168,14 @@
 /* Creation primitives. */
 
 static __inline__ struct nf_ct_frag6_queue *
-fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst)
+fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst)
 {
 	struct inet_frag_queue *q;
 	struct ip6_create_arg arg;
 	unsigned int hash;
 
 	arg.id = id;
+	arg.user = user;
 	arg.src = src;
 	arg.dst = dst;
 
@@ -559,7 +560,7 @@
 	return 0;
 }
 
-struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
+struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
 {
 	struct sk_buff *clone;
 	struct net_device *dev = skb->dev;
@@ -605,7 +606,7 @@
 	if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh)
 		nf_ct_frag6_evictor();
 
-	fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
+	fq = fq_find(fhdr->identification, user, &hdr->saddr, &hdr->daddr);
 	if (fq == NULL) {
 		pr_debug("Can't find and can't create new queue\n");
 		goto ret_orig;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 4d98549..3b3a956 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -72,6 +72,7 @@
 	struct inet_frag_queue	q;
 
 	__be32			id;		/* fragment id		*/
+	u32			user;
 	struct in6_addr		saddr;
 	struct in6_addr		daddr;
 
@@ -141,7 +142,7 @@
 	struct ip6_create_arg *arg = a;
 
 	fq = container_of(q, struct frag_queue, q);
-	return (fq->id == arg->id &&
+	return (fq->id == arg->id && fq->user == arg->user &&
 			ipv6_addr_equal(&fq->saddr, arg->src) &&
 			ipv6_addr_equal(&fq->daddr, arg->dst));
 }
@@ -163,6 +164,7 @@
 	struct ip6_create_arg *arg = a;
 
 	fq->id = arg->id;
+	fq->user = arg->user;
 	ipv6_addr_copy(&fq->saddr, arg->src);
 	ipv6_addr_copy(&fq->daddr, arg->dst);
 }
@@ -243,6 +245,7 @@
 	unsigned int hash;
 
 	arg.id = id;
+	arg.user = IP6_DEFRAG_LOCAL_DELIVER;
 	arg.src = src;
 	arg.dst = dst;
 
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 5b9af50..7208a06 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -185,6 +185,13 @@
 
 	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV);
 
+	/* check for timestamp cookie support */
+	memset(&tcp_opt, 0, sizeof(tcp_opt));
+	tcp_parse_options(skb, &tcp_opt, &hash_location, 0);
+
+	if (tcp_opt.saw_tstamp)
+		cookie_check_timestamp(&tcp_opt);
+
 	ret = NULL;
 	req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
 	if (!req)
@@ -218,6 +225,12 @@
 	req->expires = 0UL;
 	req->retrans = 0;
 	ireq->ecn_ok		= 0;
+	ireq->snd_wscale	= tcp_opt.snd_wscale;
+	ireq->rcv_wscale	= tcp_opt.rcv_wscale;
+	ireq->sack_ok		= tcp_opt.sack_ok;
+	ireq->wscale_ok		= tcp_opt.wscale_ok;
+	ireq->tstamp_ok		= tcp_opt.saw_tstamp;
+	req->ts_recent		= tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
 	treq->rcv_isn = ntohl(th->seq) - 1;
 	treq->snt_isn = cookie;
 
@@ -253,21 +266,6 @@
 			goto out_free;
 	}
 
-	/* check for timestamp cookie support */
-	memset(&tcp_opt, 0, sizeof(tcp_opt));
-	tcp_parse_options(skb, &tcp_opt, &hash_location, 0, dst);
-
-	if (tcp_opt.saw_tstamp)
-		cookie_check_timestamp(&tcp_opt);
-
-	req->ts_recent          = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
-
-	ireq->snd_wscale        = tcp_opt.snd_wscale;
-	ireq->rcv_wscale        = tcp_opt.rcv_wscale;
-	ireq->sack_ok           = tcp_opt.sack_ok;
-	ireq->wscale_ok         = tcp_opt.wscale_ok;
-	ireq->tstamp_ok         = tcp_opt.saw_tstamp;
-
 	req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
 	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 				  &req->rcv_wnd, &req->window_clamp,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ee9cf62..febfd59 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1169,7 +1169,6 @@
 	struct inet6_request_sock *treq;
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
 	__u32 isn = TCP_SKB_CB(skb)->when;
 #ifdef CONFIG_SYN_COOKIES
 	int want_cookie = 0;
@@ -1208,7 +1207,7 @@
 	tcp_clear_options(&tmp_opt);
 	tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 	tmp_opt.user_mss = tp->rx_opt.user_mss;
-	tcp_parse_options(skb, &tmp_opt, &hash_location, 0, dst);
+	tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
 
 	if (tmp_opt.cookie_plus > 0 &&
 	    tmp_opt.saw_tstamp &&
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b95699f..847ffca 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1366,6 +1366,7 @@
 	       == sysctl_ip_vs_sync_threshold[0])) ||
 	     ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
 	      ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
+	       (cp->state == IP_VS_TCP_S_CLOSE) ||
 	       (cp->state == IP_VS_TCP_S_CLOSE_WAIT) ||
 	       (cp->state == IP_VS_TCP_S_TIME_WAIT)))))
 		ip_vs_sync_conn(cp);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index e55a686..6bde12d 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2714,6 +2714,8 @@
 	if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr))))
 		return -EINVAL;
 
+	memset(usvc, 0, sizeof(*usvc));
+
 	usvc->af = nla_get_u16(nla_af);
 #ifdef CONFIG_IP_VS_IPV6
 	if (usvc->af != AF_INET && usvc->af != AF_INET6)
@@ -2901,6 +2903,8 @@
 	if (!(nla_addr && nla_port))
 		return -EINVAL;
 
+	memset(udest, 0, sizeof(*udest));
+
 	nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr));
 	udest->port = nla_get_u16(nla_port);
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 0205621..e0516a2 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -415,7 +415,7 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_pkt *saddr = (struct sockaddr_pkt *)msg->msg_name;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct net_device *dev;
 	__be16 proto = 0;
 	int err;
@@ -437,6 +437,7 @@
 	 */
 
 	saddr->spkt_device[13] = 0;
+retry:
 	rcu_read_lock();
 	dev = dev_get_by_name_rcu(sock_net(sk), saddr->spkt_device);
 	err = -ENODEV;
@@ -456,58 +457,48 @@
 	if (len > dev->mtu + dev->hard_header_len)
 		goto out_unlock;
 
-	err = -ENOBUFS;
-	skb = sock_wmalloc(sk, len + LL_RESERVED_SPACE(dev), 0, GFP_KERNEL);
+	if (!skb) {
+		size_t reserved = LL_RESERVED_SPACE(dev);
+		unsigned int hhlen = dev->header_ops ? dev->hard_header_len : 0;
 
-	/*
-	 * If the write buffer is full, then tough. At this level the user
-	 * gets to deal with the problem - do your own algorithmic backoffs.
-	 * That's far more flexible.
-	 */
+		rcu_read_unlock();
+		skb = sock_wmalloc(sk, len + reserved, 0, GFP_KERNEL);
+		if (skb == NULL)
+			return -ENOBUFS;
+		/* FIXME: Save some space for broken drivers that write a hard
+		 * header at transmission time by themselves. PPP is the notable
+		 * one here. This should really be fixed at the driver level.
+		 */
+		skb_reserve(skb, reserved);
+		skb_reset_network_header(skb);
 
-	if (skb == NULL)
-		goto out_unlock;
-
-	/*
-	 *	Fill it in
-	 */
-
-	/* FIXME: Save some space for broken drivers that write a
-	 * hard header at transmission time by themselves. PPP is the
-	 * notable one here. This should really be fixed at the driver level.
-	 */
-	skb_reserve(skb, LL_RESERVED_SPACE(dev));
-	skb_reset_network_header(skb);
-
-	/* Try to align data part correctly */
-	if (dev->header_ops) {
-		skb->data -= dev->hard_header_len;
-		skb->tail -= dev->hard_header_len;
-		if (len < dev->hard_header_len)
-			skb_reset_network_header(skb);
+		/* Try to align data part correctly */
+		if (hhlen) {
+			skb->data -= hhlen;
+			skb->tail -= hhlen;
+			if (len < hhlen)
+				skb_reset_network_header(skb);
+		}
+		err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+		if (err)
+			goto out_free;
+		goto retry;
 	}
 
-	/* Returns -EFAULT on error */
-	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+
 	skb->protocol = proto;
 	skb->dev = dev;
 	skb->priority = sk->sk_priority;
 	skb->mark = sk->sk_mark;
-	if (err)
-		goto out_free;
-
-	/*
-	 *	Now send it
-	 */
 
 	dev_queue_xmit(skb);
 	rcu_read_unlock();
 	return len;
 
-out_free:
-	kfree_skb(skb);
 out_unlock:
 	rcu_read_unlock();
+out_free:
+	kfree_skb(skb);
 	return err;
 }
 
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 536ebe5..3b89923 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -182,8 +182,8 @@
 		ic = conn->c_transport_data;
 		dev_addr = &ic->i_cm_id->route.addr.dev_addr;
 
-		ib_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid);
-		ib_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid);
+		rdma_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid);
+		rdma_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid);
 
 		rds_ibdev = ib_get_client_data(ic->i_cm_id->device, &rds_ib_client);
 		iinfo->max_send_wr = ic->i_send_ring.w_nr;
diff --git a/net/rds/iw.c b/net/rds/iw.c
index db224f7..b28fa85 100644
--- a/net/rds/iw.c
+++ b/net/rds/iw.c
@@ -184,8 +184,8 @@
 		ic = conn->c_transport_data;
 		dev_addr = &ic->i_cm_id->route.addr.dev_addr;
 
-		ib_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid);
-		ib_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid);
+		rdma_addr_get_sgid(dev_addr, (union ib_gid *) &iinfo->src_gid);
+		rdma_addr_get_dgid(dev_addr, (union ib_gid *) &iinfo->dst_gid);
 
 		rds_iwdev = ib_get_client_data(ic->i_cm_id->device, &rds_iw_client);
 		iinfo->max_send_wr = ic->i_send_ring.w_nr;
diff --git a/net/socket.c b/net/socket.c
index b94c3dd..769c386 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -312,18 +312,6 @@
 	.kill_sb =	kill_anon_super,
 };
 
-static int sockfs_delete_dentry(struct dentry *dentry)
-{
-	/*
-	 * At creation time, we pretended this dentry was hashed
-	 * (by clearing DCACHE_UNHASHED bit in d_flags)
-	 * At delete time, we restore the truth : not hashed.
-	 * (so that dput() can proceed correctly)
-	 */
-	dentry->d_flags |= DCACHE_UNHASHED;
-	return 0;
-}
-
 /*
  * sockfs_dname() is called from d_path().
  */
@@ -334,7 +322,6 @@
 }
 
 static const struct dentry_operations sockfs_dentry_operations = {
-	.d_delete = sockfs_delete_dentry,
 	.d_dname  = sockfs_dname,
 };
 
@@ -355,68 +342,55 @@
  *	but we take care of internal coherence yet.
  */
 
-static int sock_alloc_fd(struct file **filep, int flags)
+static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
 {
+	struct qstr name = { .name = "" };
+	struct path path;
+	struct file *file;
 	int fd;
 
 	fd = get_unused_fd_flags(flags);
-	if (likely(fd >= 0)) {
-		struct file *file = get_empty_filp();
+	if (unlikely(fd < 0))
+		return fd;
 
-		*filep = file;
-		if (unlikely(!file)) {
-			put_unused_fd(fd);
-			return -ENFILE;
-		}
-	} else
-		*filep = NULL;
-	return fd;
-}
-
-static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
-{
-	struct dentry *dentry;
-	struct qstr name = { .name = "" };
-
-	dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
-	if (unlikely(!dentry))
+	path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+	if (unlikely(!path.dentry)) {
+		put_unused_fd(fd);
 		return -ENOMEM;
+	}
+	path.mnt = mntget(sock_mnt);
 
-	dentry->d_op = &sockfs_dentry_operations;
-	/*
-	 * We dont want to push this dentry into global dentry hash table.
-	 * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
-	 * This permits a working /proc/$pid/fd/XXX on sockets
-	 */
-	dentry->d_flags &= ~DCACHE_UNHASHED;
-	d_instantiate(dentry, SOCK_INODE(sock));
+	path.dentry->d_op = &sockfs_dentry_operations;
+	d_instantiate(path.dentry, SOCK_INODE(sock));
+	SOCK_INODE(sock)->i_fop = &socket_file_ops;
+
+	file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
+		  &socket_file_ops);
+	if (unlikely(!file)) {
+		/* drop dentry, keep inode */
+		atomic_inc(&path.dentry->d_inode->i_count);
+		path_put(&path);
+		put_unused_fd(fd);
+		return -ENFILE;
+	}
 
 	sock->file = file;
-	init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
-		  &socket_file_ops);
-	SOCK_INODE(sock)->i_fop = &socket_file_ops;
 	file->f_flags = O_RDWR | (flags & O_NONBLOCK);
 	file->f_pos = 0;
 	file->private_data = sock;
 
-	return 0;
+	*f = file;
+	return fd;
 }
 
 int sock_map_fd(struct socket *sock, int flags)
 {
 	struct file *newfile;
-	int fd = sock_alloc_fd(&newfile, flags);
+	int fd = sock_alloc_file(sock, &newfile, flags);
 
-	if (likely(fd >= 0)) {
-		int err = sock_attach_fd(sock, newfile, flags);
-
-		if (unlikely(err < 0)) {
-			put_filp(newfile);
-			put_unused_fd(fd);
-			return err;
-		}
+	if (likely(fd >= 0))
 		fd_install(fd, newfile);
-	}
+
 	return fd;
 }
 
@@ -1390,29 +1364,19 @@
 	if (err < 0)
 		goto out_release_both;
 
-	fd1 = sock_alloc_fd(&newfile1, flags & O_CLOEXEC);
+	fd1 = sock_alloc_file(sock1, &newfile1, flags);
 	if (unlikely(fd1 < 0)) {
 		err = fd1;
 		goto out_release_both;
 	}
 
-	fd2 = sock_alloc_fd(&newfile2, flags & O_CLOEXEC);
+	fd2 = sock_alloc_file(sock2, &newfile2, flags);
 	if (unlikely(fd2 < 0)) {
 		err = fd2;
-		put_filp(newfile1);
-		put_unused_fd(fd1);
-		goto out_release_both;
-	}
-
-	err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
-	if (unlikely(err < 0)) {
-		goto out_fd2;
-	}
-
-	err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
-	if (unlikely(err < 0)) {
 		fput(newfile1);
-		goto out_fd1;
+		put_unused_fd(fd1);
+		sock_release(sock2);
+		goto out;
 	}
 
 	audit_fd_pair(fd1, fd2);
@@ -1438,16 +1402,6 @@
 	sock_release(sock1);
 out:
 	return err;
-
-out_fd2:
-	put_filp(newfile1);
-	sock_release(sock1);
-out_fd1:
-	put_filp(newfile2);
-	sock_release(sock2);
-	put_unused_fd(fd1);
-	put_unused_fd(fd2);
-	goto out;
 }
 
 /*
@@ -1551,17 +1505,13 @@
 	 */
 	__module_get(newsock->ops->owner);
 
-	newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
+	newfd = sock_alloc_file(newsock, &newfile, flags);
 	if (unlikely(newfd < 0)) {
 		err = newfd;
 		sock_release(newsock);
 		goto out_put;
 	}
 
-	err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
-	if (err < 0)
-		goto out_fd_simple;
-
 	err = security_socket_accept(sock, newsock);
 	if (err)
 		goto out_fd;
@@ -1591,11 +1541,6 @@
 	fput_light(sock->file, fput_needed);
 out:
 	return err;
-out_fd_simple:
-	sock_release(newsock);
-	put_filp(newfile);
-	put_unused_fd(newfd);
-	goto out_put;
 out_fd:
 	fput(newfile);
 	put_unused_fd(newfd);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index cef74ba..aae6907 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -210,6 +210,7 @@
 {
 	__rpc_init_priority_wait_queue(queue, qname, RPC_NR_PRIORITY);
 }
+EXPORT_SYMBOL_GPL(rpc_init_priority_wait_queue);
 
 void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
 {
@@ -385,6 +386,20 @@
 }
 
 /*
+ * Tests whether rpc queue is empty
+ */
+int rpc_queue_empty(struct rpc_wait_queue *queue)
+{
+	int res;
+
+	spin_lock_bh(&queue->lock);
+	res = queue->qlen;
+	spin_unlock_bh(&queue->lock);
+	return (res == 0);
+}
+EXPORT_SYMBOL_GPL(rpc_queue_empty);
+
+/*
  * Wake up a task on a specific queue
  */
 void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index b845e22..1c924ee 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -16,8 +16,6 @@
 
 #define RPCDBG_FACILITY	RPCDBG_SVCXPRT
 
-#define SVC_MAX_WAKING 5
-
 static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
 static int svc_deferred_recv(struct svc_rqst *rqstp);
 static struct cache_deferred_req *svc_defer(struct cache_req *req);
@@ -306,7 +304,6 @@
 	struct svc_pool *pool;
 	struct svc_rqst	*rqstp;
 	int cpu;
-	int thread_avail;
 
 	if (!(xprt->xpt_flags &
 	      ((1<<XPT_CONN)|(1<<XPT_DATA)|(1<<XPT_CLOSE)|(1<<XPT_DEFERRED))))
@@ -318,6 +315,12 @@
 
 	spin_lock_bh(&pool->sp_lock);
 
+	if (!list_empty(&pool->sp_threads) &&
+	    !list_empty(&pool->sp_sockets))
+		printk(KERN_ERR
+		       "svc_xprt_enqueue: "
+		       "threads and transports both waiting??\n");
+
 	if (test_bit(XPT_DEAD, &xprt->xpt_flags)) {
 		/* Don't enqueue dead transports */
 		dprintk("svc: transport %p is dead, not enqueued\n", xprt);
@@ -358,15 +361,7 @@
 	}
 
  process:
-	/* Work out whether threads are available */
-	thread_avail = !list_empty(&pool->sp_threads);	/* threads are asleep */
-	if (pool->sp_nwaking >= SVC_MAX_WAKING) {
-		/* too many threads are runnable and trying to wake up */
-		thread_avail = 0;
-		pool->sp_stats.overloads_avoided++;
-	}
-
-	if (thread_avail) {
+	if (!list_empty(&pool->sp_threads)) {
 		rqstp = list_entry(pool->sp_threads.next,
 				   struct svc_rqst,
 				   rq_list);
@@ -381,8 +376,6 @@
 		svc_xprt_get(xprt);
 		rqstp->rq_reserved = serv->sv_max_mesg;
 		atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
-		rqstp->rq_waking = 1;
-		pool->sp_nwaking++;
 		pool->sp_stats.threads_woken++;
 		BUG_ON(xprt->xpt_pool != pool);
 		wake_up(&rqstp->rq_wait);
@@ -651,11 +644,6 @@
 		return -EINTR;
 
 	spin_lock_bh(&pool->sp_lock);
-	if (rqstp->rq_waking) {
-		rqstp->rq_waking = 0;
-		pool->sp_nwaking--;
-		BUG_ON(pool->sp_nwaking < 0);
-	}
 	xprt = svc_xprt_dequeue(pool);
 	if (xprt) {
 		rqstp->rq_xprt = xprt;
@@ -1204,16 +1192,15 @@
 	struct svc_pool *pool = p;
 
 	if (p == SEQ_START_TOKEN) {
-		seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken overloads-avoided threads-timedout\n");
+		seq_puts(m, "# pool packets-arrived sockets-enqueued threads-woken threads-timedout\n");
 		return 0;
 	}
 
-	seq_printf(m, "%u %lu %lu %lu %lu %lu\n",
+	seq_printf(m, "%u %lu %lu %lu %lu\n",
 		pool->sp_id,
 		pool->sp_stats.packets,
 		pool->sp_stats.sockets_queued,
 		pool->sp_stats.threads_woken,
-		pool->sp_stats.overloads_avoided,
 		pool->sp_stats.threads_timedout);
 
 	return 0;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4a8f655..d8c0411 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -655,23 +655,25 @@
 		return NULL;
 }
 
-static int unix_gid_find(uid_t uid, struct group_info **gip,
-			 struct svc_rqst *rqstp)
+static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
 {
-	struct unix_gid *ug = unix_gid_lookup(uid);
+	struct unix_gid *ug;
+	struct group_info *gi;
+	int ret;
+
+	ug = unix_gid_lookup(uid);
 	if (!ug)
-		return -EAGAIN;
-	switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) {
+		return ERR_PTR(-EAGAIN);
+	ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
+	switch (ret) {
 	case -ENOENT:
-		*gip = NULL;
-		return 0;
+		return ERR_PTR(-ENOENT);
 	case 0:
-		*gip = ug->gi;
-		get_group_info(*gip);
+		gi = get_group_info(ug->gi);
 		cache_put(&ug->h, &unix_gid_cache);
-		return 0;
+		return gi;
 	default:
-		return -EAGAIN;
+		return ERR_PTR(-EAGAIN);
 	}
 }
 
@@ -681,6 +683,8 @@
 	struct sockaddr_in *sin;
 	struct sockaddr_in6 *sin6, sin6_storage;
 	struct ip_map *ipm;
+	struct group_info *gi;
+	struct svc_cred *cred = &rqstp->rq_cred;
 
 	switch (rqstp->rq_addr.ss_family) {
 	case AF_INET:
@@ -721,6 +725,17 @@
 			ip_map_cached_put(rqstp, ipm);
 			break;
 	}
+
+	gi = unix_gid_find(cred->cr_uid, rqstp);
+	switch (PTR_ERR(gi)) {
+	case -EAGAIN:
+		return SVC_DROP;
+	case -ENOENT:
+		break;
+	default:
+		put_group_info(cred->cr_group_info);
+		cred->cr_group_info = gi;
+	}
 	return SVC_OK;
 }
 
@@ -817,19 +832,11 @@
 	slen = svc_getnl(argv);			/* gids length */
 	if (slen > 16 || (len -= (slen + 2)*4) < 0)
 		goto badcred;
-	if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
-	    == -EAGAIN)
+	cred->cr_group_info = groups_alloc(slen);
+	if (cred->cr_group_info == NULL)
 		return SVC_DROP;
-	if (cred->cr_group_info == NULL) {
-		cred->cr_group_info = groups_alloc(slen);
-		if (cred->cr_group_info == NULL)
-			return SVC_DROP;
-		for (i = 0; i < slen; i++)
-			GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
-	} else {
-		for (i = 0; i < slen ; i++)
-			svc_getnl(argv);
-	}
+	for (i = 0; i < slen; i++)
+		GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
 	if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 		*authp = rpc_autherr_badverf;
 		return SVC_DENIED;
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index c67e73e..ed2773e 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -149,6 +149,12 @@
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
+# Usage:
+# $(Q)$(MAKE) $(modbuiltin)=dir
+modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
+
 # Prefix -I with $(srctree) if it is not an absolute path.
 # skip if -I has no parameter
 addtree = $(if $(patsubst -I%,%,$(1)), \
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 341b589..0b94d2f 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -207,6 +207,7 @@
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
 cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
+	"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
 	"$(if $(CONFIG_64BIT),64,32)" \
 	"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
 	"$(if $(part-of-module),1,0)" "$(@)";
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index ffdafb2..cd815ac 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -127,6 +127,11 @@
 		$(CFLAGS_GCOV))
 endif
 
+ifdef CONFIG_SYMBOL_PREFIX
+_cpp_flags += -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
+endif
+
+
 # If building the kernel in a separate objtree expand all occurrences
 # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
 
@@ -208,7 +213,7 @@
 
 # Bzip2 and LZMA do not include size in file... so we have to fake that;
 # append the size as a 32-bit littleendian number as gzip does.
-size_append = /bin/echo -ne $(shell					\
+size_append = printf $(shell						\
 dec_size=0;								\
 for F in $1; do								\
 	fsize=$$(stat -c "%s" $$F);					\
diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin
new file mode 100644
index 0000000..102a276
--- /dev/null
+++ b/scripts/Makefile.modbuiltin
@@ -0,0 +1,55 @@
+# ==========================================================================
+# Generating modules.builtin
+# ==========================================================================
+
+src := $(obj)
+
+PHONY := __modbuiltin
+__modbuiltin:
+
+-include include/config/auto.conf
+# tristate.conf sets tristate variables to uppercase 'Y' or 'M'
+# That way, we get the list of built-in modules in obj-Y
+-include include/config/tristate.conf
+
+include scripts/Kbuild.include
+
+# The filename Kbuild has precedence over Makefile
+kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
+include $(kbuild-file)
+
+include scripts/Makefile.lib
+__subdir-Y     := $(patsubst %/,%,$(filter %/, $(obj-Y)))
+subdir-Y       += $(__subdir-Y)
+subdir-ym      := $(sort $(subdir-y) $(subdir-Y) $(subdir-m))
+subdir-ym      := $(addprefix $(obj)/,$(subdir-ym))
+obj-Y          := $(addprefix $(obj)/,$(obj-Y))
+
+modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym))
+modbuiltin-mods    := $(filter %.ko, $(obj-Y:.o=.ko))
+modbuiltin-target  := $(obj)/modules.builtin
+
+__modbuiltin: $(modbuiltin-target) $(subdir-ym)
+	@:
+
+$(modbuiltin-target): $(subdir-ym) FORCE
+	$(Q)(for m in $(modbuiltin-mods); do echo kernel/$$m; done;	\
+	cat /dev/null $(modbuiltin-subdirs)) > $@
+
+PHONY += FORCE
+
+FORCE:
+
+# Descending
+# ---------------------------------------------------------------------------
+
+PHONY += $(subdir-ym)
+$(subdir-ym):
+	$(Q)$(MAKE) $(modbuiltin)=$@
+
+
+# Declare the contents of the .PHONY variable as phony.  We keep that
+# information in a variable se we can use it in if_changed and friends.
+
+.PHONY: $(PHONY)
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 6bf21f8..ea26b23 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -16,15 +16,15 @@
  * tells make when to remake a file.
  *
  * To use this list as-is however has the drawback that virtually
- * every file in the kernel includes <linux/autoconf.h>.
+ * every file in the kernel includes autoconf.h.
  *
- * If the user re-runs make *config, linux/autoconf.h will be
+ * If the user re-runs make *config, autoconf.h will be
  * regenerated.  make notices that and will rebuild every file which
  * includes autoconf.h, i.e. basically all files. This is extremely
  * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
  *
  * So we play the same trick that "mkdep" played before. We replace
- * the dependency on linux/autoconf.h by a dependency on every config
+ * the dependency on autoconf.h by a dependency on every config
  * option which is mentioned in any of the listed prequisites.
  *
  * kconfig populates a tree in include/config/ with an empty file
@@ -73,7 +73,7 @@
  *   cmd_<target> = <cmdline>
  *
  * and then basically copies the .<target>.d file to stdout, in the
- * process filtering out the dependency on linux/autoconf.h and adding
+ * process filtering out the dependency on autoconf.h and adding
  * dependencies on include/config/my/option.h for every
  * CONFIG_MY_OPTION encountered in any of the prequisites.
  *
@@ -324,7 +324,7 @@
 			p++;
 		}
 		memcpy(s, m, p-m); s[p-m] = 0;
-		if (strrcmp(s, "include/linux/autoconf.h") &&
+		if (strrcmp(s, "include/generated/autoconf.h") &&
 		    strrcmp(s, "arch/um/include/uml-config.h") &&
 		    strrcmp(s, ".ver")) {
 			printf("  %s \\\n", s);
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
index 287467a..8060e06 100644
--- a/scripts/genksyms/keywords.c_shipped
+++ b/scripts/genksyms/keywords.c_shipped
@@ -1,4 +1,4 @@
-/* ANSI-C code produced by gperf version 3.0.3 */
+/* ANSI-C code produced by gperf version 3.0.4 */
 /* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf  */
 
 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -34,7 +34,7 @@
 static const struct resword *is_reserved_word(register const char *str, register unsigned int len);
 #line 5 "scripts/genksyms/keywords.gperf"
 struct resword { const char *name; int token; };
-/* maximum key range = 62, duplicates = 0 */
+/* maximum key range = 64, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -48,39 +48,39 @@
 {
   static const unsigned char asso_values[] =
     {
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65,  5,
-      65, 65, 65, 65, 65, 65, 35, 65, 65, 65,
-       0, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65,  0, 65,  0, 65,  5,
-      20, 15, 10, 30, 65, 15, 65, 65, 20,  0,
-      10, 35, 20, 65, 10,  5,  0, 10,  5, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-      65, 65, 65, 65, 65, 65
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67,  0,
+      67, 67, 67, 67, 67, 67, 15, 67, 67, 67,
+       0, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67,  0, 67,  0, 67,  5,
+      25, 20, 15, 30, 67, 15, 67, 67, 10,  0,
+      10, 40, 20, 67, 10,  5,  0, 10, 15, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+      67, 67, 67, 67, 67, 67
     };
   return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
 }
 
 #ifdef __GNUC__
 __inline
-#ifdef __GNUC_STDC_INLINE__
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
@@ -89,116 +89,119 @@
 {
   enum
     {
-      TOTAL_KEYWORDS = 43,
+      TOTAL_KEYWORDS = 45,
       MIN_WORD_LENGTH = 3,
       MAX_WORD_LENGTH = 24,
       MIN_HASH_VALUE = 3,
-      MAX_HASH_VALUE = 64
+      MAX_HASH_VALUE = 66
     };
 
   static const struct resword wordlist[] =
     {
       {""}, {""}, {""},
-#line 28 "scripts/genksyms/keywords.gperf"
+#line 30 "scripts/genksyms/keywords.gperf"
       {"asm", ASM_KEYW},
       {""},
-#line 10 "scripts/genksyms/keywords.gperf"
+#line 12 "scripts/genksyms/keywords.gperf"
       {"__asm", ASM_KEYW},
       {""},
-#line 11 "scripts/genksyms/keywords.gperf"
+#line 13 "scripts/genksyms/keywords.gperf"
       {"__asm__", ASM_KEYW},
       {""}, {""},
-#line 54 "scripts/genksyms/keywords.gperf"
+#line 56 "scripts/genksyms/keywords.gperf"
       {"__typeof__", TYPEOF_KEYW},
       {""},
-#line 14 "scripts/genksyms/keywords.gperf"
-      {"__const", CONST_KEYW},
-#line 13 "scripts/genksyms/keywords.gperf"
-      {"__attribute__", ATTRIBUTE_KEYW},
-#line 15 "scripts/genksyms/keywords.gperf"
-      {"__const__", CONST_KEYW},
-#line 20 "scripts/genksyms/keywords.gperf"
-      {"__signed__", SIGNED_KEYW},
-#line 46 "scripts/genksyms/keywords.gperf"
-      {"static", STATIC_KEYW},
-#line 22 "scripts/genksyms/keywords.gperf"
-      {"__volatile__", VOLATILE_KEYW},
-#line 41 "scripts/genksyms/keywords.gperf"
-      {"int", INT_KEYW},
-#line 34 "scripts/genksyms/keywords.gperf"
-      {"char", CHAR_KEYW},
-#line 35 "scripts/genksyms/keywords.gperf"
-      {"const", CONST_KEYW},
-#line 47 "scripts/genksyms/keywords.gperf"
-      {"struct", STRUCT_KEYW},
-#line 26 "scripts/genksyms/keywords.gperf"
-      {"__restrict__", RESTRICT_KEYW},
-#line 27 "scripts/genksyms/keywords.gperf"
-      {"restrict", RESTRICT_KEYW},
-#line 25 "scripts/genksyms/keywords.gperf"
-      {"_restrict", RESTRICT_KEYW},
-#line 18 "scripts/genksyms/keywords.gperf"
-      {"__inline__", INLINE_KEYW},
-#line 12 "scripts/genksyms/keywords.gperf"
-      {"__attribute", ATTRIBUTE_KEYW},
-      {""},
 #line 16 "scripts/genksyms/keywords.gperf"
-      {"__extension__", EXTENSION_KEYW},
-#line 37 "scripts/genksyms/keywords.gperf"
-      {"enum", ENUM_KEYW},
-#line 21 "scripts/genksyms/keywords.gperf"
-      {"__volatile", VOLATILE_KEYW},
-#line 38 "scripts/genksyms/keywords.gperf"
-      {"extern", EXTERN_KEYW},
+      {"__const", CONST_KEYW},
+#line 15 "scripts/genksyms/keywords.gperf"
+      {"__attribute__", ATTRIBUTE_KEYW},
+#line 17 "scripts/genksyms/keywords.gperf"
+      {"__const__", CONST_KEYW},
+#line 22 "scripts/genksyms/keywords.gperf"
+      {"__signed__", SIGNED_KEYW},
+#line 48 "scripts/genksyms/keywords.gperf"
+      {"static", STATIC_KEYW},
       {""},
-#line 19 "scripts/genksyms/keywords.gperf"
-      {"__signed", SIGNED_KEYW},
+#line 43 "scripts/genksyms/keywords.gperf"
+      {"int", INT_KEYW},
+#line 36 "scripts/genksyms/keywords.gperf"
+      {"char", CHAR_KEYW},
+#line 37 "scripts/genksyms/keywords.gperf"
+      {"const", CONST_KEYW},
+#line 49 "scripts/genksyms/keywords.gperf"
+      {"struct", STRUCT_KEYW},
+#line 28 "scripts/genksyms/keywords.gperf"
+      {"__restrict__", RESTRICT_KEYW},
+#line 29 "scripts/genksyms/keywords.gperf"
+      {"restrict", RESTRICT_KEYW},
 #line 9 "scripts/genksyms/keywords.gperf"
       {"EXPORT_SYMBOL_GPL_FUTURE", EXPORT_SYMBOL_KEYW},
-      {""},
-#line 53 "scripts/genksyms/keywords.gperf"
-      {"typeof", TYPEOF_KEYW},
-#line 48 "scripts/genksyms/keywords.gperf"
-      {"typedef", TYPEDEF_KEYW},
-#line 17 "scripts/genksyms/keywords.gperf"
-      {"__inline", INLINE_KEYW},
-#line 33 "scripts/genksyms/keywords.gperf"
-      {"auto", AUTO_KEYW},
-#line 49 "scripts/genksyms/keywords.gperf"
-      {"union", UNION_KEYW},
-      {""}, {""},
-#line 50 "scripts/genksyms/keywords.gperf"
-      {"unsigned", UNSIGNED_KEYW},
-#line 51 "scripts/genksyms/keywords.gperf"
-      {"void", VOID_KEYW},
-#line 44 "scripts/genksyms/keywords.gperf"
-      {"short", SHORT_KEYW},
-      {""}, {""},
-#line 52 "scripts/genksyms/keywords.gperf"
-      {"volatile", VOLATILE_KEYW},
-      {""},
-#line 39 "scripts/genksyms/keywords.gperf"
-      {"float", FLOAT_KEYW},
-#line 36 "scripts/genksyms/keywords.gperf"
-      {"double", DOUBLE_KEYW},
-      {""},
-#line 7 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
-      {""}, {""},
-#line 40 "scripts/genksyms/keywords.gperf"
-      {"inline", INLINE_KEYW},
-#line 8 "scripts/genksyms/keywords.gperf"
-      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
-#line 43 "scripts/genksyms/keywords.gperf"
-      {"register", REGISTER_KEYW},
+#line 20 "scripts/genksyms/keywords.gperf"
+      {"__inline__", INLINE_KEYW},
       {""},
 #line 24 "scripts/genksyms/keywords.gperf"
-      {"_Bool", BOOL_KEYW},
-#line 45 "scripts/genksyms/keywords.gperf"
-      {"signed", SIGNED_KEYW},
+      {"__volatile__", VOLATILE_KEYW},
+#line 7 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 27 "scripts/genksyms/keywords.gperf"
+      {"_restrict", RESTRICT_KEYW},
+      {""},
+#line 14 "scripts/genksyms/keywords.gperf"
+      {"__attribute", ATTRIBUTE_KEYW},
+#line 8 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 18 "scripts/genksyms/keywords.gperf"
+      {"__extension__", EXTENSION_KEYW},
+#line 39 "scripts/genksyms/keywords.gperf"
+      {"enum", ENUM_KEYW},
+#line 10 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL", EXPORT_SYMBOL_KEYW},
+#line 40 "scripts/genksyms/keywords.gperf"
+      {"extern", EXTERN_KEYW},
+      {""},
+#line 21 "scripts/genksyms/keywords.gperf"
+      {"__signed", SIGNED_KEYW},
+#line 11 "scripts/genksyms/keywords.gperf"
+      {"EXPORT_UNUSED_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 51 "scripts/genksyms/keywords.gperf"
+      {"union", UNION_KEYW},
+#line 55 "scripts/genksyms/keywords.gperf"
+      {"typeof", TYPEOF_KEYW},
+#line 50 "scripts/genksyms/keywords.gperf"
+      {"typedef", TYPEDEF_KEYW},
+#line 19 "scripts/genksyms/keywords.gperf"
+      {"__inline", INLINE_KEYW},
+#line 35 "scripts/genksyms/keywords.gperf"
+      {"auto", AUTO_KEYW},
+#line 23 "scripts/genksyms/keywords.gperf"
+      {"__volatile", VOLATILE_KEYW},
       {""}, {""},
+#line 52 "scripts/genksyms/keywords.gperf"
+      {"unsigned", UNSIGNED_KEYW},
+      {""},
+#line 46 "scripts/genksyms/keywords.gperf"
+      {"short", SHORT_KEYW},
 #line 42 "scripts/genksyms/keywords.gperf"
-      {"long", LONG_KEYW}
+      {"inline", INLINE_KEYW},
+      {""},
+#line 54 "scripts/genksyms/keywords.gperf"
+      {"volatile", VOLATILE_KEYW},
+#line 44 "scripts/genksyms/keywords.gperf"
+      {"long", LONG_KEYW},
+#line 26 "scripts/genksyms/keywords.gperf"
+      {"_Bool", BOOL_KEYW},
+      {""}, {""},
+#line 45 "scripts/genksyms/keywords.gperf"
+      {"register", REGISTER_KEYW},
+#line 53 "scripts/genksyms/keywords.gperf"
+      {"void", VOID_KEYW},
+#line 41 "scripts/genksyms/keywords.gperf"
+      {"float", FLOAT_KEYW},
+#line 38 "scripts/genksyms/keywords.gperf"
+      {"double", DOUBLE_KEYW},
+      {""}, {""}, {""}, {""},
+#line 47 "scripts/genksyms/keywords.gperf"
+      {"signed", SIGNED_KEYW}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/genksyms/keywords.gperf b/scripts/genksyms/keywords.gperf
index 8fe977a..e6349ac 100644
--- a/scripts/genksyms/keywords.gperf
+++ b/scripts/genksyms/keywords.gperf
@@ -7,6 +7,8 @@
 EXPORT_SYMBOL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 EXPORT_SYMBOL_GPL_FUTURE, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL, EXPORT_SYMBOL_KEYW
+EXPORT_UNUSED_SYMBOL_GPL, EXPORT_SYMBOL_KEYW
 __asm, ASM_KEYW
 __asm__, ASM_KEYW
 __attribute, ATTRIBUTE_KEYW
diff --git a/scripts/headers.sh b/scripts/headers.sh
index 0308ecc..1ddcdd3 100755
--- a/scripts/headers.sh
+++ b/scripts/headers.sh
@@ -8,8 +8,6 @@
 {
 	if [ -f ${srctree}/arch/$2/include/asm/Kbuild ]; then
 		make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
-	elif [ -f ${srctree}/include/asm-$2/Kbuild ]; then
-		make ARCH=$2 KBUILD_HEADERS=$1 headers_$1
 	else
 		printf "Ignoring arch: %s\n" ${arch}
 	fi
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 80599e3..999e8a7 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -27,6 +27,7 @@
 	$< -o $(Kconfig)
 
 silentoldconfig: $(obj)/conf
+	$(Q)mkdir -p include/generated
 	$< -s $(Kconfig)
 
 localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index b55e72f..c4dec80 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -677,7 +677,7 @@
 	struct symbol *sym;
 	const char *str;
 	const char *name;
-	FILE *out, *out_h;
+	FILE *out, *tristate, *out_h;
 	time_t now;
 	int i, l;
 
@@ -692,9 +692,16 @@
 	if (!out)
 		return 1;
 
+	tristate = fopen(".tmpconfig_tristate", "w");
+	if (!tristate) {
+		fclose(out);
+		return 1;
+	}
+
 	out_h = fopen(".tmpconfig.h", "w");
 	if (!out_h) {
 		fclose(out);
+		fclose(tristate);
 		return 1;
 	}
 
@@ -707,6 +714,9 @@
 		     "# %s"
 		     "#\n",
 		     sym_get_string_value(sym), ctime(&now));
+	fprintf(tristate, "#\n"
+			  "# Automatically generated - do not edit\n"
+			  "\n");
 	fprintf(out_h, "/*\n"
 		       " * Automatically generated C config: don't edit\n"
 		       " * Linux kernel version: %s\n"
@@ -727,10 +737,14 @@
 				break;
 			case mod:
 				fprintf(out, "CONFIG_%s=m\n", sym->name);
+				fprintf(tristate, "CONFIG_%s=M\n", sym->name);
 				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 				break;
 			case yes:
 				fprintf(out, "CONFIG_%s=y\n", sym->name);
+				if (sym->type == S_TRISTATE)
+					fprintf(tristate, "CONFIG_%s=Y\n",
+							sym->name);
 				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 				break;
 			}
@@ -772,13 +786,19 @@
 		}
 	}
 	fclose(out);
+	fclose(tristate);
 	fclose(out_h);
 
 	name = getenv("KCONFIG_AUTOHEADER");
 	if (!name)
-		name = "include/linux/autoconf.h";
+		name = "include/generated/autoconf.h";
 	if (rename(".tmpconfig.h", name))
 		return 1;
+	name = getenv("KCONFIG_TRISTATE");
+	if (!name)
+		name = "include/config/tristate.conf";
+	if (rename(".tmpconfig_tristate", name))
+		return 1;
 	name = conf_get_autoconfig_name();
 	/*
 	 * This must be the last step, kbuild has a dependency on auto.conf
diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h
index bce3d0f..23dbad8 100755
--- a/scripts/mkcompile_h
+++ b/scripts/mkcompile_h
@@ -14,7 +14,7 @@
 # So "sudo make install" won't change the "compiled by <user>"
 # do "compiled by root"
 
-if [ -r $TARGET -a ! -O include/linux/autoconf.h ]; then
+if [ -r $TARGET -a ! -O include/generated/autoconf.h ]; then
   vecho "  SKIPPED $TARGET"
   exit 0
 fi
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index 11d69c3..ff954f8 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -8,7 +8,7 @@
 $(obj)/modpost.o $(obj)/file2alias.o $(obj)/sumversion.o: $(obj)/elfconfig.h
 
 quiet_cmd_elfconfig = MKELF   $@
-      cmd_elfconfig = $(obj)/mk_elfconfig $(ARCH) < $< > $@
+      cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
 
 $(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
 	$(call if_changed,elfconfig)
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index 6a96d47..639bca7 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -9,9 +9,6 @@
 	unsigned char ei[EI_NIDENT];
 	union { short s; char c[2]; } endian_test;
 
-	if (argc != 2) {
-		fprintf(stderr, "Error: no arch\n");
-	}
 	if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
 		fprintf(stderr, "Error: input truncated\n");
 		return 1;
@@ -55,12 +52,6 @@
 	else
 		exit(1);
 
-	if ((strcmp(argv[1], "h8300") == 0)
-	    || (strcmp(argv[1], "blackfin") == 0))
-		printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
-	else
-		printf("#define MODULE_SYMBOL_PREFIX \"\"\n");
-
 	return 0;
 }
 
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 801a16a..2092361 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -15,8 +15,17 @@
 #include <stdio.h>
 #include <ctype.h>
 #include "modpost.h"
+#include "../../include/generated/autoconf.h"
 #include "../../include/linux/license.h"
 
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_SYMBOL_PREFIX
+#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#else
+#define MODULE_SYMBOL_PREFIX ""
+#endif
+
+
 /* Are we using CONFIG_MODVERSIONS? */
 int modversions = 0;
 /* Warn about undefined symbols? (do so if we have vmlinux) */
@@ -451,8 +460,6 @@
 			info->export_unused_gpl_sec = i;
 		else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
 			info->export_gpl_future_sec = i;
-		else if (strcmp(secname, "__markers_strings") == 0)
-			info->markers_strings_sec = i;
 
 		if (sechdrs[i].sh_type != SHT_SYMTAB)
 			continue;
@@ -515,7 +522,7 @@
 		break;
 	case SHN_ABS:
 		/* CRC'd symbol */
-		if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+		if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
 			crc = (unsigned int) sym->st_value;
 			sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
 					export);
@@ -559,7 +566,7 @@
 		break;
 	default:
 		/* All exported symbols */
-		if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
+		if (strncmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
 			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
 					export);
 		}
@@ -1509,62 +1516,6 @@
 	}
 }
 
-static void get_markers(struct elf_info *info, struct module *mod)
-{
-	const Elf_Shdr *sh = &info->sechdrs[info->markers_strings_sec];
-	const char *strings = (const char *) info->hdr + sh->sh_offset;
-	const Elf_Sym *sym, *first_sym, *last_sym;
-	size_t n;
-
-	if (!info->markers_strings_sec)
-		return;
-
-	/*
-	 * First count the strings.  We look for all the symbols defined
-	 * in the __markers_strings section named __mstrtab_*.  For
-	 * these local names, the compiler puts a random .NNN suffix on,
-	 * so the names don't correspond exactly.
-	 */
-	first_sym = last_sym = NULL;
-	n = 0;
-	for (sym = info->symtab_start; sym < info->symtab_stop; sym++)
-		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-		    sym->st_shndx == info->markers_strings_sec &&
-		    !strncmp(info->strtab + sym->st_name,
-			     "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-			if (first_sym == NULL)
-				first_sym = sym;
-			last_sym = sym;
-			++n;
-		}
-
-	if (n == 0)
-		return;
-
-	/*
-	 * Now collect each name and format into a line for the output.
-	 * Lines look like:
-	 *	marker_name	vmlinux	marker %s format %d
-	 * The format string after the second \t can use whitespace.
-	 */
-	mod->markers = NOFAIL(malloc(sizeof mod->markers[0] * n));
-	mod->nmarkers = n;
-
-	n = 0;
-	for (sym = first_sym; sym <= last_sym; sym++)
-		if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT &&
-		    sym->st_shndx == info->markers_strings_sec &&
-		    !strncmp(info->strtab + sym->st_name,
-			     "__mstrtab_", sizeof "__mstrtab_" - 1)) {
-			const char *name = strings + sym->st_value;
-			const char *fmt = strchr(name, '\0') + 1;
-			char *line = NULL;
-			asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-			NOFAIL(line);
-			mod->markers[n++] = line;
-		}
-}
-
 static void read_symbols(char *modname)
 {
 	const char *symname;
@@ -1620,8 +1571,6 @@
 		get_src_version(modname, mod->srcversion,
 				sizeof(mod->srcversion)-1);
 
-	get_markers(&info, mod);
-
 	parse_elf_finish(&info);
 
 	/* Our trick to get versioning for module struct etc. - it's
@@ -1976,96 +1925,6 @@
 	write_if_changed(&buf, fname);
 }
 
-static void add_marker(struct module *mod, const char *name, const char *fmt)
-{
-	char *line = NULL;
-	asprintf(&line, "%s\t%s\t%s\n", name, mod->name, fmt);
-	NOFAIL(line);
-
-	mod->markers = NOFAIL(realloc(mod->markers, ((mod->nmarkers + 1) *
-						     sizeof mod->markers[0])));
-	mod->markers[mod->nmarkers++] = line;
-}
-
-static void read_markers(const char *fname)
-{
-	unsigned long size, pos = 0;
-	void *file = grab_file(fname, &size);
-	char *line;
-
-	if (!file)		/* No old markers, silently ignore */
-		return;
-
-	while ((line = get_next_line(&pos, file, size))) {
-		char *marker, *modname, *fmt;
-		struct module *mod;
-
-		marker = line;
-		modname = strchr(marker, '\t');
-		if (!modname)
-			goto fail;
-		*modname++ = '\0';
-		fmt = strchr(modname, '\t');
-		if (!fmt)
-			goto fail;
-		*fmt++ = '\0';
-		if (*marker == '\0' || *modname == '\0')
-			goto fail;
-
-		mod = find_module(modname);
-		if (!mod) {
-			mod = new_module(modname);
-			mod->skip = 1;
-		}
-		if (is_vmlinux(modname)) {
-			have_vmlinux = 1;
-			mod->skip = 0;
-		}
-
-		if (!mod->skip)
-			add_marker(mod, marker, fmt);
-	}
-	release_file(file, size);
-	return;
-fail:
-	fatal("parse error in markers list file\n");
-}
-
-static int compare_strings(const void *a, const void *b)
-{
-	return strcmp(*(const char **) a, *(const char **) b);
-}
-
-static void write_markers(const char *fname)
-{
-	struct buffer buf = { };
-	struct module *mod;
-	size_t i;
-
-	for (mod = modules; mod; mod = mod->next)
-		if ((!external_module || !mod->skip) && mod->markers != NULL) {
-			/*
-			 * Sort the strings so we can skip duplicates when
-			 * we write them out.
-			 */
-			qsort(mod->markers, mod->nmarkers,
-			      sizeof mod->markers[0], &compare_strings);
-			for (i = 0; i < mod->nmarkers; ++i) {
-				char *line = mod->markers[i];
-				buf_write(&buf, line, strlen(line));
-				while (i + 1 < mod->nmarkers &&
-				       !strcmp(mod->markers[i],
-					       mod->markers[i + 1]))
-					free(mod->markers[i++]);
-				free(mod->markers[i]);
-			}
-			free(mod->markers);
-			mod->markers = NULL;
-		}
-
-	write_if_changed(&buf, fname);
-}
-
 struct ext_sym_list {
 	struct ext_sym_list *next;
 	const char *file;
@@ -2077,8 +1936,6 @@
 	struct buffer buf = { };
 	char *kernel_read = NULL, *module_read = NULL;
 	char *dump_write = NULL;
-	char *markers_read = NULL;
-	char *markers_write = NULL;
 	int opt;
 	int err;
 	struct ext_sym_list *extsym_iter;
@@ -2122,12 +1979,6 @@
 		case 'w':
 			warn_unresolved = 1;
 			break;
-			case 'M':
-				markers_write = optarg;
-				break;
-			case 'K':
-				markers_read = optarg;
-				break;
 		default:
 			exit(1);
 		}
@@ -2182,11 +2033,5 @@
 		     "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
 		     sec_mismatch_count);
 
-	if (markers_read)
-		read_markers(markers_read);
-
-	if (markers_write)
-		write_markers(markers_write);
-
 	return err;
 }
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 09f58e3..be987a4 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -112,8 +112,6 @@
 	int has_init;
 	int has_cleanup;
 	struct buffer dev_table_buf;
-	char **markers;
-	size_t nmarkers;
 	char	     srcversion[25];
 };
 
@@ -128,7 +126,6 @@
 	Elf_Section  export_gpl_sec;
 	Elf_Section  export_unused_gpl_sec;
 	Elf_Section  export_gpl_future_sec;
-	Elf_Section  markers_strings_sec;
 	const char   *strtab;
 	char	     *modinfo;
 	unsigned int modinfo_len;
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index f67cc88..62fcc3a 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -77,9 +77,27 @@
 
 # Deb target
 # ---------------------------------------------------------------------------
+quiet_cmd_builddeb = BUILDDEB
+      cmd_builddeb = set -e; \
+	test `id -u` = 0 || \
+	test -n "$(KBUILD_PKG_ROOTCMD)" || { \
+		which fakeroot >/dev/null 2>&1 && \
+		KBUILD_PKG_ROOTCMD="fakeroot -u"; \
+	} || { \
+		echo; \
+		echo "builddeb must be run as root (or using fakeroot)."; \
+		echo "KBUILD_PKG_ROOTCMD is unset and fakeroot not found."; \
+		echo "Try setting KBUILD_PKG_ROOTCMD to a command to acquire"; \
+		echo "root privileges (e.g., 'fakeroot -u' or 'sudo')."; \
+		false; \
+	} && \
+	\
+	$$KBUILD_PKG_ROOTCMD $(CONFIG_SHELL) \
+		$(srctree)/scripts/package/builddeb
+
 deb-pkg: FORCE
 	$(MAKE) KBUILD_SRC=
-	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
+	$(call cmd,builddeb)
 
 clean-dirs += $(objtree)/debian/
 
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index b1fd48d..51b2aa0 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -101,7 +101,11 @@
 #
 (
 	cd "${tmpdir}"
-	tar cf - . | ${compress} > "${tarball}${file_ext}"
+	opts=
+	if tar --owner=root --group=root --help >/dev/null 2>&1; then
+		opts="--owner=root --group=root"
+	fi
+	tar cf - . $opts | ${compress} > "${tarball}${file_ext}"
 )
 
 echo "Tarball successfully created in ${tarball}${file_ext}"
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 9cf0a6f..92f09fe 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -113,13 +113,13 @@
 
 my $V = '0.1';
 
-if ($#ARGV != 10) {
-	print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
+if ($#ARGV != 11) {
+	print "usage: $P arch endian bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
 	print "version: $V\n";
 	exit(1);
 }
 
-my ($arch, $bits, $objdump, $objcopy, $cc,
+my ($arch, $endian, $bits, $objdump, $objcopy, $cc,
     $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
 
 # This file refers to mcount and shouldn't be ftraced, so lets' ignore it
@@ -295,6 +295,58 @@
     $ld .= " -m elf64_sparc";
     $cc .= " -m64";
     $objcopy .= " -O elf64-sparc";
+} elsif ($arch eq "mips") {
+    # To enable module support, we need to enable the -mlong-calls option
+    # of gcc for module, after using this option, we can not get the real
+    # offset of the calling to _mcount, but the offset of the lui
+    # instruction or the addiu one. herein, we record the address of the
+    # first one, and then we can replace this instruction by a branch
+    # instruction to jump over the profiling function to filter the
+    # indicated functions, or swith back to the lui instruction to trace
+    # them, which means dynamic tracing.
+    #
+    #       c:	3c030000 	lui	v1,0x0
+    #			c: R_MIPS_HI16	_mcount
+    #			c: R_MIPS_NONE	*ABS*
+    #			c: R_MIPS_NONE	*ABS*
+    #      10:	64630000 	daddiu	v1,v1,0
+    #			10: R_MIPS_LO16	_mcount
+    #			10: R_MIPS_NONE	*ABS*
+    #			10: R_MIPS_NONE	*ABS*
+    #      14:	03e0082d 	move	at,ra
+    #      18:	0060f809 	jalr	v1
+    #
+    # for the kernel:
+    #
+    #     10:   03e0082d        move    at,ra
+    #	  14:   0c000000        jal     0 <loongson_halt>
+    #                    14: R_MIPS_26   _mcount
+    #                    14: R_MIPS_NONE *ABS*
+    #                    14: R_MIPS_NONE *ABS*
+    #	 18:   00020021        nop
+    if ($is_module eq "0") {
+	    $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+    } else {
+	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
+    }
+    $objdump .= " -Melf-trad".$endian."mips ";
+
+    if ($endian eq "big") {
+	    $endian = " -EB ";
+	    $ld .= " -melf".$bits."btsmip";
+    } else {
+	    $endian = " -EL ";
+	    $ld .= " -melf".$bits."ltsmip";
+    }
+
+    $cc .= " -mno-abicalls -fno-pic -mabi=" . $bits . $endian;
+    $ld .= $endian;
+
+    if ($bits == 64) {
+	    $function_regex =
+		"^([0-9a-fA-F]+)\\s+<(.|[^\$]L.*?|\$[^L].*?|[^\$][^L].*?)>:";
+	    $type = ".dword";
+    }
 } elsif ($arch eq "microblaze") {
     # Microblaze calls '_mcount' instead of plain 'mcount'.
     $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
diff --git a/scripts/tags.sh b/scripts/tags.sh
index d52f7a0..1a0c44d 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -89,7 +89,13 @@
 
 docscope()
 {
-	(echo \-k; echo \-q; all_sources) > cscope.files
+	# always use absolute paths for cscope, as recommended by cscope
+	# upstream
+	case "$tree" in
+		/*) ;;
+		*) tree=$PWD/$tree ;;
+	esac
+	(cd /; echo \-k; echo \-q; all_sources) > cscope.files
 	cscope -b -f cscope.out
 }
 
diff --git a/scripts/unifdef.c b/scripts/unifdef.c
index 30d459f..44d3978 100644
--- a/scripts/unifdef.c
+++ b/scripts/unifdef.c
@@ -1,13 +1,5 @@
 /*
- * Copyright (c) 2002 - 2005 Tony Finch <dot@dotat.at>.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by Dave Yost.
- * It was rewritten to support ANSI C by Tony Finch. The original version of
- * unifdef carried the following copyright notice. None of its code remains
- * in this version (though some of the names remain).
- *
- * Copyright (c) 1985, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,23 +23,20 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
+/*
+ * This code was derived from software contributed to Berkeley by Dave Yost.
+ * It was rewritten to support ANSI C by Tony Finch. The original version
+ * of unifdef carried the 4-clause BSD copyright licence. None of its code
+ * remains in this version (though some of the names remain) so it now
+ * carries a more liberal licence.
+ *
+ * The latest version is available from http://dotat.at/prog/unifdef
+ */
 
-#ifndef lint
-#if 0
-static const char copyright[] =
-"@(#) Copyright (c) 1985, 1993\n\
-	The Regents of the University of California.  All rights reserved.\n";
-#endif
-#ifdef __IDSTRING
-__IDSTRING(Berkeley, "@(#)unifdef.c	8.1 (Berkeley) 6/6/93");
-__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $");
-__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $");
-#endif
-#endif /* not lint */
-#ifdef __FBSDID
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $");
-#endif
+static const char * const copyright[] = {
+    "@(#) Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>\n",
+    "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $",
+};
 
 /*
  * unifdef - remove ifdef'ed lines
@@ -72,8 +61,6 @@
 #include <string.h>
 #include <unistd.h>
 
-size_t strlcpy(char *dst, const char *src, size_t siz);
-
 /* types of input lines: */
 typedef enum {
 	LT_TRUEI,		/* a true #if with ignore flag */
@@ -90,6 +77,7 @@
 	LT_DODGY_LAST = LT_DODGY + LT_ENDIF,
 	LT_PLAIN,		/* ordinary line */
 	LT_EOF,			/* end of file */
+	LT_ERROR,		/* unevaluable #if */
 	LT_COUNT
 } Linetype;
 
@@ -100,7 +88,7 @@
 	"DODGY IF", "DODGY TRUE", "DODGY FALSE",
 	"DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE",
 	"DODGY ELSE", "DODGY ENDIF",
-	"PLAIN", "EOF"
+	"PLAIN", "EOF", "ERROR"
 };
 
 /* state of #if processing */
@@ -168,11 +156,13 @@
  * Globals.
  */
 
+static bool             compblank;		/* -B: compress blank lines */
+static bool             lnblank;		/* -b: blank deleted lines */
 static bool             complement;		/* -c: do the complement */
 static bool             debugging;		/* -d: debugging reports */
 static bool             iocccok;		/* -e: fewer IOCCC errors */
+static bool             strictlogic;		/* -K: keep ambiguous #ifs */
 static bool             killconsts;		/* -k: eval constant #ifs */
-static bool             lnblank;		/* -l: blank deleted lines */
 static bool             lnnum;			/* -n: add #line directives */
 static bool             symlist;		/* -s: output symbol list */
 static bool             text;			/* -t: this is a text file */
@@ -196,7 +186,9 @@
 static int              stifline[MAXDEPTH];	/* start of current #if */
 static int              depth;			/* current #if nesting */
 static int              delcount;		/* count of deleted lines */
-static bool             keepthis;		/* don't delete constant #if */
+static unsigned         blankcount;		/* count of blank lines */
+static unsigned         blankmax;		/* maximum recent blankcount */
+static bool             constexpr;		/* constant #if expression */
 
 static int              exitstat;		/* program exit status */
 
@@ -206,13 +198,14 @@
 static void             error(const char *);
 static int              findsym(const char *);
 static void             flushline(bool);
-static Linetype         get_line(void);
+static Linetype         parseline(void);
 static Linetype         ifeval(const char **);
 static void             ignoreoff(void);
 static void             ignoreon(void);
 static void             keywordedit(const char *);
 static void             nest(void);
 static void             process(void);
+static const char      *skipargs(const char *);
 static const char      *skipcomment(const char *);
 static const char      *skipsym(const char *);
 static void             state(Ifstate);
@@ -220,7 +213,7 @@
 static void             unnest(void);
 static void             usage(void);
 
-#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_')
+#define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
 /*
  * The main program.
@@ -230,7 +223,7 @@
 {
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1)
+	while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
 		switch (opt) {
 		case 'i': /* treat stuff controlled by these symbols as text */
 			/*
@@ -255,6 +248,13 @@
 		case 'I':
 			/* no-op for compatibility with cpp */
 			break;
+		case 'B': /* compress blank lines around removed section */
+			compblank = true;
+			break;
+		case 'b': /* blank deleted lines instead of omitting them */
+		case 'l': /* backwards compatibility */
+			lnblank = true;
+			break;
 		case 'c': /* treat -D as -U and vice versa */
 			complement = true;
 			break;
@@ -264,12 +264,12 @@
 		case 'e': /* fewer errors from dodgy lines */
 			iocccok = true;
 			break;
+		case 'K': /* keep ambiguous #ifs */
+			strictlogic = true;
+			break;
 		case 'k': /* process constant #ifs */
 			killconsts = true;
 			break;
-		case 'l': /* blank deleted lines instead of omitting them */
-			lnblank = true;
-			break;
 		case 'n': /* add #line directive after deleted lines */
 			lnnum = true;
 			break;
@@ -284,6 +284,8 @@
 		}
 	argc -= optind;
 	argv += optind;
+	if (compblank && lnblank)
+		errx(2, "-B and -b are mutually exclusive");
 	if (argc > 1) {
 		errx(2, "can only do one file");
 	} else if (argc == 1 && strcmp(*argv, "-") != 0) {
@@ -302,7 +304,7 @@
 static void
 usage(void)
 {
-	fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]"
+	fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]"
 	    " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
 	exit(2);
 }
@@ -383,46 +385,46 @@
 /* IS_OUTSIDE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Eendif,
-  print, done },
+  print, done,  abort },
 /* IS_FALSE_PREFIX */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_PREFIX */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_PASS_MIDDLE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Pelif, Oelif, Oelif, Pelse, Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_MIDDLE */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_MIDDLE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eioccc,Eioccc,Eioccc,Eioccc,Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_PASS_ELSE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Pendif,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_ELSE */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc,
-  drop,  Eeof },
+  drop,  Eeof,  abort },
 /* IS_TRUE_ELSE */
 { Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif,
   Oiffy, Oiffy, Fpass, Oif,   Oif,   Eelif, Eelif, Eelif, Eelse, Eioccc,
-  print, Eeof },
+  print, Eeof,  abort },
 /* IS_FALSE_TRAILER */
 { Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif,
   Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc,
-  drop,  Eeof }
+  drop,  Eeof,  abort }
 /*TRUEI  FALSEI IF     TRUE   FALSE  ELIF   ELTRUE ELFALSE ELSE  ENDIF
   TRUEI  FALSEI IF     TRUE   FALSE  ELIF   ELTRUE ELFALSE ELSE  ENDIF (DODGY)
-  PLAIN  EOF */
+  PLAIN  EOF    ERROR */
 };
 
 /*
@@ -463,9 +465,11 @@
 static void
 nest(void)
 {
-	depth += 1;
-	if (depth >= MAXDEPTH)
+	if (depth > MAXDEPTH-1)
+		abort(); /* bug */
+	if (depth == MAXDEPTH-1)
 		error("Too many levels of nesting");
+	depth += 1;
 	stifline[depth] = linenum;
 }
 static void
@@ -490,15 +494,23 @@
 	if (symlist)
 		return;
 	if (keep ^ complement) {
-		if (lnnum && delcount > 0)
-			printf("#line %d\n", linenum);
-		fputs(tline, stdout);
-		delcount = 0;
+		bool blankline = tline[strspn(tline, " \t\n")] == '\0';
+		if (blankline && compblank && blankcount != blankmax) {
+			delcount += 1;
+			blankcount += 1;
+		} else {
+			if (lnnum && delcount > 0)
+				printf("#line %d\n", linenum);
+			fputs(tline, stdout);
+			delcount = 0;
+			blankmax = blankcount = blankline ? blankcount + 1 : 0;
+		}
 	} else {
 		if (lnblank)
 			putc('\n', stdout);
 		exitstat = 1;
 		delcount += 1;
+		blankcount = 0;
 	}
 }
 
@@ -510,9 +522,12 @@
 {
 	Linetype lineval;
 
+	/* When compressing blank lines, act as if the file
+	   is preceded by a large number of blank lines. */
+	blankmax = blankcount = 1000;
 	for (;;) {
 		linenum++;
-		lineval = get_line();
+		lineval = parseline();
 		trans_table[ifstate[depth]][lineval]();
 		debug("process %s -> %s depth %d",
 		    linetype_name[lineval],
@@ -526,7 +541,7 @@
  * help from skipcomment().
  */
 static Linetype
-get_line(void)
+parseline(void)
 {
 	const char *cp;
 	int cursym;
@@ -595,9 +610,21 @@
 			if (incomment)
 				linestate = LS_DIRTY;
 		}
-		/* skipcomment should have changed the state */
-		if (linestate == LS_HASH)
-			abort(); /* bug */
+		/* skipcomment normally changes the state, except
+		   if the last line of the file lacks a newline, or
+		   if there is too much whitespace in a directive */
+		if (linestate == LS_HASH) {
+			size_t len = cp - tline;
+			if (fgets(tline + len, MAXLINE - len, input) == NULL) {
+				/* append the missing newline */
+				tline[len+0] = '\n';
+				tline[len+1] = '\0';
+				cp++;
+				linestate = LS_START;
+			} else {
+				linestate = LS_DIRTY;
+			}
+		}
 	}
 	if (linestate == LS_DIRTY) {
 		while (*cp != '\0')
@@ -610,17 +637,40 @@
 
 /*
  * These are the binary operators that are supported by the expression
- * evaluator. Note that if support for division is added then we also
- * need short-circuiting booleans because of divide-by-zero.
+ * evaluator.
  */
-static int op_lt(int a, int b) { return (a < b); }
-static int op_gt(int a, int b) { return (a > b); }
-static int op_le(int a, int b) { return (a <= b); }
-static int op_ge(int a, int b) { return (a >= b); }
-static int op_eq(int a, int b) { return (a == b); }
-static int op_ne(int a, int b) { return (a != b); }
-static int op_or(int a, int b) { return (a || b); }
-static int op_and(int a, int b) { return (a && b); }
+static Linetype op_strict(int *p, int v, Linetype at, Linetype bt) {
+	if(at == LT_IF || bt == LT_IF) return (LT_IF);
+	return (*p = v, v ? LT_TRUE : LT_FALSE);
+}
+static Linetype op_lt(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a < b, at, bt);
+}
+static Linetype op_gt(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a > b, at, bt);
+}
+static Linetype op_le(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a <= b, at, bt);
+}
+static Linetype op_ge(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a >= b, at, bt);
+}
+static Linetype op_eq(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a == b, at, bt);
+}
+static Linetype op_ne(int *p, Linetype at, int a, Linetype bt, int b) {
+	return op_strict(p, a != b, at, bt);
+}
+static Linetype op_or(int *p, Linetype at, int a, Linetype bt, int b) {
+	if (!strictlogic && (at == LT_TRUE || bt == LT_TRUE))
+		return (*p = 1, LT_TRUE);
+	return op_strict(p, a || b, at, bt);
+}
+static Linetype op_and(int *p, Linetype at, int a, Linetype bt, int b) {
+	if (!strictlogic && (at == LT_FALSE || bt == LT_FALSE))
+		return (*p = 0, LT_FALSE);
+	return op_strict(p, a && b, at, bt);
+}
 
 /*
  * An evaluation function takes three arguments, as follows: (1) a pointer to
@@ -629,8 +679,8 @@
  * value of the expression; and (3) a pointer to a char* that points to the
  * expression to be evaluated and that is updated to the end of the expression
  * when evaluation is complete. The function returns LT_FALSE if the value of
- * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the
- * expression could not be evaluated.
+ * the expression is zero, LT_TRUE if it is non-zero, LT_IF if the expression
+ * depends on an unknown symbol, or LT_ERROR if there is a parse failure.
  */
 struct ops;
 
@@ -649,7 +699,7 @@
 	eval_fn *inner;
 	struct op {
 		const char *str;
-		int (*fn)(int, int);
+		Linetype (*fn)(int *, Linetype, int, Linetype, int);
 	} op[5];
 } eval_ops[] = {
 	{ eval_table, { { "||", op_or } } },
@@ -664,8 +714,8 @@
 
 /*
  * Function for evaluating the innermost parts of expressions,
- * viz. !expr (expr) defined(symbol) symbol number
- * We reset the keepthis flag when we find a non-constant subexpression.
+ * viz. !expr (expr) number defined(symbol) symbol
+ * We reset the constexpr flag in the last two cases.
  */
 static Linetype
 eval_unary(const struct ops *ops, int *valp, const char **cpp)
@@ -673,68 +723,83 @@
 	const char *cp;
 	char *ep;
 	int sym;
+	bool defparen;
+	Linetype lt;
 
 	cp = skipcomment(*cpp);
 	if (*cp == '!') {
 		debug("eval%d !", ops - eval_ops);
 		cp++;
-		if (eval_unary(ops, valp, &cp) == LT_IF) {
-			*cpp = cp;
-			return (LT_IF);
+		lt = eval_unary(ops, valp, &cp);
+		if (lt == LT_ERROR)
+			return (LT_ERROR);
+		if (lt != LT_IF) {
+			*valp = !*valp;
+			lt = *valp ? LT_TRUE : LT_FALSE;
 		}
-		*valp = !*valp;
 	} else if (*cp == '(') {
 		cp++;
 		debug("eval%d (", ops - eval_ops);
-		if (eval_table(eval_ops, valp, &cp) == LT_IF)
-			return (LT_IF);
+		lt = eval_table(eval_ops, valp, &cp);
+		if (lt == LT_ERROR)
+			return (LT_ERROR);
 		cp = skipcomment(cp);
 		if (*cp++ != ')')
-			return (LT_IF);
+			return (LT_ERROR);
 	} else if (isdigit((unsigned char)*cp)) {
 		debug("eval%d number", ops - eval_ops);
 		*valp = strtol(cp, &ep, 0);
+		if (ep == cp)
+			return (LT_ERROR);
+		lt = *valp ? LT_TRUE : LT_FALSE;
 		cp = skipsym(cp);
 	} else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) {
 		cp = skipcomment(cp+7);
 		debug("eval%d defined", ops - eval_ops);
-		if (*cp++ != '(')
-			return (LT_IF);
-		cp = skipcomment(cp);
+		if (*cp == '(') {
+			cp = skipcomment(cp+1);
+			defparen = true;
+		} else {
+			defparen = false;
+		}
 		sym = findsym(cp);
+		if (sym < 0) {
+			lt = LT_IF;
+		} else {
+			*valp = (value[sym] != NULL);
+			lt = *valp ? LT_TRUE : LT_FALSE;
+		}
 		cp = skipsym(cp);
 		cp = skipcomment(cp);
-		if (*cp++ != ')')
-			return (LT_IF);
-		if (sym >= 0)
-			*valp = (value[sym] != NULL);
-		else {
-			*cpp = cp;
-			return (LT_IF);
-		}
-		keepthis = false;
+		if (defparen && *cp++ != ')')
+			return (LT_ERROR);
+		constexpr = false;
 	} else if (!endsym(*cp)) {
 		debug("eval%d symbol", ops - eval_ops);
 		sym = findsym(cp);
-		if (sym < 0)
-			return (LT_IF);
-		if (value[sym] == NULL)
+		cp = skipsym(cp);
+		if (sym < 0) {
+			lt = LT_IF;
+			cp = skipargs(cp);
+		} else if (value[sym] == NULL) {
 			*valp = 0;
-		else {
+			lt = LT_FALSE;
+		} else {
 			*valp = strtol(value[sym], &ep, 0);
 			if (*ep != '\0' || ep == value[sym])
-				return (LT_IF);
+				return (LT_ERROR);
+			lt = *valp ? LT_TRUE : LT_FALSE;
+			cp = skipargs(cp);
 		}
-		cp = skipsym(cp);
-		keepthis = false;
+		constexpr = false;
 	} else {
 		debug("eval%d bad expr", ops - eval_ops);
-		return (LT_IF);
+		return (LT_ERROR);
 	}
 
 	*cpp = cp;
 	debug("eval%d = %d", ops - eval_ops, *valp);
-	return (*valp ? LT_TRUE : LT_FALSE);
+	return (lt);
 }
 
 /*
@@ -746,11 +811,13 @@
 	const struct op *op;
 	const char *cp;
 	int val;
-	Linetype lhs, rhs;
+	Linetype lt, rt;
 
 	debug("eval%d", ops - eval_ops);
 	cp = *cpp;
-	lhs = ops->inner(ops+1, valp, &cp);
+	lt = ops->inner(ops+1, valp, &cp);
+	if (lt == LT_ERROR)
+		return (LT_ERROR);
 	for (;;) {
 		cp = skipcomment(cp);
 		for (op = ops->op; op->str != NULL; op++)
@@ -760,32 +827,16 @@
 			break;
 		cp += strlen(op->str);
 		debug("eval%d %s", ops - eval_ops, op->str);
-		rhs = ops->inner(ops+1, &val, &cp);
-		if (op->fn == op_and && (lhs == LT_FALSE || rhs == LT_FALSE)) {
-			debug("eval%d: and always false", ops - eval_ops);
-			if (lhs == LT_IF)
-				*valp = val;
-			lhs = LT_FALSE;
-			continue;
-		}
-		if (op->fn == op_or && (lhs == LT_TRUE || rhs == LT_TRUE)) {
-			debug("eval%d: or always true", ops - eval_ops);
-			if (lhs == LT_IF)
-				*valp = val;
-			lhs = LT_TRUE;
-			continue;
-		}
-		if (rhs == LT_IF)
-			lhs = LT_IF;
-		if (lhs != LT_IF)
-			*valp = op->fn(*valp, val);
+		rt = ops->inner(ops+1, &val, &cp);
+		if (rt == LT_ERROR)
+			return (LT_ERROR);
+		lt = op->fn(valp, lt, *valp, rt, val);
 	}
 
 	*cpp = cp;
 	debug("eval%d = %d", ops - eval_ops, *valp);
-	if (lhs != LT_IF)
-		lhs = (*valp ? LT_TRUE : LT_FALSE);
-	return lhs;
+	debug("eval%d lt = %s", ops - eval_ops, linetype_name[lt]);
+	return (lt);
 }
 
 /*
@@ -796,17 +847,14 @@
 static Linetype
 ifeval(const char **cpp)
 {
-	const char *cp = *cpp;
 	int ret;
-	int val;
+	int val = 0;
 
 	debug("eval %s", *cpp);
-	keepthis = killconsts ? false : true;
-	ret = eval_table(eval_ops, &val, &cp);
-	if (ret != LT_IF)
-		*cpp = cp;
+	constexpr = killconsts ? false : true;
+	ret = eval_table(eval_ops, &val, cpp);
 	debug("eval = %d", val);
-	return (keepthis ? LT_IF : ret);
+	return (constexpr ? LT_IF : ret == LT_ERROR ? LT_IF : ret);
 }
 
 /*
@@ -918,6 +966,31 @@
 }
 
 /*
+ * Skip macro arguments.
+ */
+static const char *
+skipargs(const char *cp)
+{
+	const char *ocp = cp;
+	int level = 0;
+	cp = skipcomment(cp);
+	if (*cp != '(')
+		return (cp);
+	do {
+		if (*cp == '(')
+			level++;
+		if (*cp == ')')
+			level--;
+		cp = skipcomment(cp+1);
+	} while (level != 0 && *cp != '\0');
+	if (level == 0)
+		return (cp);
+	else
+	/* Rewind and re-detect the syntax error later. */
+		return (ocp);
+}
+
+/*
  * Skip over an identifier.
  */
 static const char *
@@ -929,7 +1002,7 @@
 }
 
 /*
- * Look for the symbol in the symbol table. If is is found, we return
+ * Look for the symbol in the symbol table. If it is found, we return
  * the symbol table index, else we return -1.
  */
 static int
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 165eb53..c41afe6 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -97,7 +97,6 @@
 
 /* iint cache flags */
 #define IMA_MEASURED		1
-#define IMA_IINT_DUMP_STACK	512
 
 /* integrity data associated with an inode */
 struct ima_iint_cache {
@@ -128,8 +127,6 @@
  */
 struct ima_iint_cache *ima_iint_insert(struct inode *inode);
 struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
-struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode);
-void ima_iint_delete(struct inode *inode);
 void iint_free(struct kref *kref);
 void iint_rcu_free(struct rcu_head *rcu);
 
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index a4e2b1d..fa592ff 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -19,8 +19,6 @@
 #include <linux/radix-tree.h>
 #include "ima.h"
 
-#define ima_iint_delete ima_inode_free
-
 RADIX_TREE(ima_iint_store, GFP_ATOMIC);
 DEFINE_SPINLOCK(ima_iint_lock);
 
@@ -45,22 +43,21 @@
 	return iint;
 }
 
-/* Allocate memory for the iint associated with the inode
- * from the iint_cache slab, initialize the iint, and
- * insert it into the radix tree.
- *
- * On success return a pointer to the iint; on failure return NULL.
+/**
+ * ima_inode_alloc - allocate an iint associated with an inode
+ * @inode: pointer to the inode
  */
-struct ima_iint_cache *ima_iint_insert(struct inode *inode)
+int ima_inode_alloc(struct inode *inode)
 {
 	struct ima_iint_cache *iint = NULL;
 	int rc = 0;
 
 	if (!ima_initialized)
-		return iint;
+		return 0;
+
 	iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
 	if (!iint)
-		return iint;
+		return -ENOMEM;
 
 	rc = radix_tree_preload(GFP_NOFS);
 	if (rc < 0)
@@ -70,66 +67,14 @@
 	rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
 	spin_unlock(&ima_iint_lock);
 out:
-	if (rc < 0) {
+	if (rc < 0)
 		kmem_cache_free(iint_cache, iint);
-		if (rc == -EEXIST) {
-			spin_lock(&ima_iint_lock);
-			iint = radix_tree_lookup(&ima_iint_store,
-						 (unsigned long)inode);
-			spin_unlock(&ima_iint_lock);
-		} else
-			iint = NULL;
-	}
+
 	radix_tree_preload_end();
-	return iint;
+
+	return rc;
 }
 
-/**
- * ima_inode_alloc - allocate an iint associated with an inode
- * @inode: pointer to the inode
- *
- * Return 0 on success, 1 on failure.
- */
-int ima_inode_alloc(struct inode *inode)
-{
-	struct ima_iint_cache *iint;
-
-	if (!ima_initialized)
-		return 0;
-
-	iint = ima_iint_insert(inode);
-	if (!iint)
-		return 1;
-	return 0;
-}
-
-/* ima_iint_find_insert_get - get the iint associated with an inode
- *
- * Most insertions are done at inode_alloc, except those allocated
- * before late_initcall. When the iint does not exist, allocate it,
- * initialize and insert it, and increment the iint refcount.
- *
- * (Can't initialize at security_initcall before any inodes are
- * allocated, got to wait at least until proc_init.)
- *
- *  Return the iint.
- */
-struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode)
-{
-	struct ima_iint_cache *iint = NULL;
-
-	iint = ima_iint_find_get(inode);
-	if (iint)
-		return iint;
-
-	iint = ima_iint_insert(inode);
-	if (iint)
-		kref_get(&iint->refcount);
-
-	return iint;
-}
-EXPORT_SYMBOL_GPL(ima_iint_find_insert_get);
-
 /* iint_free - called when the iint refcount goes to zero */
 void iint_free(struct kref *kref)
 {
@@ -164,12 +109,12 @@
 }
 
 /**
- * ima_iint_delete - called on integrity_inode_free
+ * ima_inode_free - called on security_inode_free
  * @inode: pointer to the inode
  *
  * Free the integrity information(iint) associated with an inode.
  */
-void ima_iint_delete(struct inode *inode)
+void ima_inode_free(struct inode *inode)
 {
 	struct ima_iint_cache *iint;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index b85e61b..a89f44d 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -13,8 +13,8 @@
  * License.
  *
  * File: ima_main.c
- *             implements the IMA hooks: ima_bprm_check, ima_file_mmap,
- *             and ima_path_check.
+ *	implements the IMA hooks: ima_bprm_check, ima_file_mmap,
+ *	and ima_path_check.
  */
 #include <linux/module.h>
 #include <linux/file.h>
@@ -35,6 +35,100 @@
 }
 __setup("ima_hash=", hash_setup);
 
+struct ima_imbalance {
+	struct hlist_node node;
+	unsigned long fsmagic;
+};
+
+/*
+ * ima_limit_imbalance - emit one imbalance message per filesystem type
+ *
+ * Maintain list of filesystem types that do not measure files properly.
+ * Return false if unknown, true if known.
+ */
+static bool ima_limit_imbalance(struct file *file)
+{
+	static DEFINE_SPINLOCK(ima_imbalance_lock);
+	static HLIST_HEAD(ima_imbalance_list);
+
+	struct super_block *sb = file->f_dentry->d_sb;
+	struct ima_imbalance *entry;
+	struct hlist_node *node;
+	bool found = false;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
+		if (entry->fsmagic == sb->s_magic) {
+			found = true;
+			break;
+		}
+	}
+	rcu_read_unlock();
+	if (found)
+		goto out;
+
+	entry = kmalloc(sizeof(*entry), GFP_NOFS);
+	if (!entry)
+		goto out;
+	entry->fsmagic = sb->s_magic;
+	spin_lock(&ima_imbalance_lock);
+	/*
+	 * we could have raced and something else might have added this fs
+	 * to the list, but we don't really care
+	 */
+	hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
+	spin_unlock(&ima_imbalance_lock);
+	printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
+	       entry->fsmagic);
+out:
+	return found;
+}
+
+/*
+ * Update the counts given an fmode_t
+ */
+static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
+{
+	BUG_ON(!mutex_is_locked(&iint->mutex));
+
+	iint->opencount++;
+	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		iint->readcount++;
+	if (mode & FMODE_WRITE)
+		iint->writecount++;
+}
+
+/*
+ * Decrement ima counts
+ */
+static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
+			   struct file *file)
+{
+	mode_t mode = file->f_mode;
+	BUG_ON(!mutex_is_locked(&iint->mutex));
+
+	iint->opencount--;
+	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		iint->readcount--;
+	if (mode & FMODE_WRITE) {
+		iint->writecount--;
+		if (iint->writecount == 0) {
+			if (iint->version != inode->i_version)
+				iint->flags &= ~IMA_MEASURED;
+		}
+	}
+
+	if (((iint->opencount < 0) ||
+	     (iint->readcount < 0) ||
+	     (iint->writecount < 0)) &&
+	    !ima_limit_imbalance(file)) {
+		printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
+		       __FUNCTION__, iint->readcount, iint->writecount,
+		       iint->opencount);
+		dump_stack();
+	}
+}
+
 /**
  * ima_file_free - called on __fput()
  * @file: pointer to file structure being freed
@@ -54,29 +148,7 @@
 		return;
 
 	mutex_lock(&iint->mutex);
-	if (iint->opencount <= 0) {
-		printk(KERN_INFO
-		       "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n",
-		       __FUNCTION__, file->f_dentry->d_name.name,
-		       iint->readcount, iint->writecount,
-		       iint->opencount, atomic_long_read(&file->f_count));
-		if (!(iint->flags & IMA_IINT_DUMP_STACK)) {
-			dump_stack();
-			iint->flags |= IMA_IINT_DUMP_STACK;
-		}
-	}
-	iint->opencount--;
-
-	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-		iint->readcount--;
-
-	if (file->f_mode & FMODE_WRITE) {
-		iint->writecount--;
-		if (iint->writecount == 0) {
-			if (iint->version != inode->i_version)
-				iint->flags &= ~IMA_MEASURED;
-		}
-	}
+	ima_dec_counts(iint, inode, file);
 	mutex_unlock(&iint->mutex);
 	kref_put(&iint->refcount, iint_free);
 }
@@ -116,8 +188,7 @@
 {
 	int rc = 0;
 
-	iint->opencount++;
-	iint->readcount++;
+	ima_inc_counts(iint, file->f_mode);
 
 	rc = ima_collect_measurement(iint, file);
 	if (!rc)
@@ -125,15 +196,6 @@
 	return rc;
 }
 
-static void ima_update_counts(struct ima_iint_cache *iint, int mask)
-{
-	iint->opencount++;
-	if ((mask & MAY_WRITE) || (mask == 0))
-		iint->writecount++;
-	else if (mask & (MAY_READ | MAY_EXEC))
-		iint->readcount++;
-}
-
 /**
  * ima_path_check - based on policy, collect/store measurement.
  * @path: contains a pointer to the path to be measured
@@ -152,7 +214,7 @@
  * Always return 0 and audit dentry_open failures.
  * (Return code will be based upon measurement appraisal.)
  */
-int ima_path_check(struct path *path, int mask, int update_counts)
+int ima_path_check(struct path *path, int mask)
 {
 	struct inode *inode = path->dentry->d_inode;
 	struct ima_iint_cache *iint;
@@ -161,13 +223,11 @@
 
 	if (!ima_initialized || !S_ISREG(inode->i_mode))
 		return 0;
-	iint = ima_iint_find_insert_get(inode);
+	iint = ima_iint_find_get(inode);
 	if (!iint)
 		return 0;
 
 	mutex_lock(&iint->mutex);
-	if (update_counts)
-		ima_update_counts(iint, mask);
 
 	rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK);
 	if (rc < 0)
@@ -219,7 +279,7 @@
 
 	if (!ima_initialized || !S_ISREG(inode->i_mode))
 		return 0;
-	iint = ima_iint_find_insert_get(inode);
+	iint = ima_iint_find_get(inode);
 	if (!iint)
 		return -ENOMEM;
 
@@ -238,39 +298,6 @@
 }
 
 /*
- * ima_counts_put - decrement file counts
- *
- * File counts are incremented in ima_path_check. On file open
- * error, such as ETXTBSY, decrement the counts to prevent
- * unnecessary imbalance messages.
- */
-void ima_counts_put(struct path *path, int mask)
-{
-	struct inode *inode = path->dentry->d_inode;
-	struct ima_iint_cache *iint;
-
-	/* The inode may already have been freed, freeing the iint
-	 * with it. Verify the inode is not NULL before dereferencing
-	 * it.
-	 */
-	if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
-		return;
-	iint = ima_iint_find_insert_get(inode);
-	if (!iint)
-		return;
-
-	mutex_lock(&iint->mutex);
-	iint->opencount--;
-	if ((mask & MAY_WRITE) || (mask == 0))
-		iint->writecount--;
-	else if (mask & (MAY_READ | MAY_EXEC))
-		iint->readcount--;
-	mutex_unlock(&iint->mutex);
-
-	kref_put(&iint->refcount, iint_free);
-}
-
-/*
  * ima_counts_get - increment file counts
  *
  * - for IPC shm and shmat file.
@@ -286,16 +313,11 @@
 
 	if (!ima_initialized || !S_ISREG(inode->i_mode))
 		return;
-	iint = ima_iint_find_insert_get(inode);
+	iint = ima_iint_find_get(inode);
 	if (!iint)
 		return;
 	mutex_lock(&iint->mutex);
-	iint->opencount++;
-	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-		iint->readcount++;
-
-	if (file->f_mode & FMODE_WRITE)
-		iint->writecount++;
+	ima_inc_counts(iint, file->f_mode);
 	mutex_unlock(&iint->mutex);
 
 	kref_put(&iint->refcount, iint_free);
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
new file mode 100644
index 0000000..8974e20
--- /dev/null
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -0,0 +1,55 @@
+perf-diff(1)
+==============
+
+NAME
+----
+perf-diff - Read two perf.data files and display the differential profile
+
+SYNOPSIS
+--------
+[verse]
+'perf diff' [oldfile] [newfile]
+
+DESCRIPTION
+-----------
+This command displays the performance difference amongst two perf.data files
+captured via perf record.
+
+If no parameters are passed it will assume perf.data.old and perf.data.
+
+OPTIONS
+-------
+-d::
+--dsos=::
+	Only consider symbols in these dsos. CSV that understands
+	file://filename entries.
+
+-C::
+--comms=::
+	Only consider symbols in these comms. CSV that understands
+	file://filename entries.
+
+-S::
+--symbols=::
+	Only consider these symbols. CSV that understands
+	file://filename entries.
+
+-s::
+--sort=::
+	Sort by key(s): pid, comm, dso, symbol.
+
+-t::
+--field-separator=::
+
+	Use a special separator character and don't pad with spaces, replacing
+	all occurances of this separator in symbol names (and other output)
+	with a '.' character, that thus it's the only non valid separator.
+
+-v::
+--verbose::
+	Be verbose, for instance, show the raw counts in addition to the
+	diff.
+
+SEE ALSO
+--------
+linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 8fa6bf9..250e391 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -49,8 +49,9 @@
 ------------
 Probe points are defined by following syntax.
 
- "FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
+ "[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
 
+'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function.
 It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number.
 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9dccb18..abfabe9 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -39,6 +39,10 @@
 	Only consider these symbols. CSV that understands
 	file://filename entries.
 
+-s::
+--sort=::
+	Sort by key(s): pid, comm, dso, symbol, parent.
+
 -w::
 --field-width=::
 	Force each column width to the provided list, for large terminal
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 07065ef..60e5900 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -8,18 +8,43 @@
 SYNOPSIS
 --------
 [verse]
-'perf trace' [-i <file> | --input=file] symbol_name
+'perf trace' {record <script> | report <script> [args] }
 
 DESCRIPTION
 -----------
 This command reads the input file and displays the trace recorded.
 
+There are several variants of perf trace:
+
+  'perf trace' to see a detailed trace of the workload that was
+  recorded.
+
+  'perf trace record <script>' to record the events required for 'perf
+  trace report'.  <script> is the name displayed in the output of
+  'perf trace --list' i.e. the actual script name minus any language
+  extension.
+
+  'perf trace report <script>' to run and display the results of
+  <script>.  <script> is the name displayed in the output of 'perf
+  trace --list' i.e. the actual script name minus any language
+  extension.  The perf.data output from a previous run of 'perf trace
+  record <script>' is used and should be present for this command to
+  succeed.
+
 OPTIONS
 -------
 -D::
 --dump-raw-trace=::
         Display verbose dump of the trace data.
 
+-L::
+--Latency=::
+        Show latency attributes (irqs/preemption disabled, etc).
+
+-l::
+--list=::
+        Display a list of available trace scripts.
+
 -s::
 --script=::
         Process trace data with the given script ([lang]:script[.ext]).
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 4069996..7814dbb 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -370,7 +370,6 @@
 LIB_H += util/sort.h
 LIB_H += util/hist.h
 LIB_H += util/thread.h
-LIB_H += util/data_map.h
 LIB_H += util/probe-finder.h
 LIB_H += util/probe-event.h
 
@@ -428,6 +427,7 @@
 BUILTIN_OBJS += bench/sched-pipe.o
 BUILTIN_OBJS += bench/mem-memcpy.o
 
+BUILTIN_OBJS += builtin-diff.o
 BUILTIN_OBJS += builtin-help.o
 BUILTIN_OBJS += builtin-sched.o
 BUILTIN_OBJS += builtin-buildid-list.o
@@ -996,8 +996,6 @@
 	$(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
 	$(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
 	$(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
-	$(INSTALL) scripts/perl/Perf-Trace-Util/Makefile.PL -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util'
-	$(INSTALL) scripts/perl/Perf-Trace-Util/README -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util'
 ifdef BUILT_INS
 	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 	$(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 21a78d3..593ff25 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -26,7 +26,6 @@
 #include "util/sort.h"
 #include "util/hist.h"
 #include "util/session.h"
-#include "util/data_map.h"
 
 static char		const *input_name = "perf.data";
 
@@ -52,11 +51,6 @@
 	struct sym_ext	*ext;
 };
 
-static struct symbol_conf symbol_conf = {
-	.priv_size	  = sizeof(struct sym_priv),
-	.try_vmlinux_path = true,
-};
-
 static const char *sym_hist_filter;
 
 static int symbol_filter(struct map *map __used, struct symbol *sym)
@@ -122,30 +116,32 @@
 			h->ip[offset]);
 }
 
-static int hist_entry__add(struct addr_location *al, u64 count)
+static int perf_session__add_hist_entry(struct perf_session *self,
+					struct addr_location *al, u64 count)
 {
 	bool hit;
-	struct hist_entry *he = __hist_entry__add(al, NULL, count, &hit);
+	struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL,
+							       count, &hit);
 	if (he == NULL)
 		return -ENOMEM;
 	hist_hit(he, al->addr);
 	return 0;
 }
 
-static int process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct addr_location al;
 
 	dump_printf("(IP, %d): %d: %p\n", event->header.misc,
 		    event->ip.pid, (void *)(long)event->ip.ip);
 
-	if (event__preprocess_sample(event, &al, symbol_filter) < 0) {
+	if (event__preprocess_sample(event, session, &al, symbol_filter) < 0) {
 		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
 		return -1;
 	}
 
-	if (hist_entry__add(&al, 1)) {
+	if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) {
 		fprintf(stderr, "problem incrementing symbol count, "
 				"skipping event\n");
 		return -1;
@@ -429,11 +425,11 @@
 		free_source_line(he, len);
 }
 
-static void find_annotations(void)
+static void perf_session__find_annotations(struct perf_session *self)
 {
 	struct rb_node *nd;
 
-	for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
+	for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
 		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
 		struct sym_priv *priv;
 
@@ -454,7 +450,7 @@
 	}
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_sample_event	= process_sample_event,
 	.process_mmap_event	= event__process_mmap,
 	.process_comm_event	= event__process_comm,
@@ -463,17 +459,14 @@
 
 static int __cmd_annotate(void)
 {
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, force);
-	struct thread *idle;
 	int ret;
+	struct perf_session *session;
 
+	session = perf_session__new(input_name, O_RDONLY, force);
 	if (session == NULL)
 		return -ENOMEM;
 
-	idle = register_idle_thread();
-	register_perf_file_handler(&file_handler);
-
-	ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
+	ret = perf_session__process_events(session, &event_ops);
 	if (ret)
 		goto out_delete;
 
@@ -483,15 +476,14 @@
 	}
 
 	if (verbose > 3)
-		threads__fprintf(stdout);
+		perf_session__fprintf(session, stdout);
 
 	if (verbose > 2)
 		dsos__fprintf(stdout);
 
-	collapse__resort();
-	output__resort(event__total[0]);
-
-	find_annotations();
+	perf_session__collapse_resort(session);
+	perf_session__output_resort(session, session->event_total[0]);
+	perf_session__find_annotations(session);
 out_delete:
 	perf_session__delete(session);
 
@@ -524,29 +516,17 @@
 	OPT_END()
 };
 
-static void setup_sorting(void)
-{
-	char *tmp, *tok, *str = strdup(sort_order);
-
-	for (tok = strtok_r(str, ", ", &tmp);
-			tok; tok = strtok_r(NULL, ", ", &tmp)) {
-		if (sort_dimension__add(tok) < 0) {
-			error("Unknown --sort key: `%s'", tok);
-			usage_with_options(annotate_usage, options);
-		}
-	}
-
-	free(str);
-}
-
 int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 {
-	if (symbol__init(&symbol_conf) < 0)
-		return -1;
-
 	argc = parse_options(argc, argv, options, annotate_usage, 0);
 
-	setup_sorting();
+	symbol_conf.priv_size = sizeof(struct sym_priv);
+	symbol_conf.try_vmlinux_path = true;
+
+	if (symbol__init() < 0)
+		return -1;
+
+	setup_sorting(annotate_usage, options);
 
 	if (argc) {
 		/*
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index bfd16a1..e693e67 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -9,7 +9,6 @@
 #include "builtin.h"
 #include "perf.h"
 #include "util/cache.h"
-#include "util/data_map.h"
 #include "util/debug.h"
 #include "util/parse-options.h"
 #include "util/session.h"
@@ -55,8 +54,9 @@
 static int __cmd_buildid_list(void)
 {
 	int err = -1;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, force);
+	struct perf_session *session;
 
+	session = perf_session__new(input_name, O_RDONLY, force);
 	if (session == NULL)
 		return -1;
 
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
new file mode 100644
index 0000000..4d33b55
--- /dev/null
+++ b/tools/perf/builtin-diff.c
@@ -0,0 +1,248 @@
+/*
+ * builtin-diff.c
+ *
+ * Builtin diff command: Analyze two perf.data input files, look up and read
+ * DSOs and symbol information, sort them and produce a diff.
+ */
+#include "builtin.h"
+
+#include "util/debug.h"
+#include "util/event.h"
+#include "util/hist.h"
+#include "util/session.h"
+#include "util/sort.h"
+#include "util/symbol.h"
+#include "util/util.h"
+
+#include <stdlib.h>
+
+static char const *input_old = "perf.data.old",
+		  *input_new = "perf.data";
+static char	  diff__default_sort_order[] = "dso,symbol";
+static int  force;
+static bool show_displacement;
+
+static int perf_session__add_hist_entry(struct perf_session *self,
+					struct addr_location *al, u64 count)
+{
+	bool hit;
+	struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL,
+							       count, &hit);
+	if (he == NULL)
+		return -ENOMEM;
+
+	if (hit)
+		he->count += count;
+
+	return 0;
+}
+
+static int diff__process_sample_event(event_t *event, struct perf_session *session)
+{
+	struct addr_location al;
+	struct sample_data data = { .period = 1, };
+
+	dump_printf("(IP, %d): %d: %p\n", event->header.misc,
+		    event->ip.pid, (void *)(long)event->ip.ip);
+
+	if (event__preprocess_sample(event, session, &al, NULL) < 0) {
+		pr_warning("problem processing %d event, skipping it.\n",
+			   event->header.type);
+		return -1;
+	}
+
+	if (al.filtered)
+		return 0;
+
+	event__parse_sample(event, session->sample_type, &data);
+
+	if (al.sym && perf_session__add_hist_entry(session, &al, data.period)) {
+		pr_warning("problem incrementing symbol count, skipping event\n");
+		return -1;
+	}
+
+	session->events_stats.total += data.period;
+	return 0;
+}
+
+static struct perf_event_ops event_ops = {
+	.process_sample_event = diff__process_sample_event,
+	.process_mmap_event   = event__process_mmap,
+	.process_comm_event   = event__process_comm,
+	.process_exit_event   = event__process_task,
+	.process_fork_event   = event__process_task,
+	.process_lost_event   = event__process_lost,
+};
+
+static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
+						    struct hist_entry *he)
+{
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	struct hist_entry *iter;
+
+	while (*p != NULL) {
+		int cmp;
+		parent = *p;
+		iter = rb_entry(parent, struct hist_entry, rb_node);
+
+		cmp = strcmp(he->map->dso->name, iter->map->dso->name);
+		if (cmp > 0)
+			p = &(*p)->rb_left;
+		else if (cmp < 0)
+			p = &(*p)->rb_right;
+		else {
+			cmp = strcmp(he->sym->name, iter->sym->name);
+			if (cmp > 0)
+				p = &(*p)->rb_left;
+			else
+				p = &(*p)->rb_right;
+		}
+	}
+
+	rb_link_node(&he->rb_node, parent, p);
+	rb_insert_color(&he->rb_node, root);
+}
+
+static void perf_session__resort_by_name(struct perf_session *self)
+{
+	unsigned long position = 1;
+	struct rb_root tmp = RB_ROOT;
+	struct rb_node *next = rb_first(&self->hists);
+
+	while (next != NULL) {
+		struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
+
+		next = rb_next(&n->rb_node);
+		rb_erase(&n->rb_node, &self->hists);
+		n->position = position++;
+		perf_session__insert_hist_entry_by_name(&tmp, n);
+	}
+
+	self->hists = tmp;
+}
+
+static struct hist_entry *
+perf_session__find_hist_entry_by_name(struct perf_session *self,
+				      struct hist_entry *he)
+{
+	struct rb_node *n = self->hists.rb_node;
+
+	while (n) {
+		struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
+		int cmp = strcmp(he->map->dso->name, iter->map->dso->name);
+
+		if (cmp > 0)
+			n = n->rb_left;
+		else if (cmp < 0)
+			n = n->rb_right;
+		else {
+			cmp = strcmp(he->sym->name, iter->sym->name);
+			if (cmp > 0)
+				n = n->rb_left;
+			else if (cmp < 0)
+				n = n->rb_right;
+			else
+				return iter;
+		}
+	}
+
+	return NULL;
+}
+
+static void perf_session__match_hists(struct perf_session *old_session,
+				      struct perf_session *new_session)
+{
+	struct rb_node *nd;
+
+	perf_session__resort_by_name(old_session);
+
+	for (nd = rb_first(&new_session->hists); nd; nd = rb_next(nd)) {
+		struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node);
+		pos->pair = perf_session__find_hist_entry_by_name(old_session, pos);
+	}
+}
+
+static int __cmd_diff(void)
+{
+	int ret, i;
+	struct perf_session *session[2];
+
+	session[0] = perf_session__new(input_old, O_RDONLY, force);
+	session[1] = perf_session__new(input_new, O_RDONLY, force);
+	if (session[0] == NULL || session[1] == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < 2; ++i) {
+		ret = perf_session__process_events(session[i], &event_ops);
+		if (ret)
+			goto out_delete;
+		perf_session__output_resort(session[i], session[i]->events_stats.total);
+	}
+
+	perf_session__match_hists(session[0], session[1]);
+	perf_session__fprintf_hists(session[1], session[0],
+				    show_displacement, stdout);
+out_delete:
+	for (i = 0; i < 2; ++i)
+		perf_session__delete(session[i]);
+	return ret;
+}
+
+static const char *const diff_usage[] = {
+	"perf diff [<options>] [old_file] [new_file]",
+};
+
+static const struct option options[] = {
+	OPT_BOOLEAN('v', "verbose", &verbose,
+		    "be more verbose (show symbol address, etc)"),
+	OPT_BOOLEAN('m', "displacement", &show_displacement,
+		    "Show position displacement relative to baseline"),
+	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
+		    "dump raw trace in ASCII"),
+	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
+		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
+	OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths,
+		    "Don't shorten the pathnames taking into account the cwd"),
+	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
+		   "only consider symbols in these dsos"),
+	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
+		   "only consider symbols in these comms"),
+	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
+		   "only consider these symbols"),
+	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
+		   "sort by key(s): pid, comm, dso, symbol, parent"),
+	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
+		   "separator for columns, no spaces will be added between "
+		   "columns '.' is reserved."),
+	OPT_END()
+};
+
+int cmd_diff(int argc, const char **argv, const char *prefix __used)
+{
+	sort_order = diff__default_sort_order;
+	argc = parse_options(argc, argv, options, diff_usage, 0);
+	if (argc) {
+		if (argc > 2)
+			usage_with_options(diff_usage, options);
+		if (argc == 2) {
+			input_old = argv[0];
+			input_new = argv[1];
+		} else
+			input_new = argv[0];
+	}
+
+	symbol_conf.exclude_other = false;
+	if (symbol__init() < 0)
+		return -1;
+
+	setup_sorting(diff_usage, options);
+	setup_pager();
+
+	sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", NULL);
+	sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", NULL);
+	sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", NULL);
+
+	return __cmd_diff();
+}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 2071d24..fc21ad7 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -12,7 +12,6 @@
 #include "util/trace-event.h"
 
 #include "util/debug.h"
-#include "util/data_map.h"
 
 #include <linux/rbtree.h>
 
@@ -21,8 +20,6 @@
 
 static char const		*input_name = "perf.data";
 
-static u64			sample_type;
-
 static int			alloc_flag;
 static int			caller_flag;
 
@@ -312,7 +309,7 @@
 	}
 }
 
-static int process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct sample_data data;
 	struct thread *thread;
@@ -322,7 +319,7 @@
 	data.cpu = -1;
 	data.period = 1;
 
-	event__parse_sample(event, sample_type, &data);
+	event__parse_sample(event, session->sample_type, &data);
 
 	dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
 		event->header.misc,
@@ -330,7 +327,7 @@
 		(void *)(long)data.ip,
 		(long long)data.period);
 
-	thread = threads__findnew(event->ip.pid);
+	thread = perf_session__findnew(session, event->ip.pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
@@ -345,11 +342,9 @@
 	return 0;
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
 {
-	sample_type = type;
-
-	if (!(sample_type & PERF_SAMPLE_RAW)) {
+	if (!(session->sample_type & PERF_SAMPLE_RAW)) {
 		fprintf(stderr,
 			"No trace sample to read. Did you call perf record "
 			"without -R?");
@@ -359,28 +354,12 @@
 	return 0;
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_sample_event	= process_sample_event,
 	.process_comm_event	= event__process_comm,
 	.sample_type_check	= sample_type_check,
 };
 
-static int read_events(void)
-{
-	int err;
-	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
-
-	if (session == NULL)
-		return -ENOMEM;
-
-	register_idle_thread();
-	register_perf_file_handler(&file_handler);
-
-	err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
-	perf_session__delete(session);
-	return err;
-}
-
 static double fragmentation(unsigned long n_req, unsigned long n_alloc)
 {
 	if (n_alloc == 0)
@@ -389,7 +368,8 @@
 		return 100.0 - (100.0 * n_req / n_alloc);
 }
 
-static void __print_result(struct rb_root *root, int n_lines, int is_caller)
+static void __print_result(struct rb_root *root, struct perf_session *session,
+			   int n_lines, int is_caller)
 {
 	struct rb_node *next;
 
@@ -410,7 +390,7 @@
 		if (is_caller) {
 			addr = data->call_site;
 			if (!raw_ip)
-				sym = map_groups__find_function(kmaps, addr, NULL);
+				sym = map_groups__find_function(&session->kmaps, session, addr, NULL);
 		} else
 			addr = data->ptr;
 
@@ -451,12 +431,12 @@
 	printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
 }
 
-static void print_result(void)
+static void print_result(struct perf_session *session)
 {
 	if (caller_flag)
-		__print_result(&root_caller_sorted, caller_lines, 1);
+		__print_result(&root_caller_sorted, session, caller_lines, 1);
 	if (alloc_flag)
-		__print_result(&root_alloc_sorted, alloc_lines, 0);
+		__print_result(&root_alloc_sorted, session, alloc_lines, 0);
 	print_summary();
 }
 
@@ -524,12 +504,20 @@
 
 static int __cmd_kmem(void)
 {
-	setup_pager();
-	read_events();
-	sort_result();
-	print_result();
+	int err;
+	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
+	if (session == NULL)
+		return -ENOMEM;
 
-	return 0;
+	setup_pager();
+	err = perf_session__process_events(session, &event_ops);
+	if (err != 0)
+		goto out_delete;
+	sort_result();
+	print_result(session);
+out_delete:
+	perf_session__delete(session);
+	return err;
 }
 
 static const char * const kmem_usage[] = {
@@ -778,13 +766,13 @@
 
 int cmd_kmem(int argc, const char **argv, const char *prefix __used)
 {
-	symbol__init(0);
-
 	argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
 
 	if (!argc)
 		usage_with_options(kmem_usage, kmem_options);
 
+	symbol__init();
+
 	if (!strncmp(argv[0], "rec", 3)) {
 		return __cmd_record(argc, argv);
 	} else if (!strcmp(argv[0], "stat")) {
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 5a47c1e..7e741f5 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -38,34 +38,29 @@
 #include "util/strlist.h"
 #include "util/event.h"
 #include "util/debug.h"
+#include "util/symbol.h"
+#include "util/thread.h"
+#include "util/session.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"	/* For debugfs_path */
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
 
-/* Default vmlinux search paths */
-#define NR_SEARCH_PATH 4
-const char *default_search_path[NR_SEARCH_PATH] = {
-"/lib/modules/%s/build/vmlinux",		/* Custom build kernel */
-"/usr/lib/debug/lib/modules/%s/vmlinux",	/* Red Hat debuginfo */
-"/boot/vmlinux-debug-%s",			/* Ubuntu */
-"./vmlinux",					/* CWD */
-};
-
 #define MAX_PATH_LEN 256
 #define MAX_PROBES 128
 
 /* Session management structure */
 static struct {
-	char *vmlinux;
-	char *release;
-	int need_dwarf;
+	bool need_dwarf;
+	bool list_events;
+	bool force_add;
 	int nr_probe;
 	struct probe_point probes[MAX_PROBES];
 	struct strlist *dellist;
+	struct perf_session *psession;
+	struct map *kmap;
 } session;
 
-static bool listing;
 
 /* Parse an event definition. Note that any error must die. */
 static void parse_probe_event(const char *str)
@@ -77,7 +72,7 @@
 		die("Too many probes (> %d) are specified.", MAX_PROBES);
 
 	/* Parse perf-probe event into probe_point */
-	session.need_dwarf = parse_perf_probe_event(str, pp);
+	parse_perf_probe_event(str, pp, &session.need_dwarf);
 
 	pr_debug("%d arguments\n", pp->nr_args);
 }
@@ -120,34 +115,26 @@
 	return 0;
 }
 
-#ifndef NO_LIBDWARF
-static int open_default_vmlinux(void)
+/* Currently just checking function name from symbol map */
+static void evaluate_probe_point(struct probe_point *pp)
 {
-	struct utsname uts;
-	char fname[MAX_PATH_LEN];
-	int fd, ret, i;
+	struct symbol *sym;
+	sym = map__find_symbol_by_name(session.kmap, pp->function,
+				       session.psession, NULL);
+	if (!sym)
+		die("Kernel symbol \'%s\' not found - probe not added.",
+		    pp->function);
+}
 
-	ret = uname(&uts);
-	if (ret) {
-		pr_debug("uname() failed.\n");
-		return -errno;
+#ifndef NO_LIBDWARF
+static int open_vmlinux(void)
+{
+	if (map__load(session.kmap, session.psession, NULL) < 0) {
+		pr_debug("Failed to load kernel map.\n");
+		return -EINVAL;
 	}
-	session.release = uts.release;
-	for (i = 0; i < NR_SEARCH_PATH; i++) {
-		ret = snprintf(fname, MAX_PATH_LEN,
-			       default_search_path[i], session.release);
-		if (ret >= MAX_PATH_LEN || ret < 0) {
-			pr_debug("Filename(%d,%s) is too long.\n", i,
-				uts.release);
-			errno = E2BIG;
-			return -E2BIG;
-		}
-		pr_debug("try to open %s\n", fname);
-		fd = open(fname, O_RDONLY);
-		if (fd >= 0)
-			break;
-	}
-	return fd;
+	pr_debug("Try to open %s\n", session.kmap->dso->long_name);
+	return open(session.kmap->dso->long_name, O_RDONLY);
 }
 #endif
 
@@ -163,21 +150,22 @@
 	OPT_BOOLEAN('v', "verbose", &verbose,
 		    "be more verbose (show parsed arguments, etc)"),
 #ifndef NO_LIBDWARF
-	OPT_STRING('k', "vmlinux", &session.vmlinux, "file",
-		"vmlinux/module pathname"),
+	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
+		   "file", "vmlinux pathname"),
 #endif
-	OPT_BOOLEAN('l', "list", &listing, "list up current probe events"),
+	OPT_BOOLEAN('l', "list", &session.list_events,
+		    "list up current probe events"),
 	OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
 		opt_del_probe_event),
 	OPT_CALLBACK('a', "add", NULL,
 #ifdef NO_LIBDWARF
-		"FUNC[+OFFS|%return] [ARG ...]",
+		"[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
 #else
-		"FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
+		"[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
 #endif
 		"probe point definition, where\n"
-		"\t\tGRP:\tGroup name (optional)\n"
-		"\t\tNAME:\tEvent name\n"
+		"\t\tGROUP:\tGroup name (optional)\n"
+		"\t\tEVENT:\tEvent name\n"
 		"\t\tFUNC:\tFunction name\n"
 		"\t\tOFFS:\tOffset from function entry (in byte)\n"
 		"\t\t%return:\tPut the probe at function return\n"
@@ -191,6 +179,8 @@
 #endif
 		"\t\t\tkprobe-tracer argument format.)\n",
 		opt_add_probe_event),
+	OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
+		    " with existing name"),
 	OPT_END()
 };
 
@@ -204,13 +194,18 @@
 
 	argc = parse_options(argc, argv, options, probe_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
-	if (argc > 0)
+	if (argc > 0) {
+		if (strcmp(argv[0], "-") == 0) {
+			pr_warning("  Error: '-' is not supported.\n");
+			usage_with_options(probe_usage, options);
+		}
 		parse_probe_event_argv(argc, argv);
+	}
 
-	if ((session.nr_probe == 0 && !session.dellist && !listing))
+	if ((!session.nr_probe && !session.dellist && !session.list_events))
 		usage_with_options(probe_usage, options);
 
-	if (listing) {
+	if (session.list_events) {
 		if (session.nr_probe != 0 || session.dellist) {
 			pr_warning("  Error: Don't use --list with"
 				   " --add/--del.\n");
@@ -227,17 +222,28 @@
 			return 0;
 	}
 
+	/* Initialize symbol maps for vmlinux */
+	symbol_conf.sort_by_name = true;
+	if (symbol_conf.vmlinux_name == NULL)
+		symbol_conf.try_vmlinux_path = true;
+	if (symbol__init() < 0)
+		die("Failed to init symbol map.");
+	session.psession = perf_session__new(NULL, O_WRONLY, false);
+	if (session.psession == NULL)
+		die("Failed to init perf_session.");
+	session.kmap = map_groups__find_by_name(&session.psession->kmaps,
+						MAP__FUNCTION,
+						"[kernel.kallsyms]");
+	if (!session.kmap)
+		die("Could not find kernel map.\n");
+
 	if (session.need_dwarf)
 #ifdef NO_LIBDWARF
 		die("Debuginfo-analysis is not supported");
 #else	/* !NO_LIBDWARF */
 		pr_debug("Some probes require debuginfo.\n");
 
-	if (session.vmlinux) {
-		pr_debug("Try to open %s.", session.vmlinux);
-		fd = open(session.vmlinux, O_RDONLY);
-	} else
-		fd = open_default_vmlinux();
+	fd = open_vmlinux();
 	if (fd < 0) {
 		if (session.need_dwarf)
 			die("Could not open debuginfo file.");
@@ -255,15 +261,22 @@
 
 		lseek(fd, SEEK_SET, 0);
 		ret = find_probepoint(fd, pp);
-		if (ret < 0) {
-			if (session.need_dwarf)
-				die("Could not analyze debuginfo.");
-
-			pr_warning("An error occurred in debuginfo analysis. Try to use symbols.\n");
-			break;
+		if (ret > 0)
+			continue;
+		if (ret == 0) {	/* No error but failed to find probe point. */
+			synthesize_perf_probe_point(pp);
+			die("Probe point '%s' not found. - probe not added.",
+			    pp->probes[0]);
 		}
-		if (ret == 0)	/* No error but failed to find probe point. */
-			die("No probe point found.");
+		/* Error path */
+		if (session.need_dwarf) {
+			if (ret == -ENOENT)
+				pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n");
+			die("Could not analyze debuginfo.");
+		}
+		pr_debug("An error occurred in debuginfo analysis."
+			 " Try to use symbols.\n");
+		break;
 	}
 	close(fd);
 
@@ -276,6 +289,7 @@
 		if (pp->found)	/* This probe is already found. */
 			continue;
 
+		evaluate_probe_point(pp);
 		ret = synthesize_trace_kprobe_event(pp);
 		if (ret == -E2BIG)
 			die("probe point definition becomes too long.");
@@ -284,7 +298,8 @@
 	}
 
 	/* Settng up probe points */
-	add_trace_kprobe_events(session.probes, session.nr_probe);
+	add_trace_kprobe_events(session.probes, session.nr_probe,
+				session.force_add);
 	return 0;
 }
 
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4decbd1..63136d0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -123,7 +123,8 @@
 	write_output(buf, size);
 }
 
-static int process_synthesized_event(event_t *event)
+static int process_synthesized_event(event_t *event,
+				     struct perf_session *self __used)
 {
 	write_event(event, event->header.size);
 	return 0;
@@ -277,7 +278,7 @@
 
 	attr->mmap		= track;
 	attr->comm		= track;
-	attr->inherit		= (cpu < 0) && inherit;
+	attr->inherit		= inherit;
 	attr->disabled		= 1;
 
 try_again:
@@ -401,7 +402,7 @@
 	perf_header__write(&session->header, output, true);
 }
 
-static int __cmd_record(int argc, const char **argv)
+static int __cmd_record(int argc __used, const char **argv)
 {
 	int i, counter;
 	struct stat st;
@@ -409,6 +410,8 @@
 	int flags;
 	int err;
 	unsigned long waking = 0;
+	int child_ready_pipe[2], go_pipe[2];
+	char buf;
 
 	page_size = sysconf(_SC_PAGE_SIZE);
 	nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
@@ -419,11 +422,25 @@
 	signal(SIGCHLD, sig_handler);
 	signal(SIGINT, sig_handler);
 
+	if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) {
+		perror("failed to create pipes");
+		exit(-1);
+	}
+
 	if (!stat(output_name, &st) && st.st_size) {
-		if (!force && !append_file) {
-			fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
-					output_name);
-			exit(-1);
+		if (!force) {
+			if (!append_file) {
+				pr_err("Error, output file %s exists, use -A "
+				       "to append or -f to overwrite.\n",
+				       output_name);
+				exit(-1);
+			}
+		} else {
+			char oldname[PATH_MAX];
+			snprintf(oldname, sizeof(oldname), "%s.old",
+				 output_name);
+			unlink(oldname);
+			rename(output_name, oldname);
 		}
 	} else {
 		append_file = 0;
@@ -466,19 +483,65 @@
 
 	atexit(atexit_header);
 
-	if (!system_wide) {
-		pid = target_pid;
-		if (pid == -1)
-			pid = getpid();
-
-		open_counters(profile_cpu, pid);
-	} else {
-		if (profile_cpu != -1) {
-			open_counters(profile_cpu, target_pid);
-		} else {
-			for (i = 0; i < nr_cpus; i++)
-				open_counters(i, target_pid);
+	if (target_pid == -1) {
+		pid = fork();
+		if (pid < 0) {
+			perror("failed to fork");
+			exit(-1);
 		}
+
+		if (!pid) {
+			close(child_ready_pipe[0]);
+			close(go_pipe[1]);
+			fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
+
+			/*
+			 * Do a dummy execvp to get the PLT entry resolved,
+			 * so we avoid the resolver overhead on the real
+			 * execvp call.
+			 */
+			execvp("", (char **)argv);
+
+			/*
+			 * Tell the parent we're ready to go
+			 */
+			close(child_ready_pipe[1]);
+
+			/*
+			 * Wait until the parent tells us to go.
+			 */
+			if (read(go_pipe[0], &buf, 1) == -1)
+				perror("unable to read pipe");
+
+			execvp(argv[0], (char **)argv);
+
+			perror(argv[0]);
+			exit(-1);
+		}
+
+		child_pid = pid;
+
+		if (!system_wide)
+			target_pid = pid;
+
+		close(child_ready_pipe[1]);
+		close(go_pipe[0]);
+		/*
+		 * wait for child to settle
+		 */
+		if (read(child_ready_pipe[0], &buf, 1) == -1) {
+			perror("unable to read pipe");
+			exit(-1);
+		}
+		close(child_ready_pipe[0]);
+	}
+
+
+	if ((!system_wide && !inherit) || profile_cpu != -1) {
+		open_counters(profile_cpu, target_pid);
+	} else {
+		for (i = 0; i < nr_cpus; i++)
+			open_counters(i, target_pid);
 	}
 
 	if (file_new) {
@@ -488,33 +551,10 @@
 	}
 
 	if (!system_wide)
-		event__synthesize_thread(pid, process_synthesized_event);
+		event__synthesize_thread(pid, process_synthesized_event,
+					 session);
 	else
-		event__synthesize_threads(process_synthesized_event);
-
-	if (target_pid == -1 && argc) {
-		pid = fork();
-		if (pid < 0)
-			die("failed to fork");
-
-		if (!pid) {
-			if (execvp(argv[0], (char **)argv)) {
-				perror(argv[0]);
-				exit(-1);
-			}
-		} else {
-			/*
-			 * Wait a bit for the execv'ed child to appear
-			 * and be updated in /proc
-			 * FIXME: Do you know a less heuristical solution?
-			 */
-			usleep(1000);
-			event__synthesize_thread(pid,
-						 process_synthesized_event);
-		}
-
-		child_pid = pid;
-	}
+		event__synthesize_threads(process_synthesized_event, session);
 
 	if (realtime_prio) {
 		struct sched_param param;
@@ -526,6 +566,11 @@
 		}
 	}
 
+	/*
+	 * Let the child rip
+	 */
+	close(go_pipe[1]);
+
 	for (;;) {
 		int hits = samples;
 
@@ -620,13 +665,13 @@
 {
 	int counter;
 
-	symbol__init(0);
-
 	argc = parse_options(argc, argv, options, record_usage,
-		PARSE_OPT_STOP_AT_NON_OPTION);
-	if (!argc && target_pid == -1 && !system_wide)
+			    PARSE_OPT_STOP_AT_NON_OPTION);
+	if (!argc && target_pid == -1 && (!system_wide || profile_cpu == -1))
 		usage_with_options(record_usage, options);
 
+	symbol__init();
+
 	if (!nr_counters) {
 		nr_counters	= 1;
 		attrs[0].type	= PERF_TYPE_HARDWARE;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index e2ec49a..e50a6b1 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -27,467 +27,41 @@
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 
-#include "util/data_map.h"
 #include "util/thread.h"
 #include "util/sort.h"
 #include "util/hist.h"
 
 static char		const *input_name = "perf.data";
 
-static char		*dso_list_str, *comm_list_str, *sym_list_str,
-			*col_width_list_str;
-static struct strlist	*dso_list, *comm_list, *sym_list;
-
 static int		force;
 
-static int		full_paths;
-static int		show_nr_samples;
-
 static int		show_threads;
 static struct perf_read_values	show_threads_values;
 
 static char		default_pretty_printing_style[] = "normal";
 static char		*pretty_printing_style = default_pretty_printing_style;
 
-static int		exclude_other = 1;
-
 static char		callchain_default_opt[] = "fractal,0.5";
 
-static struct perf_session *session;
-
-static u64		sample_type;
-
-struct symbol_conf	symbol_conf;
-
-
-static size_t
-callchain__fprintf_left_margin(FILE *fp, int left_margin)
-{
-	int i;
-	int ret;
-
-	ret = fprintf(fp, "            ");
-
-	for (i = 0; i < left_margin; i++)
-		ret += fprintf(fp, " ");
-
-	return ret;
-}
-
-static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
-					  int left_margin)
-{
-	int i;
-	size_t ret = 0;
-
-	ret += callchain__fprintf_left_margin(fp, left_margin);
-
-	for (i = 0; i < depth; i++)
-		if (depth_mask & (1 << i))
-			ret += fprintf(fp, "|          ");
-		else
-			ret += fprintf(fp, "           ");
-
-	ret += fprintf(fp, "\n");
-
-	return ret;
-}
-static size_t
-ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
-		       int depth_mask, int count, u64 total_samples,
-		       int hits, int left_margin)
-{
-	int i;
-	size_t ret = 0;
-
-	ret += callchain__fprintf_left_margin(fp, left_margin);
-	for (i = 0; i < depth; i++) {
-		if (depth_mask & (1 << i))
-			ret += fprintf(fp, "|");
-		else
-			ret += fprintf(fp, " ");
-		if (!count && i == depth - 1) {
-			double percent;
-
-			percent = hits * 100.0 / total_samples;
-			ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
-		} else
-			ret += fprintf(fp, "%s", "          ");
-	}
-	if (chain->sym)
-		ret += fprintf(fp, "%s\n", chain->sym->name);
-	else
-		ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
-
-	return ret;
-}
-
-static struct symbol *rem_sq_bracket;
-static struct callchain_list rem_hits;
-
-static void init_rem_hits(void)
-{
-	rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
-	if (!rem_sq_bracket) {
-		fprintf(stderr, "Not enough memory to display remaining hits\n");
-		return;
-	}
-
-	strcpy(rem_sq_bracket->name, "[...]");
-	rem_hits.sym = rem_sq_bracket;
-}
-
-static size_t
-__callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
-			   u64 total_samples, int depth, int depth_mask,
-			   int left_margin)
-{
-	struct rb_node *node, *next;
-	struct callchain_node *child;
-	struct callchain_list *chain;
-	int new_depth_mask = depth_mask;
-	u64 new_total;
-	u64 remaining;
-	size_t ret = 0;
-	int i;
-
-	if (callchain_param.mode == CHAIN_GRAPH_REL)
-		new_total = self->children_hit;
-	else
-		new_total = total_samples;
-
-	remaining = new_total;
-
-	node = rb_first(&self->rb_root);
-	while (node) {
-		u64 cumul;
-
-		child = rb_entry(node, struct callchain_node, rb_node);
-		cumul = cumul_hits(child);
-		remaining -= cumul;
-
-		/*
-		 * The depth mask manages the output of pipes that show
-		 * the depth. We don't want to keep the pipes of the current
-		 * level for the last child of this depth.
-		 * Except if we have remaining filtered hits. They will
-		 * supersede the last child
-		 */
-		next = rb_next(node);
-		if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
-			new_depth_mask &= ~(1 << (depth - 1));
-
-		/*
-		 * But we keep the older depth mask for the line seperator
-		 * to keep the level link until we reach the last child
-		 */
-		ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
-						   left_margin);
-		i = 0;
-		list_for_each_entry(chain, &child->val, list) {
-			if (chain->ip >= PERF_CONTEXT_MAX)
-				continue;
-			ret += ipchain__fprintf_graph(fp, chain, depth,
-						      new_depth_mask, i++,
-						      new_total,
-						      cumul,
-						      left_margin);
-		}
-		ret += __callchain__fprintf_graph(fp, child, new_total,
-						  depth + 1,
-						  new_depth_mask | (1 << depth),
-						  left_margin);
-		node = next;
-	}
-
-	if (callchain_param.mode == CHAIN_GRAPH_REL &&
-		remaining && remaining != new_total) {
-
-		if (!rem_sq_bracket)
-			return ret;
-
-		new_depth_mask &= ~(1 << (depth - 1));
-
-		ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
-					      new_depth_mask, 0, new_total,
-					      remaining, left_margin);
-	}
-
-	return ret;
-}
-
-
-static size_t
-callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
-			 u64 total_samples, int left_margin)
-{
-	struct callchain_list *chain;
-	bool printed = false;
-	int i = 0;
-	int ret = 0;
-
-	list_for_each_entry(chain, &self->val, list) {
-		if (chain->ip >= PERF_CONTEXT_MAX)
-			continue;
-
-		if (!i++ && sort__first_dimension == SORT_SYM)
-			continue;
-
-		if (!printed) {
-			ret += callchain__fprintf_left_margin(fp, left_margin);
-			ret += fprintf(fp, "|\n");
-			ret += callchain__fprintf_left_margin(fp, left_margin);
-			ret += fprintf(fp, "---");
-
-			left_margin += 3;
-			printed = true;
-		} else
-			ret += callchain__fprintf_left_margin(fp, left_margin);
-
-		if (chain->sym)
-			ret += fprintf(fp, " %s\n", chain->sym->name);
-		else
-			ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
-	}
-
-	ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
-
-	return ret;
-}
-
-static size_t
-callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
-			u64 total_samples)
-{
-	struct callchain_list *chain;
-	size_t ret = 0;
-
-	if (!self)
-		return 0;
-
-	ret += callchain__fprintf_flat(fp, self->parent, total_samples);
-
-
-	list_for_each_entry(chain, &self->val, list) {
-		if (chain->ip >= PERF_CONTEXT_MAX)
-			continue;
-		if (chain->sym)
-			ret += fprintf(fp, "                %s\n", chain->sym->name);
-		else
-			ret += fprintf(fp, "                %p\n",
-					(void *)(long)chain->ip);
-	}
-
-	return ret;
-}
-
-static size_t
-hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
-			      u64 total_samples, int left_margin)
-{
-	struct rb_node *rb_node;
-	struct callchain_node *chain;
-	size_t ret = 0;
-
-	rb_node = rb_first(&self->sorted_chain);
-	while (rb_node) {
-		double percent;
-
-		chain = rb_entry(rb_node, struct callchain_node, rb_node);
-		percent = chain->hit * 100.0 / total_samples;
-		switch (callchain_param.mode) {
-		case CHAIN_FLAT:
-			ret += percent_color_fprintf(fp, "           %6.2f%%\n",
-						     percent);
-			ret += callchain__fprintf_flat(fp, chain, total_samples);
-			break;
-		case CHAIN_GRAPH_ABS: /* Falldown */
-		case CHAIN_GRAPH_REL:
-			ret += callchain__fprintf_graph(fp, chain, total_samples,
-							left_margin);
-		case CHAIN_NONE:
-		default:
-			break;
-		}
-		ret += fprintf(fp, "\n");
-		rb_node = rb_next(rb_node);
-	}
-
-	return ret;
-}
-
-static size_t
-hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
-{
-	struct sort_entry *se;
-	size_t ret;
-
-	if (exclude_other && !self->parent)
-		return 0;
-
-	if (total_samples)
-		ret = percent_color_fprintf(fp,
-					    field_sep ? "%.2f" : "   %6.2f%%",
-					(self->count * 100.0) / total_samples);
-	else
-		ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
-
-	if (show_nr_samples) {
-		if (field_sep)
-			fprintf(fp, "%c%lld", *field_sep, self->count);
-		else
-			fprintf(fp, "%11lld", self->count);
-	}
-
-	list_for_each_entry(se, &hist_entry__sort_list, list) {
-		if (se->elide)
-			continue;
-
-		fprintf(fp, "%s", field_sep ?: "  ");
-		ret += se->print(fp, self, se->width ? *se->width : 0);
-	}
-
-	ret += fprintf(fp, "\n");
-
-	if (callchain) {
-		int left_margin = 0;
-
-		if (sort__first_dimension == SORT_COMM) {
-			se = list_first_entry(&hist_entry__sort_list, typeof(*se),
-						list);
-			left_margin = se->width ? *se->width : 0;
-			left_margin -= thread__comm_len(self->thread);
-		}
-
-		hist_entry_callchain__fprintf(fp, self, total_samples,
-					      left_margin);
-	}
-
-	return ret;
-}
-
-/*
- *
- */
-
-static void dso__calc_col_width(struct dso *self)
-{
-	if (!col_width_list_str && !field_sep &&
-	    (!dso_list || strlist__has_entry(dso_list, self->name))) {
-		unsigned int slen = strlen(self->name);
-		if (slen > dsos__col_width)
-			dsos__col_width = slen;
-	}
-
-	self->slen_calculated = 1;
-}
-
-static void thread__comm_adjust(struct thread *self)
-{
-	char *comm = self->comm;
-
-	if (!col_width_list_str && !field_sep &&
-	    (!comm_list || strlist__has_entry(comm_list, comm))) {
-		unsigned int slen = strlen(comm);
-
-		if (slen > comms__col_width) {
-			comms__col_width = slen;
-			threads__col_width = slen + 6;
-		}
-	}
-}
-
-static int thread__set_comm_adjust(struct thread *self, const char *comm)
-{
-	int ret = thread__set_comm(self, comm);
-
-	if (ret)
-		return ret;
-
-	thread__comm_adjust(self);
-
-	return 0;
-}
-
-static int call__match(struct symbol *sym)
-{
-	if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
-		return 1;
-
-	return 0;
-}
-
-static struct symbol **resolve_callchain(struct thread *thread,
-					 struct ip_callchain *chain,
-					 struct symbol **parent)
-{
-	u8 cpumode = PERF_RECORD_MISC_USER;
-	struct symbol **syms = NULL;
-	unsigned int i;
-
-	if (callchain) {
-		syms = calloc(chain->nr, sizeof(*syms));
-		if (!syms) {
-			fprintf(stderr, "Can't allocate memory for symbols\n");
-			exit(-1);
-		}
-	}
-
-	for (i = 0; i < chain->nr; i++) {
-		u64 ip = chain->ips[i];
-		struct addr_location al;
-
-		if (ip >= PERF_CONTEXT_MAX) {
-			switch (ip) {
-			case PERF_CONTEXT_HV:
-				cpumode = PERF_RECORD_MISC_HYPERVISOR;	break;
-			case PERF_CONTEXT_KERNEL:
-				cpumode = PERF_RECORD_MISC_KERNEL;	break;
-			case PERF_CONTEXT_USER:
-				cpumode = PERF_RECORD_MISC_USER;	break;
-			default:
-				break;
-			}
-			continue;
-		}
-
-		thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
-					   ip, &al, NULL);
-		if (al.sym != NULL) {
-			if (sort__has_parent && !*parent &&
-			    call__match(al.sym))
-				*parent = al.sym;
-			if (!callchain)
-				break;
-			syms[i] = al.sym;
-		}
-	}
-
-	return syms;
-}
-
-/*
- * collect histogram counts
- */
-
-static int hist_entry__add(struct addr_location *al,
-			   struct ip_callchain *chain, u64 count)
+static int perf_session__add_hist_entry(struct perf_session *self,
+					struct addr_location *al,
+					struct ip_callchain *chain, u64 count)
 {
 	struct symbol **syms = NULL, *parent = NULL;
 	bool hit;
 	struct hist_entry *he;
 
-	if ((sort__has_parent || callchain) && chain)
-		syms = resolve_callchain(al->thread, chain, &parent);
-
-	he = __hist_entry__add(al, parent, count, &hit);
+	if ((sort__has_parent || symbol_conf.use_callchain) && chain)
+		syms = perf_session__resolve_callchain(self, al->thread,
+						       chain, &parent);
+	he = __perf_session__add_hist_entry(self, al, parent, count, &hit);
 	if (he == NULL)
 		return -ENOMEM;
 
 	if (hit)
 		he->count += count;
 
-	if (callchain) {
+	if (symbol_conf.use_callchain) {
 		if (!hit)
 			callchain_init(&he->callchain);
 		append_chain(&he->callchain, chain, syms);
@@ -497,100 +71,6 @@
 	return 0;
 }
 
-static size_t output__fprintf(FILE *fp, u64 total_samples)
-{
-	struct hist_entry *pos;
-	struct sort_entry *se;
-	struct rb_node *nd;
-	size_t ret = 0;
-	unsigned int width;
-	char *col_width = col_width_list_str;
-	int raw_printing_style;
-
-	raw_printing_style = !strcmp(pretty_printing_style, "raw");
-
-	init_rem_hits();
-
-	fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
-	fprintf(fp, "#\n");
-
-	fprintf(fp, "# Overhead");
-	if (show_nr_samples) {
-		if (field_sep)
-			fprintf(fp, "%cSamples", *field_sep);
-		else
-			fputs("  Samples  ", fp);
-	}
-	list_for_each_entry(se, &hist_entry__sort_list, list) {
-		if (se->elide)
-			continue;
-		if (field_sep) {
-			fprintf(fp, "%c%s", *field_sep, se->header);
-			continue;
-		}
-		width = strlen(se->header);
-		if (se->width) {
-			if (col_width_list_str) {
-				if (col_width) {
-					*se->width = atoi(col_width);
-					col_width = strchr(col_width, ',');
-					if (col_width)
-						++col_width;
-				}
-			}
-			width = *se->width = max(*se->width, width);
-		}
-		fprintf(fp, "  %*s", width, se->header);
-	}
-	fprintf(fp, "\n");
-
-	if (field_sep)
-		goto print_entries;
-
-	fprintf(fp, "# ........");
-	if (show_nr_samples)
-		fprintf(fp, " ..........");
-	list_for_each_entry(se, &hist_entry__sort_list, list) {
-		unsigned int i;
-
-		if (se->elide)
-			continue;
-
-		fprintf(fp, "  ");
-		if (se->width)
-			width = *se->width;
-		else
-			width = strlen(se->header);
-		for (i = 0; i < width; i++)
-			fprintf(fp, ".");
-	}
-	fprintf(fp, "\n");
-
-	fprintf(fp, "#\n");
-
-print_entries:
-	for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
-		pos = rb_entry(nd, struct hist_entry, rb_node);
-		ret += hist_entry__fprintf(fp, pos, total_samples);
-	}
-
-	if (sort_order == default_sort_order &&
-			parent_pattern == default_parent_pattern) {
-		fprintf(fp, "#\n");
-		fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
-		fprintf(fp, "#\n");
-	}
-	fprintf(fp, "\n");
-
-	free(rem_sq_bracket);
-
-	if (show_threads)
-		perf_read_values_display(fp, &show_threads_values,
-					 raw_printing_style);
-
-	return ret;
-}
-
 static int validate_chain(struct ip_callchain *chain, event_t *event)
 {
 	unsigned int chain_size;
@@ -604,17 +84,12 @@
 	return 0;
 }
 
-static int process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
-	struct sample_data data;
-	int cpumode;
+	struct sample_data data = { .period = 1, };
 	struct addr_location al;
-	struct thread *thread;
 
-	memset(&data, 0, sizeof(data));
-	data.period = 1;
-
-	event__parse_sample(event, sample_type, &data);
+	event__parse_sample(event, session->sample_type, &data);
 
 	dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
 		event->header.misc,
@@ -622,7 +97,7 @@
 		(void *)(long)data.ip,
 		(long long)data.period);
 
-	if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+	if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
 		unsigned int i;
 
 		dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
@@ -640,65 +115,25 @@
 		}
 	}
 
-	thread = threads__findnew(data.pid);
-	if (thread == NULL) {
-		pr_debug("problem processing %d event, skipping it.\n",
+	if (event__preprocess_sample(event, session, &al, NULL) < 0) {
+		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
 		return -1;
 	}
 
-	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
-
-	if (comm_list && !strlist__has_entry(comm_list, thread->comm))
+	if (al.filtered)
 		return 0;
 
-	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-
-	thread__find_addr_location(thread, cpumode,
-				   MAP__FUNCTION, data.ip, &al, NULL);
-	/*
-	 * We have to do this here as we may have a dso with no symbol hit that
-	 * has a name longer than the ones with symbols sampled.
-	 */
-	if (al.map && !sort_dso.elide && !al.map->dso->slen_calculated)
-		dso__calc_col_width(al.map->dso);
-
-	if (dso_list &&
-	    (!al.map || !al.map->dso ||
-	     !(strlist__has_entry(dso_list, al.map->dso->short_name) ||
-	       (al.map->dso->short_name != al.map->dso->long_name &&
-		strlist__has_entry(dso_list, al.map->dso->long_name)))))
-		return 0;
-
-	if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
-		return 0;
-
-	if (hist_entry__add(&al, data.callchain, data.period)) {
+	if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) {
 		pr_debug("problem incrementing symbol count, skipping event\n");
 		return -1;
 	}
 
-	event__stats.total += data.period;
-
+	session->events_stats.total += data.period;
 	return 0;
 }
 
-static int process_comm_event(event_t *event)
-{
-	struct thread *thread = threads__findnew(event->comm.pid);
-
-	dump_printf(": %s:%d\n", event->comm.comm, event->comm.pid);
-
-	if (thread == NULL ||
-	    thread__set_comm_adjust(thread, event->comm.comm)) {
-		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int process_read_event(event_t *event)
+static int process_read_event(event_t *event, struct perf_session *session __used)
 {
 	struct perf_event_attr *attr;
 
@@ -721,25 +156,23 @@
 	return 0;
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
 {
-	sample_type = type;
-
-	if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
+	if (!(session->sample_type & PERF_SAMPLE_CALLCHAIN)) {
 		if (sort__has_parent) {
 			fprintf(stderr, "selected --sort parent, but no"
 					" callchain data. Did you call"
 					" perf record without -g?\n");
 			return -1;
 		}
-		if (callchain) {
+		if (symbol_conf.use_callchain) {
 			fprintf(stderr, "selected -g but no callchain data."
 					" Did you call perf record without"
 					" -g?\n");
 			return -1;
 		}
-	} else if (callchain_param.mode != CHAIN_NONE && !callchain) {
-			callchain = 1;
+	} else if (callchain_param.mode != CHAIN_NONE && !symbol_conf.use_callchain) {
+			symbol_conf.use_callchain = true;
 			if (register_callchain_param(&callchain_param) < 0) {
 				fprintf(stderr, "Can't register callchain"
 						" params\n");
@@ -750,10 +183,10 @@
 	return 0;
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_sample_event	= process_sample_event,
 	.process_mmap_event	= event__process_mmap,
-	.process_comm_event	= process_comm_event,
+	.process_comm_event	= event__process_comm,
 	.process_exit_event	= event__process_task,
 	.process_fork_event	= event__process_task,
 	.process_lost_event	= event__process_lost,
@@ -764,23 +197,17 @@
 
 static int __cmd_report(void)
 {
-	struct thread *idle;
 	int ret;
+	struct perf_session *session;
 
 	session = perf_session__new(input_name, O_RDONLY, force);
 	if (session == NULL)
 		return -ENOMEM;
 
-	idle = register_idle_thread();
-	thread__comm_adjust(idle);
-
 	if (show_threads)
 		perf_read_values_init(&show_threads_values);
 
-	register_perf_file_handler(&file_handler);
-
-	ret = perf_session__process_events(session, full_paths,
-					   &event__cwdlen, &event__cwd);
+	ret = perf_session__process_events(session, &event_ops);
 	if (ret)
 		goto out_delete;
 
@@ -790,17 +217,25 @@
 	}
 
 	if (verbose > 3)
-		threads__fprintf(stdout);
+		perf_session__fprintf(session, stdout);
 
 	if (verbose > 2)
 		dsos__fprintf(stdout);
 
-	collapse__resort();
-	output__resort(event__stats.total);
-	output__fprintf(stdout, event__stats.total);
+	perf_session__collapse_resort(session);
+	perf_session__output_resort(session, session->events_stats.total);
+	fprintf(stdout, "# Samples: %ld\n#\n", session->events_stats.total);
+	perf_session__fprintf_hists(session, NULL, false, stdout);
+	if (sort_order == default_sort_order &&
+	    parent_pattern == default_parent_pattern)
+		fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n");
 
-	if (show_threads)
+	if (show_threads) {
+		bool raw_printing_style = !strcmp(pretty_printing_style, "raw");
+		perf_read_values_display(stdout, &show_threads_values,
+					 raw_printing_style);
 		perf_read_values_destroy(&show_threads_values);
+	}
 out_delete:
 	perf_session__delete(session);
 	return ret;
@@ -813,7 +248,7 @@
 	char *tok;
 	char *endptr;
 
-	callchain = 1;
+	symbol_conf.use_callchain = true;
 
 	if (!arg)
 		return 0;
@@ -834,7 +269,7 @@
 
 	else if (!strncmp(tok, "none", strlen(arg))) {
 		callchain_param.mode = CHAIN_NONE;
-		callchain = 0;
+		symbol_conf.use_callchain = true;
 
 		return 0;
 	}
@@ -877,7 +312,7 @@
 	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
 	OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
 		    "load module symbols - WARNING: use only with -k and LIVE kernel"),
-	OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
+	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
 		    "Show a column with the number of samples"),
 	OPT_BOOLEAN('T', "threads", &show_threads,
 		    "Show per-thread event counters"),
@@ -885,78 +320,46 @@
 		   "pretty printing style key: normal raw"),
 	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
 		   "sort by key(s): pid, comm, dso, symbol, parent"),
-	OPT_BOOLEAN('P', "full-paths", &full_paths,
+	OPT_BOOLEAN('P', "full-paths", &event_ops.full_paths,
 		    "Don't shorten the pathnames taking into account the cwd"),
 	OPT_STRING('p', "parent", &parent_pattern, "regex",
 		   "regex filter to identify parent, see: '--sort parent'"),
-	OPT_BOOLEAN('x', "exclude-other", &exclude_other,
+	OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
 		    "Only display entries with parent-match"),
 	OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
 		     "Display callchains using output_type and min percent threshold. "
 		     "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
-	OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
+	OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
 		   "only consider symbols in these dsos"),
-	OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
+	OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
 		   "only consider symbols in these comms"),
-	OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
+	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
 		   "only consider these symbols"),
-	OPT_STRING('w', "column-widths", &col_width_list_str,
+	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
 		   "width[,width...]",
 		   "don't try to adjust column width, use these fixed values"),
-	OPT_STRING('t', "field-separator", &field_sep, "separator",
+	OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
 		   "separator for columns, no spaces will be added between "
 		   "columns '.' is reserved."),
 	OPT_END()
 };
 
-static void setup_sorting(void)
-{
-	char *tmp, *tok, *str = strdup(sort_order);
-
-	for (tok = strtok_r(str, ", ", &tmp);
-			tok; tok = strtok_r(NULL, ", ", &tmp)) {
-		if (sort_dimension__add(tok) < 0) {
-			error("Unknown --sort key: `%s'", tok);
-			usage_with_options(report_usage, options);
-		}
-	}
-
-	free(str);
-}
-
-static void setup_list(struct strlist **list, const char *list_str,
-		       struct sort_entry *se, const char *list_name,
-		       FILE *fp)
-{
-	if (list_str) {
-		*list = strlist__new(true, list_str);
-		if (!*list) {
-			fprintf(stderr, "problems parsing %s list\n",
-				list_name);
-			exit(129);
-		}
-		if (strlist__nr_entries(*list) == 1) {
-			fprintf(fp, "# %s: %s\n", list_name,
-				strlist__entry(*list, 0)->s);
-			se->elide = true;
-		}
-	}
-}
-
 int cmd_report(int argc, const char **argv, const char *prefix __used)
 {
-	if (symbol__init(&symbol_conf) < 0)
-		return -1;
-
 	argc = parse_options(argc, argv, options, report_usage, 0);
 
-	setup_sorting();
+	setup_pager();
+
+	if (symbol__init() < 0)
+		return -1;
+
+	setup_sorting(report_usage, options);
 
 	if (parent_pattern != default_parent_pattern) {
 		sort_dimension__add("parent");
 		sort_parent.elide = 1;
 	} else
-		exclude_other = 0;
+		symbol_conf.exclude_other = false;
 
 	/*
 	 * Any (unrecognized) arguments left?
@@ -964,17 +367,9 @@
 	if (argc)
 		usage_with_options(report_usage, options);
 
-	setup_pager();
-
-	setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
-	setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
-	setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
-
-	if (field_sep && *field_sep == '.') {
-		fputs("'.' is the only non valid --field-separator argument\n",
-		      stderr);
-		exit(129);
-	}
+	sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
+	sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
+	sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
 
 	return __cmd_report();
 }
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 65021fe..80209df 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -12,7 +12,6 @@
 #include "util/trace-event.h"
 
 #include "util/debug.h"
-#include "util/data_map.h"
 
 #include <sys/prctl.h>
 
@@ -22,8 +21,6 @@
 
 static char			const *input_name = "perf.data";
 
-static u64			sample_type;
-
 static char			default_sort_order[] = "avg, max, switch, runtime";
 static char			*sort_order = default_sort_order;
 
@@ -731,18 +728,21 @@
 
 struct trace_sched_handler {
 	void (*switch_event)(struct trace_switch_event *,
+			     struct perf_session *,
 			     struct event *,
 			     int cpu,
 			     u64 timestamp,
 			     struct thread *thread);
 
 	void (*runtime_event)(struct trace_runtime_event *,
+			      struct perf_session *,
 			      struct event *,
 			      int cpu,
 			      u64 timestamp,
 			      struct thread *thread);
 
 	void (*wakeup_event)(struct trace_wakeup_event *,
+			     struct perf_session *,
 			     struct event *,
 			     int cpu,
 			     u64 timestamp,
@@ -755,6 +755,7 @@
 			   struct thread *thread);
 
 	void (*migrate_task_event)(struct trace_migrate_task_event *,
+			   struct perf_session *session,
 			   struct event *,
 			   int cpu,
 			   u64 timestamp,
@@ -764,6 +765,7 @@
 
 static void
 replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
+		    struct perf_session *session __used,
 		    struct event *event,
 		    int cpu __used,
 		    u64 timestamp __used,
@@ -790,6 +792,7 @@
 
 static void
 replay_switch_event(struct trace_switch_event *switch_event,
+		    struct perf_session *session __used,
 		    struct event *event,
 		    int cpu,
 		    u64 timestamp,
@@ -1023,6 +1026,7 @@
 
 static void
 latency_switch_event(struct trace_switch_event *switch_event,
+		     struct perf_session *session,
 		     struct event *event __used,
 		     int cpu,
 		     u64 timestamp,
@@ -1046,8 +1050,8 @@
 		die("hm, delta: %Ld < 0 ?\n", delta);
 
 
-	sched_out = threads__findnew(switch_event->prev_pid);
-	sched_in = threads__findnew(switch_event->next_pid);
+	sched_out = perf_session__findnew(session, switch_event->prev_pid);
+	sched_in = perf_session__findnew(session, switch_event->next_pid);
 
 	out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
 	if (!out_events) {
@@ -1075,12 +1079,13 @@
 
 static void
 latency_runtime_event(struct trace_runtime_event *runtime_event,
+		     struct perf_session *session,
 		     struct event *event __used,
 		     int cpu,
 		     u64 timestamp,
 		     struct thread *this_thread __used)
 {
-	struct thread *thread = threads__findnew(runtime_event->pid);
+	struct thread *thread = perf_session__findnew(session, runtime_event->pid);
 	struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
 
 	BUG_ON(cpu >= MAX_CPUS || cpu < 0);
@@ -1097,6 +1102,7 @@
 
 static void
 latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
+		     struct perf_session *session,
 		     struct event *__event __used,
 		     int cpu __used,
 		     u64 timestamp,
@@ -1110,7 +1116,7 @@
 	if (!wakeup_event->success)
 		return;
 
-	wakee = threads__findnew(wakeup_event->pid);
+	wakee = perf_session__findnew(session, wakeup_event->pid);
 	atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
 	if (!atoms) {
 		thread_atoms_insert(wakee);
@@ -1144,6 +1150,7 @@
 
 static void
 latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
+		     struct perf_session *session,
 		     struct event *__event __used,
 		     int cpu __used,
 		     u64 timestamp,
@@ -1159,7 +1166,7 @@
 	if (profile_cpu == -1)
 		return;
 
-	migrant = threads__findnew(migrate_task_event->pid);
+	migrant = perf_session__findnew(session, migrate_task_event->pid);
 	atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
 	if (!atoms) {
 		thread_atoms_insert(migrant);
@@ -1354,7 +1361,7 @@
 static struct trace_sched_handler *trace_handler;
 
 static void
-process_sched_wakeup_event(void *data,
+process_sched_wakeup_event(void *data, struct perf_session *session,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1371,7 +1378,8 @@
 	FILL_FIELD(wakeup_event, cpu, event, data);
 
 	if (trace_handler->wakeup_event)
-		trace_handler->wakeup_event(&wakeup_event, event, cpu, timestamp, thread);
+		trace_handler->wakeup_event(&wakeup_event, session, event,
+					    cpu, timestamp, thread);
 }
 
 /*
@@ -1389,6 +1397,7 @@
 
 static void
 map_switch_event(struct trace_switch_event *switch_event,
+		 struct perf_session *session,
 		 struct event *event __used,
 		 int this_cpu,
 		 u64 timestamp,
@@ -1416,8 +1425,8 @@
 		die("hm, delta: %Ld < 0 ?\n", delta);
 
 
-	sched_out = threads__findnew(switch_event->prev_pid);
-	sched_in = threads__findnew(switch_event->next_pid);
+	sched_out = perf_session__findnew(session, switch_event->prev_pid);
+	sched_in = perf_session__findnew(session, switch_event->next_pid);
 
 	curr_thread[this_cpu] = sched_in;
 
@@ -1467,7 +1476,7 @@
 
 
 static void
-process_sched_switch_event(void *data,
+process_sched_switch_event(void *data, struct perf_session *session,
 			   struct event *event,
 			   int this_cpu,
 			   u64 timestamp __used,
@@ -1494,13 +1503,14 @@
 			nr_context_switch_bugs++;
 	}
 	if (trace_handler->switch_event)
-		trace_handler->switch_event(&switch_event, event, this_cpu, timestamp, thread);
+		trace_handler->switch_event(&switch_event, session, event,
+					    this_cpu, timestamp, thread);
 
 	curr_pid[this_cpu] = switch_event.next_pid;
 }
 
 static void
-process_sched_runtime_event(void *data,
+process_sched_runtime_event(void *data, struct perf_session *session,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1514,7 +1524,7 @@
 	FILL_FIELD(runtime_event, vruntime, event, data);
 
 	if (trace_handler->runtime_event)
-		trace_handler->runtime_event(&runtime_event, event, cpu, timestamp, thread);
+		trace_handler->runtime_event(&runtime_event, session, event, cpu, timestamp, thread);
 }
 
 static void
@@ -1534,7 +1544,8 @@
 	FILL_FIELD(fork_event, child_pid, event, data);
 
 	if (trace_handler->fork_event)
-		trace_handler->fork_event(&fork_event, event, cpu, timestamp, thread);
+		trace_handler->fork_event(&fork_event, event,
+					  cpu, timestamp, thread);
 }
 
 static void
@@ -1548,7 +1559,7 @@
 }
 
 static void
-process_sched_migrate_task_event(void *data,
+process_sched_migrate_task_event(void *data, struct perf_session *session,
 			   struct event *event,
 			   int cpu __used,
 			   u64 timestamp __used,
@@ -1564,12 +1575,13 @@
 	FILL_FIELD(migrate_task_event, cpu, event, data);
 
 	if (trace_handler->migrate_task_event)
-		trace_handler->migrate_task_event(&migrate_task_event, event, cpu, timestamp, thread);
+		trace_handler->migrate_task_event(&migrate_task_event, session,
+						 event, cpu, timestamp, thread);
 }
 
 static void
-process_raw_event(event_t *raw_event __used, void *data,
-		  int cpu, u64 timestamp, struct thread *thread)
+process_raw_event(event_t *raw_event __used, struct perf_session *session,
+		  void *data, int cpu, u64 timestamp, struct thread *thread)
 {
 	struct event *event;
 	int type;
@@ -1579,27 +1591,27 @@
 	event = trace_find_event(type);
 
 	if (!strcmp(event->name, "sched_switch"))
-		process_sched_switch_event(data, event, cpu, timestamp, thread);
+		process_sched_switch_event(data, session, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_stat_runtime"))
-		process_sched_runtime_event(data, event, cpu, timestamp, thread);
+		process_sched_runtime_event(data, session, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_wakeup"))
-		process_sched_wakeup_event(data, event, cpu, timestamp, thread);
+		process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_wakeup_new"))
-		process_sched_wakeup_event(data, event, cpu, timestamp, thread);
+		process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_process_fork"))
 		process_sched_fork_event(data, event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_process_exit"))
 		process_sched_exit_event(event, cpu, timestamp, thread);
 	if (!strcmp(event->name, "sched_migrate_task"))
-		process_sched_migrate_task_event(data, event, cpu, timestamp, thread);
+		process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
 }
 
-static int process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct sample_data data;
 	struct thread *thread;
 
-	if (!(sample_type & PERF_SAMPLE_RAW))
+	if (!(session->sample_type & PERF_SAMPLE_RAW))
 		return 0;
 
 	memset(&data, 0, sizeof(data));
@@ -1607,7 +1619,7 @@
 	data.cpu = -1;
 	data.period = -1;
 
-	event__parse_sample(event, sample_type, &data);
+	event__parse_sample(event, session->sample_type, &data);
 
 	dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
 		event->header.misc,
@@ -1615,7 +1627,7 @@
 		(void *)(long)data.ip,
 		(long long)data.period);
 
-	thread = threads__findnew(data.pid);
+	thread = perf_session__findnew(session, data.pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
@@ -1627,12 +1639,13 @@
 	if (profile_cpu != -1 && profile_cpu != (int)data.cpu)
 		return 0;
 
-	process_raw_event(event, data.raw_data, data.cpu, data.time, thread);
+	process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread);
 
 	return 0;
 }
 
-static int process_lost_event(event_t *event __used)
+static int process_lost_event(event_t *event __used,
+			      struct perf_session *session __used)
 {
 	nr_lost_chunks++;
 	nr_lost_events += event->lost.lost;
@@ -1640,11 +1653,9 @@
 	return 0;
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session __used)
 {
-	sample_type = type;
-
-	if (!(sample_type & PERF_SAMPLE_RAW)) {
+	if (!(session->sample_type & PERF_SAMPLE_RAW)) {
 		fprintf(stderr,
 			"No trace sample to read. Did you call perf record "
 			"without -R?");
@@ -1654,7 +1665,7 @@
 	return 0;
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_sample_event	= process_sample_event,
 	.process_comm_event	= event__process_comm,
 	.process_lost_event	= process_lost_event,
@@ -1665,14 +1676,10 @@
 {
 	int err;
 	struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
-
 	if (session == NULL)
 		return -ENOMEM;
 
-	register_idle_thread();
-	register_perf_file_handler(&file_handler);
-
-	err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
+	err = perf_session__process_events(session, &event_ops);
 	perf_session__delete(session);
 	return err;
 }
@@ -1904,7 +1911,7 @@
 	if (!strcmp(argv[0], "trace"))
 		return cmd_trace(argc, argv, prefix);
 
-	symbol__init(0);
+	symbol__init();
 	if (!strncmp(argv[0], "rec", 3)) {
 		return __cmd_record(argc, argv);
 	} else if (!strncmp(argv[0], "lat", 3)) {
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 759dd2b..a589a43 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -30,15 +30,12 @@
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 #include "util/event.h"
-#include "util/data_map.h"
+#include "util/session.h"
 #include "util/svghelper.h"
 
 static char		const *input_name = "perf.data";
 static char		const *output_name = "output.svg";
 
-
-static u64		sample_type;
-
 static unsigned int	numcpus;
 static u64		min_freq;	/* Lowest CPU frequency seen */
 static u64		max_freq;	/* Highest CPU frequency seen */
@@ -281,21 +278,19 @@
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int
-process_comm_event(event_t *event)
+static int process_comm_event(event_t *event, struct perf_session *session __used)
 {
 	pid_set_comm(event->comm.pid, event->comm.comm);
 	return 0;
 }
-static int
-process_fork_event(event_t *event)
+
+static int process_fork_event(event_t *event, struct perf_session *session __used)
 {
 	pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
 	return 0;
 }
 
-static int
-process_exit_event(event_t *event)
+static int process_exit_event(event_t *event, struct perf_session *session __used)
 {
 	pid_exit(event->fork.pid, event->fork.time);
 	return 0;
@@ -480,17 +475,16 @@
 }
 
 
-static int
-process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct sample_data data;
 	struct trace_entry *te;
 
 	memset(&data, 0, sizeof(data));
 
-	event__parse_sample(event, sample_type, &data);
+	event__parse_sample(event, session->sample_type, &data);
 
-	if (sample_type & PERF_SAMPLE_TIME) {
+	if (session->sample_type & PERF_SAMPLE_TIME) {
 		if (!first_time || first_time > data.time)
 			first_time = data.time;
 		if (last_time < data.time)
@@ -498,7 +492,7 @@
 	}
 
 	te = (void *)data.raw_data;
-	if (sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
+	if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) {
 		char *event_str;
 		struct power_entry *pe;
 
@@ -575,16 +569,16 @@
 	}
 }
 
-static u64 sample_time(event_t *event)
+static u64 sample_time(event_t *event, const struct perf_session *session)
 {
 	int cursor;
 
 	cursor = 0;
-	if (sample_type & PERF_SAMPLE_IP)
+	if (session->sample_type & PERF_SAMPLE_IP)
 		cursor++;
-	if (sample_type & PERF_SAMPLE_TID)
+	if (session->sample_type & PERF_SAMPLE_TID)
 		cursor++;
-	if (sample_type & PERF_SAMPLE_TIME)
+	if (session->sample_type & PERF_SAMPLE_TIME)
 		return event->sample.array[cursor];
 	return 0;
 }
@@ -594,8 +588,7 @@
  * We first queue all events, sorted backwards by insertion.
  * The order will get flipped later.
  */
-static int
-queue_sample_event(event_t *event)
+static int queue_sample_event(event_t *event, struct perf_session *session)
 {
 	struct sample_wrapper *copy, *prev;
 	int size;
@@ -609,7 +602,7 @@
 	memset(copy, 0, size);
 
 	copy->next = NULL;
-	copy->timestamp = sample_time(event);
+	copy->timestamp = sample_time(event, session);
 
 	memcpy(&copy->data, event, event->sample.header.size);
 
@@ -1021,7 +1014,7 @@
 	svg_close();
 }
 
-static void process_samples(void)
+static void process_samples(struct perf_session *session)
 {
 	struct sample_wrapper *cursor;
 	event_t *event;
@@ -1032,15 +1025,13 @@
 	while (cursor) {
 		event = (void *)&cursor->data;
 		cursor = cursor->next;
-		process_sample_event(event);
+		process_sample_event(event, session);
 	}
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
 {
-	sample_type = type;
-
-	if (!(sample_type & PERF_SAMPLE_RAW)) {
+	if (!(session->sample_type & PERF_SAMPLE_RAW)) {
 		fprintf(stderr, "No trace samples found in the file.\n"
 				"Have you used 'perf timechart record' to record it?\n");
 		return -1;
@@ -1049,7 +1040,7 @@
 	return 0;
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_comm_event	= process_comm_event,
 	.process_fork_event	= process_fork_event,
 	.process_exit_event	= process_exit_event,
@@ -1065,13 +1056,11 @@
 	if (session == NULL)
 		return -ENOMEM;
 
-	register_perf_file_handler(&file_handler);
-
-	ret = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
+	ret = perf_session__process_events(session, &event_ops);
 	if (ret)
 		goto out_delete;
 
-	process_samples();
+	process_samples(session);
 
 	end_sample_processing();
 
@@ -1148,11 +1137,11 @@
 
 int cmd_timechart(int argc, const char **argv, const char *prefix __used)
 {
-	symbol__init(0);
-
 	argc = parse_options(argc, argv, options, timechart_usage,
 			PARSE_OPT_STOP_AT_NON_OPTION);
 
+	symbol__init();
+
 	if (argc && !strncmp(argv[0], "rec", 3))
 		return __cmd_record(argc, argv);
 	else if (argc)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e0a374d..ddc584b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -20,8 +20,9 @@
 
 #include "perf.h"
 
-#include "util/symbol.h"
 #include "util/color.h"
+#include "util/session.h"
+#include "util/symbol.h"
 #include "util/thread.h"
 #include "util/util.h"
 #include <linux/rbtree.h>
@@ -79,7 +80,6 @@
 static bool			hide_kernel_symbols		=  false;
 static bool			hide_user_symbols		=  false;
 static struct winsize		winsize;
-struct symbol_conf		symbol_conf;
 
 /*
  * Source
@@ -926,7 +926,8 @@
 	return 0;
 }
 
-static void event__process_sample(const event_t *self, int counter)
+static void event__process_sample(const event_t *self,
+				 struct perf_session *session, int counter)
 {
 	u64 ip = self->ip.ip;
 	struct sym_entry *syme;
@@ -946,8 +947,8 @@
 		return;
 	}
 
-	if (event__preprocess_sample(self, &al, symbol_filter) < 0 ||
-	    al.sym == NULL)
+	if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 ||
+	    al.sym == NULL || al.filtered)
 		return;
 
 	syme = symbol__priv(al.sym);
@@ -965,14 +966,14 @@
 	}
 }
 
-static int event__process(event_t *event)
+static int event__process(event_t *event, struct perf_session *session)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		event__process_comm(event);
+		event__process_comm(event, session);
 		break;
 	case PERF_RECORD_MMAP:
-		event__process_mmap(event);
+		event__process_mmap(event, session);
 		break;
 	default:
 		break;
@@ -999,7 +1000,8 @@
 	return head;
 }
 
-static void mmap_read_counter(struct mmap_data *md)
+static void perf_session__mmap_read_counter(struct perf_session *self,
+					    struct mmap_data *md)
 {
 	unsigned int head = mmap_read_head(md);
 	unsigned int old = md->prev;
@@ -1052,9 +1054,9 @@
 		}
 
 		if (event->header.type == PERF_RECORD_SAMPLE)
-			event__process_sample(event, md->counter);
+			event__process_sample(event, self, md->counter);
 		else
-			event__process(event);
+			event__process(event, self);
 		old += size;
 	}
 
@@ -1064,13 +1066,13 @@
 static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
 static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
 
-static void mmap_read(void)
+static void perf_session__mmap_read(struct perf_session *self)
 {
 	int i, counter;
 
 	for (i = 0; i < nr_cpus; i++) {
 		for (counter = 0; counter < nr_counters; counter++)
-			mmap_read_counter(&mmap_array[i][counter]);
+			perf_session__mmap_read_counter(self, &mmap_array[i][counter]);
 	}
 }
 
@@ -1155,11 +1157,18 @@
 	pthread_t thread;
 	int i, counter;
 	int ret;
+	/*
+	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
+	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
+	 */
+	struct perf_session *session = perf_session__new(NULL, O_WRONLY, false);
+	if (session == NULL)
+		return -ENOMEM;
 
 	if (target_pid != -1)
-		event__synthesize_thread(target_pid, event__process);
+		event__synthesize_thread(target_pid, event__process, session);
 	else
-		event__synthesize_threads(event__process);
+		event__synthesize_threads(event__process, session);
 
 	for (i = 0; i < nr_cpus; i++) {
 		group_fd = -1;
@@ -1170,7 +1179,7 @@
 	/* Wait for a minimal set of events before starting the snapshot */
 	poll(event_array, nr_poll, 100);
 
-	mmap_read();
+	perf_session__mmap_read(session);
 
 	if (pthread_create(&thread, NULL, display_thread, NULL)) {
 		printf("Could not create display thread.\n");
@@ -1190,7 +1199,7 @@
 	while (1) {
 		int hits = samples;
 
-		mmap_read();
+		perf_session__mmap_read(session);
 
 		if (hits == samples)
 			ret = poll(event_array, nr_poll, 100);
@@ -1273,7 +1282,7 @@
 				 (nr_counters + 1) * sizeof(unsigned long));
 	if (symbol_conf.vmlinux_name == NULL)
 		symbol_conf.try_vmlinux_path = true;
-	if (symbol__init(&symbol_conf) < 0)
+	if (symbol__init() < 0)
 		return -1;
 
 	if (delay_secs < 1)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0756664..e2285e2 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -12,7 +12,9 @@
 static char const		*script_name;
 static char const		*generate_script_lang;
 
-static int default_start_script(const char *script __attribute((unused)))
+static int default_start_script(const char *script __unused,
+				int argc __unused,
+				const char **argv __unused)
 {
 	return 0;
 }
@@ -22,7 +24,7 @@
 	return 0;
 }
 
-static int default_generate_script(const char *outfile __attribute ((unused)))
+static int default_generate_script(const char *outfile __unused)
 {
 	return 0;
 }
@@ -57,15 +59,11 @@
 #include "util/debug.h"
 
 #include "util/trace-event.h"
-#include "util/data_map.h"
 #include "util/exec_cmd.h"
 
 static char const		*input_name = "perf.data";
 
-static struct perf_session 	*session;
-static u64			sample_type;
-
-static int process_sample_event(event_t *event)
+static int process_sample_event(event_t *event, struct perf_session *session)
 {
 	struct sample_data data;
 	struct thread *thread;
@@ -75,7 +73,7 @@
 	data.cpu = -1;
 	data.period = 1;
 
-	event__parse_sample(event, sample_type, &data);
+	event__parse_sample(event, session->sample_type, &data);
 
 	dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
 		event->header.misc,
@@ -83,14 +81,14 @@
 		(void *)(long)data.ip,
 		(long long)data.period);
 
-	thread = threads__findnew(event->ip.pid);
+	thread = perf_session__findnew(session, event->ip.pid);
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
 			 event->header.type);
 		return -1;
 	}
 
-	if (sample_type & PERF_SAMPLE_RAW) {
+	if (session->sample_type & PERF_SAMPLE_RAW) {
 		/*
 		 * FIXME: better resolve from pid from the struct trace_entry
 		 * field, although it should be the same than this perf
@@ -100,16 +98,14 @@
 					     data.raw_size,
 					     data.time, thread->comm);
 	}
-	event__stats.total += data.period;
 
+	session->events_stats.total += data.period;
 	return 0;
 }
 
-static int sample_type_check(u64 type)
+static int sample_type_check(struct perf_session *session)
 {
-	sample_type = type;
-
-	if (!(sample_type & PERF_SAMPLE_RAW)) {
+	if (!(session->sample_type & PERF_SAMPLE_RAW)) {
 		fprintf(stderr,
 			"No trace sample to read. Did you call perf record "
 			"without -R?");
@@ -119,26 +115,15 @@
 	return 0;
 }
 
-static struct perf_file_handler file_handler = {
+static struct perf_event_ops event_ops = {
 	.process_sample_event	= process_sample_event,
 	.process_comm_event	= event__process_comm,
 	.sample_type_check	= sample_type_check,
 };
 
-static int __cmd_trace(void)
+static int __cmd_trace(struct perf_session *session)
 {
-	int err;
-
-	session = perf_session__new(input_name, O_RDONLY, 0);
-	if (session == NULL)
-		return -ENOMEM;
-
-	register_idle_thread();
-	register_perf_file_handler(&file_handler);
-
-	err = perf_session__process_events(session, 0, &event__cwdlen, &event__cwd);
-	perf_session__delete(session);
-	return err;
+	return perf_session__process_events(session, &event_ops);
 }
 
 struct script_spec {
@@ -289,6 +274,244 @@
 	return 0;
 }
 
+#define for_each_lang(scripts_dir, lang_dirent, lang_next)		\
+	while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) &&	\
+	       lang_next)						\
+		if (lang_dirent.d_type == DT_DIR &&			\
+		    (strcmp(lang_dirent.d_name, ".")) &&		\
+		    (strcmp(lang_dirent.d_name, "..")))
+
+#define for_each_script(lang_dir, script_dirent, script_next)		\
+	while (!readdir_r(lang_dir, &script_dirent, &script_next) &&	\
+	       script_next)						\
+		if (script_dirent.d_type != DT_DIR)
+
+
+#define RECORD_SUFFIX			"-record"
+#define REPORT_SUFFIX			"-report"
+
+struct script_desc {
+	struct list_head	node;
+	char			*name;
+	char			*half_liner;
+	char			*args;
+};
+
+LIST_HEAD(script_descs);
+
+static struct script_desc *script_desc__new(const char *name)
+{
+	struct script_desc *s = zalloc(sizeof(*s));
+
+	if (s != NULL)
+		s->name = strdup(name);
+
+	return s;
+}
+
+static void script_desc__delete(struct script_desc *s)
+{
+	free(s->name);
+	free(s);
+}
+
+static void script_desc__add(struct script_desc *s)
+{
+	list_add_tail(&s->node, &script_descs);
+}
+
+static struct script_desc *script_desc__find(const char *name)
+{
+	struct script_desc *s;
+
+	list_for_each_entry(s, &script_descs, node)
+		if (strcasecmp(s->name, name) == 0)
+			return s;
+	return NULL;
+}
+
+static struct script_desc *script_desc__findnew(const char *name)
+{
+	struct script_desc *s = script_desc__find(name);
+
+	if (s)
+		return s;
+
+	s = script_desc__new(name);
+	if (!s)
+		goto out_delete_desc;
+
+	script_desc__add(s);
+
+	return s;
+
+out_delete_desc:
+	script_desc__delete(s);
+
+	return NULL;
+}
+
+static char *ends_with(char *str, const char *suffix)
+{
+	size_t suffix_len = strlen(suffix);
+	char *p = str;
+
+	if (strlen(str) > suffix_len) {
+		p = str + strlen(str) - suffix_len;
+		if (!strncmp(p, suffix, suffix_len))
+			return p;
+	}
+
+	return NULL;
+}
+
+static char *ltrim(char *str)
+{
+	int len = strlen(str);
+
+	while (len && isspace(*str)) {
+		len--;
+		str++;
+	}
+
+	return str;
+}
+
+static int read_script_info(struct script_desc *desc, const char *filename)
+{
+	char line[BUFSIZ], *p;
+	FILE *fp;
+
+	fp = fopen(filename, "r");
+	if (!fp)
+		return -1;
+
+	while (fgets(line, sizeof(line), fp)) {
+		p = ltrim(line);
+		if (strlen(p) == 0)
+			continue;
+		if (*p != '#')
+			continue;
+		p++;
+		if (strlen(p) && *p == '!')
+			continue;
+
+		p = ltrim(p);
+		if (strlen(p) && p[strlen(p) - 1] == '\n')
+			p[strlen(p) - 1] = '\0';
+
+		if (!strncmp(p, "description:", strlen("description:"))) {
+			p += strlen("description:");
+			desc->half_liner = strdup(ltrim(p));
+			continue;
+		}
+
+		if (!strncmp(p, "args:", strlen("args:"))) {
+			p += strlen("args:");
+			desc->args = strdup(ltrim(p));
+			continue;
+		}
+	}
+
+	fclose(fp);
+
+	return 0;
+}
+
+static int list_available_scripts(const struct option *opt __used,
+				  const char *s __used, int unset __used)
+{
+	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	char scripts_path[MAXPATHLEN];
+	DIR *scripts_dir, *lang_dir;
+	char script_path[MAXPATHLEN];
+	char lang_path[MAXPATHLEN];
+	struct script_desc *desc;
+	char first_half[BUFSIZ];
+	char *script_root;
+	char *str;
+
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+
+	scripts_dir = opendir(scripts_path);
+	if (!scripts_dir)
+		return -1;
+
+	for_each_lang(scripts_dir, lang_dirent, lang_next) {
+		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
+			 lang_dirent.d_name);
+		lang_dir = opendir(lang_path);
+		if (!lang_dir)
+			continue;
+
+		for_each_script(lang_dir, script_dirent, script_next) {
+			script_root = strdup(script_dirent.d_name);
+			str = ends_with(script_root, REPORT_SUFFIX);
+			if (str) {
+				*str = '\0';
+				desc = script_desc__findnew(script_root);
+				snprintf(script_path, MAXPATHLEN, "%s/%s",
+					 lang_path, script_dirent.d_name);
+				read_script_info(desc, script_path);
+			}
+			free(script_root);
+		}
+	}
+
+	fprintf(stdout, "List of available trace scripts:\n");
+	list_for_each_entry(desc, &script_descs, node) {
+		sprintf(first_half, "%s %s", desc->name,
+			desc->args ? desc->args : "");
+		fprintf(stdout, "  %-36s %s\n", first_half,
+			desc->half_liner ? desc->half_liner : "");
+	}
+
+	exit(0);
+}
+
+static char *get_script_path(const char *script_root, const char *suffix)
+{
+	struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+	char scripts_path[MAXPATHLEN];
+	char script_path[MAXPATHLEN];
+	DIR *scripts_dir, *lang_dir;
+	char lang_path[MAXPATHLEN];
+	char *str, *__script_root;
+	char *path = NULL;
+
+	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+
+	scripts_dir = opendir(scripts_path);
+	if (!scripts_dir)
+		return NULL;
+
+	for_each_lang(scripts_dir, lang_dirent, lang_next) {
+		snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
+			 lang_dirent.d_name);
+		lang_dir = opendir(lang_path);
+		if (!lang_dir)
+			continue;
+
+		for_each_script(lang_dir, script_dirent, script_next) {
+			__script_root = strdup(script_dirent.d_name);
+			str = ends_with(__script_root, suffix);
+			if (str) {
+				*str = '\0';
+				if (strcmp(__script_root, script_root))
+					continue;
+				snprintf(script_path, MAXPATHLEN, "%s/%s",
+					 lang_path, script_dirent.d_name);
+				path = strdup(script_path);
+				free(__script_root);
+				break;
+			}
+			free(__script_root);
+		}
+	}
+
+	return path;
+}
+
 static const char * const annotate_usage[] = {
 	"perf trace [<options>] <command>",
 	NULL
@@ -299,8 +522,10 @@
 		    "dump raw trace in ASCII"),
 	OPT_BOOLEAN('v', "verbose", &verbose,
 		    "be more verbose (show symbol address, etc)"),
-	OPT_BOOLEAN('l', "latency", &latency_format,
+	OPT_BOOLEAN('L', "Latency", &latency_format,
 		    "show latency attributes (irqs/preemption disabled, etc)"),
+	OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
+			   list_available_scripts),
 	OPT_CALLBACK('s', "script", NULL, "name",
 		     "script file name (lang:script name, script name, or *)",
 		     parse_scriptname),
@@ -312,24 +537,61 @@
 
 int cmd_trace(int argc, const char **argv, const char *prefix __used)
 {
-	int err;
+	struct perf_session *session;
+	const char *suffix = NULL;
+	const char **__argv;
+	char *script_path;
+	int i, err;
 
-	symbol__init(0);
+	if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) {
+		if (argc < 3) {
+			fprintf(stderr,
+				"Please specify a record script\n");
+			return -1;
+		}
+		suffix = RECORD_SUFFIX;
+	}
+
+	if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) {
+		if (argc < 3) {
+			fprintf(stderr,
+				"Please specify a report script\n");
+			return -1;
+		}
+		suffix = REPORT_SUFFIX;
+	}
+
+	if (suffix) {
+		script_path = get_script_path(argv[2], suffix);
+		if (!script_path) {
+			fprintf(stderr, "script not found\n");
+			return -1;
+		}
+
+		__argv = malloc((argc + 1) * sizeof(const char *));
+		__argv[0] = "/bin/sh";
+		__argv[1] = script_path;
+		for (i = 3; i < argc; i++)
+			__argv[i - 1] = argv[i];
+		__argv[argc - 1] = NULL;
+
+		execvp("/bin/sh", (char **)__argv);
+		exit(-1);
+	}
 
 	setup_scripting();
 
-	argc = parse_options(argc, argv, options, annotate_usage, 0);
-	if (argc) {
-		/*
-		 * Special case: if there's an argument left then assume tha
-		 * it's a symbol filter:
-		 */
-		if (argc > 1)
-			usage_with_options(annotate_usage, options);
-	}
+	argc = parse_options(argc, argv, options, annotate_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (symbol__init() < 0)
+		return -1;
 	setup_pager();
 
+	session = perf_session__new(input_name, O_RDONLY, 0);
+	if (session == NULL)
+		return -ENOMEM;
+
 	if (generate_script_lang) {
 		struct stat perf_stat;
 
@@ -362,13 +624,14 @@
 	}
 
 	if (script_name) {
-		err = scripting_ops->start_script(script_name);
+		err = scripting_ops->start_script(script_name, argc, argv);
 		if (err)
 			goto out;
 	}
 
-	err = __cmd_trace();
+	err = __cmd_trace(session);
 
+	perf_session__delete(session);
 	cleanup_scripting();
 out:
 	return err;
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index a3d8bf6..18035b1 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -17,6 +17,7 @@
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_bench(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
+extern int cmd_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_sched(int argc, const char **argv, const char *prefix);
 extern int cmd_list(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 02b09ea..71dc7c3 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -5,6 +5,7 @@
 perf-annotate			mainporcelain common
 perf-bench			mainporcelain common
 perf-buildid-list		mainporcelain common
+perf-diff			mainporcelain common
 perf-list			mainporcelain common
 perf-sched			mainporcelain common
 perf-record			mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index cf64049..873e55f 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -286,6 +286,7 @@
 	const char *cmd = argv[0];
 	static struct cmd_struct commands[] = {
 		{ "buildid-list", cmd_buildid_list, 0 },
+		{ "diff",	cmd_diff,	0 },
 		{ "help",	cmd_help,	0 },
 		{ "list",	cmd_list,	0 },
 		{ "record",	cmd_record,	0 },
diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-report b/tools/perf/scripts/perl/bin/check-perf-trace-report
index 89948b0..7fc4a03 100644
--- a/tools/perf/scripts/perl/bin/check-perf-trace-report
+++ b/tools/perf/scripts/perl/bin/check-perf-trace-report
@@ -1,4 +1,5 @@
 #!/bin/bash
+# description: useless but exhaustive test script
 perf trace -s ~/libexec/perf-core/scripts/perl/check-perf-trace.pl
 
 
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index f5dcf9c..eddb9cc 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -1,5 +1,7 @@
 #!/bin/bash
-perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl
+# description: r/w activity for a program, by file
+# args: <comm>
+perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $1
 
 
 
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index cea16f7..7f44c25 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,4 +1,5 @@
 #!/bin/bash
+# description: system-wide r/w activity
 perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl
 
 
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index 85769dc..fce3adc 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,4 +1,5 @@
 #!/bin/bash
+# description: system-wide min/max/avg wakeup latency
 perf trace -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl
 
 
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index aa68435..71cfbd1 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,4 +1,5 @@
 #!/bin/bash
+# description: workqueue stats (ins/exe/create/destroy)
 perf trace -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl
 
 
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
index 61f9156..2a39097 100644
--- a/tools/perf/scripts/perl/rw-by-file.pl
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -18,8 +18,9 @@
 use Perf::Trace::Core;
 use Perf::Trace::Util;
 
-# change this to the comm of the program you're interested in
-my $for_comm = "perf";
+my $usage = "perf trace -s rw-by-file.pl <comm>\n";
+
+my $for_comm = shift or die $usage;
 
 my %reads;
 my %writes;
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index 6d46dda..b557b83 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -1,20 +1,17 @@
-#include "data_map.h"
 #include "symbol.h"
 #include "util.h"
 #include "debug.h"
+#include "thread.h"
+#include "session.h"
 
-
-static struct perf_file_handler *curr_handler;
-static unsigned long	mmap_window = 32;
-static char		__cwd[PATH_MAX];
-
-static int process_event_stub(event_t *event __used)
+static int process_event_stub(event_t *event __used,
+			      struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
-void register_perf_file_handler(struct perf_file_handler *handler)
+static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 {
 	if (!handler->process_sample_event)
 		handler->process_sample_event = process_event_stub;
@@ -34,8 +31,6 @@
 		handler->process_throttle_event = process_event_stub;
 	if (!handler->process_unthrottle_event)
 		handler->process_unthrottle_event = process_event_stub;
-
-	curr_handler = handler;
 }
 
 static const char *event__name[] = {
@@ -61,8 +56,9 @@
 			event__name[i], event__total[i]);
 }
 
-static int
-process_event(event_t *event, unsigned long offset, unsigned long head)
+static int process_event(event_t *event, struct perf_session *session,
+			 struct perf_event_ops *ops,
+			 unsigned long offset, unsigned long head)
 {
 	trace_event(event);
 
@@ -77,25 +73,25 @@
 
 	switch (event->header.type) {
 	case PERF_RECORD_SAMPLE:
-		return curr_handler->process_sample_event(event);
+		return ops->process_sample_event(event, session);
 	case PERF_RECORD_MMAP:
-		return curr_handler->process_mmap_event(event);
+		return ops->process_mmap_event(event, session);
 	case PERF_RECORD_COMM:
-		return curr_handler->process_comm_event(event);
+		return ops->process_comm_event(event, session);
 	case PERF_RECORD_FORK:
-		return curr_handler->process_fork_event(event);
+		return ops->process_fork_event(event, session);
 	case PERF_RECORD_EXIT:
-		return curr_handler->process_exit_event(event);
+		return ops->process_exit_event(event, session);
 	case PERF_RECORD_LOST:
-		return curr_handler->process_lost_event(event);
+		return ops->process_lost_event(event, session);
 	case PERF_RECORD_READ:
-		return curr_handler->process_read_event(event);
+		return ops->process_read_event(event, session);
 	case PERF_RECORD_THROTTLE:
-		return curr_handler->process_throttle_event(event);
+		return ops->process_throttle_event(event, session);
 	case PERF_RECORD_UNTHROTTLE:
-		return curr_handler->process_unthrottle_event(event);
+		return ops->process_unthrottle_event(event, session);
 	default:
-		curr_handler->total_unknown++;
+		ops->total_unknown++;
 		return -1;
 	}
 }
@@ -129,44 +125,58 @@
 	return err;
 }
 
+static struct thread *perf_session__register_idle_thread(struct perf_session *self)
+{
+	struct thread *thread = perf_session__findnew(self, 0);
+
+	if (!thread || thread__set_comm(thread, "swapper")) {
+		pr_err("problem inserting idle task.\n");
+		thread = NULL;
+	}
+
+	return thread;
+}
+
 int perf_session__process_events(struct perf_session *self,
-				 int full_paths, int *cwdlen, char **cwd)
+				 struct perf_event_ops *ops)
 {
 	int err;
 	unsigned long head, shift;
 	unsigned long offset = 0;
 	size_t	page_size;
-	u64 sample_type;
 	event_t *event;
 	uint32_t size;
 	char *buf;
 
-	if (curr_handler == NULL) {
-		pr_debug("Forgot to register perf file handler\n");
-		return -EINVAL;
-	}
+	if (perf_session__register_idle_thread(self) == NULL)
+		return -ENOMEM;
+
+	perf_event_ops__fill_defaults(ops);
 
 	page_size = getpagesize();
 
 	head = self->header.data_offset;
-	sample_type = perf_header__sample_type(&self->header);
+	self->sample_type = perf_header__sample_type(&self->header);
 
 	err = -EINVAL;
-	if (curr_handler->sample_type_check &&
-	    curr_handler->sample_type_check(sample_type) < 0)
+	if (ops->sample_type_check && ops->sample_type_check(self) < 0)
 		goto out_err;
 
-	if (!full_paths) {
-		if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
-			pr_err("failed to get the current directory\n");
+	if (!ops->full_paths) {
+		char bf[PATH_MAX];
+
+		if (getcwd(bf, sizeof(bf)) == NULL) {
 			err = -errno;
+out_getcwd_err:
+			pr_err("failed to get the current directory\n");
 			goto out_err;
 		}
-		*cwd = __cwd;
-		*cwdlen = strlen(*cwd);
-	} else {
-		*cwd = NULL;
-		*cwdlen = 0;
+		self->cwd = strdup(bf);
+		if (self->cwd == NULL) {
+			err = -ENOMEM;
+			goto out_getcwd_err;
+		}
+		self->cwdlen = strlen(self->cwd);
 	}
 
 	shift = page_size * (head / page_size);
@@ -174,7 +184,7 @@
 	head -= shift;
 
 remap:
-	buf = mmap(NULL, page_size * mmap_window, PROT_READ,
+	buf = mmap(NULL, page_size * self->mmap_window, PROT_READ,
 		   MAP_SHARED, self->fd, offset);
 	if (buf == MAP_FAILED) {
 		pr_err("failed to mmap file\n");
@@ -189,12 +199,12 @@
 	if (!size)
 		size = 8;
 
-	if (head + event->header.size >= page_size * mmap_window) {
+	if (head + event->header.size >= page_size * self->mmap_window) {
 		int munmap_ret;
 
 		shift = page_size * (head / page_size);
 
-		munmap_ret = munmap(buf, page_size * mmap_window);
+		munmap_ret = munmap(buf, page_size * self->mmap_window);
 		assert(munmap_ret == 0);
 
 		offset += shift;
@@ -209,7 +219,7 @@
 			(void *)(long)event->header.size,
 			event->header.type);
 
-	if (!size || process_event(event, offset, head) < 0) {
+	if (!size || process_event(event, self, ops, offset, head) < 0) {
 
 		dump_printf("%p [%p]: skipping unknown header type: %d\n",
 			(void *)(offset + head),
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
deleted file mode 100644
index 98c5b82..0000000
--- a/tools/perf/util/data_map.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __PERF_DATAMAP_H
-#define __PERF_DATAMAP_H
-
-#include "event.h"
-#include "header.h"
-#include "session.h"
-
-typedef int (*event_type_handler_t)(event_t *);
-
-struct perf_file_handler {
-	event_type_handler_t	process_sample_event;
-	event_type_handler_t	process_mmap_event;
-	event_type_handler_t	process_comm_event;
-	event_type_handler_t	process_fork_event;
-	event_type_handler_t	process_exit_event;
-	event_type_handler_t	process_lost_event;
-	event_type_handler_t	process_read_event;
-	event_type_handler_t	process_throttle_event;
-	event_type_handler_t	process_unthrottle_event;
-	int			(*sample_type_check)(u64 sample_type);
-	unsigned long		total_unknown;
-};
-
-void register_perf_file_handler(struct perf_file_handler *handler);
-int perf_session__process_events(struct perf_session *self,
-				 int full_paths, int *cwdlen, char **cwd);
-int perf_header__read_build_ids(int input, u64 offset, u64 file_size);
-
-#endif
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index ba0de90..bb0fd6d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,11 +1,16 @@
 #include <linux/types.h>
 #include "event.h"
 #include "debug.h"
+#include "session.h"
+#include "sort.h"
 #include "string.h"
+#include "strlist.h"
 #include "thread.h"
 
 static pid_t event__synthesize_comm(pid_t pid, int full,
-				    int (*process)(event_t *event))
+				    int (*process)(event_t *event,
+						   struct perf_session *session),
+				    struct perf_session *session)
 {
 	event_t ev;
 	char filename[PATH_MAX];
@@ -54,7 +59,7 @@
 	if (!full) {
 		ev.comm.tid = pid;
 
-		process(&ev);
+		process(&ev, session);
 		goto out_fclose;
 	}
 
@@ -72,7 +77,7 @@
 
 		ev.comm.tid = pid;
 
-		process(&ev);
+		process(&ev, session);
 	}
 	closedir(tasks);
 
@@ -86,7 +91,9 @@
 }
 
 static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
-					 int (*process)(event_t *event))
+					 int (*process)(event_t *event,
+							struct perf_session *session),
+					 struct perf_session *session)
 {
 	char filename[PATH_MAX];
 	FILE *fp;
@@ -141,7 +148,7 @@
 			ev.mmap.pid = tgid;
 			ev.mmap.tid = pid;
 
-			process(&ev);
+			process(&ev, session);
 		}
 	}
 
@@ -149,15 +156,20 @@
 	return 0;
 }
 
-int event__synthesize_thread(pid_t pid, int (*process)(event_t *event))
+int event__synthesize_thread(pid_t pid,
+			     int (*process)(event_t *event,
+					    struct perf_session *session),
+			     struct perf_session *session)
 {
-	pid_t tgid = event__synthesize_comm(pid, 1, process);
+	pid_t tgid = event__synthesize_comm(pid, 1, process, session);
 	if (tgid == -1)
 		return -1;
-	return event__synthesize_mmap_events(pid, tgid, process);
+	return event__synthesize_mmap_events(pid, tgid, process, session);
 }
 
-void event__synthesize_threads(int (*process)(event_t *event))
+void event__synthesize_threads(int (*process)(event_t *event,
+					      struct perf_session *session),
+			       struct perf_session *session)
 {
 	DIR *proc;
 	struct dirent dirent, *next;
@@ -171,24 +183,47 @@
 		if (*end) /* only interested in proper numerical dirents */
 			continue;
 
-		event__synthesize_thread(pid, process);
+		event__synthesize_thread(pid, process, session);
 	}
 
 	closedir(proc);
 }
 
-char *event__cwd;
-int  event__cwdlen;
-
-struct events_stats event__stats;
-
-int event__process_comm(event_t *self)
+static void thread__comm_adjust(struct thread *self)
 {
-	struct thread *thread = threads__findnew(self->comm.pid);
+	char *comm = self->comm;
+
+	if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
+	    (!symbol_conf.comm_list ||
+	     strlist__has_entry(symbol_conf.comm_list, comm))) {
+		unsigned int slen = strlen(comm);
+
+		if (slen > comms__col_width) {
+			comms__col_width = slen;
+			threads__col_width = slen + 6;
+		}
+	}
+}
+
+static int thread__set_comm_adjust(struct thread *self, const char *comm)
+{
+	int ret = thread__set_comm(self, comm);
+
+	if (ret)
+		return ret;
+
+	thread__comm_adjust(self);
+
+	return 0;
+}
+
+int event__process_comm(event_t *self, struct perf_session *session)
+{
+	struct thread *thread = perf_session__findnew(session, self->comm.pid);
 
 	dump_printf(": %s:%d\n", self->comm.comm, self->comm.pid);
 
-	if (thread == NULL || thread__set_comm(thread, self->comm.comm)) {
+	if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm)) {
 		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
 		return -1;
 	}
@@ -196,18 +231,18 @@
 	return 0;
 }
 
-int event__process_lost(event_t *self)
+int event__process_lost(event_t *self, struct perf_session *session)
 {
 	dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost);
-	event__stats.lost += self->lost.lost;
+	session->events_stats.lost += self->lost.lost;
 	return 0;
 }
 
-int event__process_mmap(event_t *self)
+int event__process_mmap(event_t *self, struct perf_session *session)
 {
-	struct thread *thread = threads__findnew(self->mmap.pid);
+	struct thread *thread = perf_session__findnew(session, self->mmap.pid);
 	struct map *map = map__new(&self->mmap, MAP__FUNCTION,
-				   event__cwd, event__cwdlen);
+				   session->cwd, session->cwdlen);
 
 	dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n",
 		    self->mmap.pid, self->mmap.tid,
@@ -224,10 +259,10 @@
 	return 0;
 }
 
-int event__process_task(event_t *self)
+int event__process_task(event_t *self, struct perf_session *session)
 {
-	struct thread *thread = threads__findnew(self->fork.pid);
-	struct thread *parent = threads__findnew(self->fork.ppid);
+	struct thread *thread = perf_session__findnew(session, self->fork.pid);
+	struct thread *parent = perf_session__findnew(session, self->fork.ppid);
 
 	dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
 		    self->fork.ppid, self->fork.ptid);
@@ -249,7 +284,8 @@
 	return 0;
 }
 
-void thread__find_addr_location(struct thread *self, u8 cpumode,
+void thread__find_addr_location(struct thread *self,
+				struct perf_session *session, u8 cpumode,
 				enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter)
@@ -261,7 +297,7 @@
 
 	if (cpumode & PERF_RECORD_MISC_KERNEL) {
 		al->level = 'k';
-		mg = kmaps;
+		mg = &session->kmaps;
 	} else if (cpumode & PERF_RECORD_MISC_USER)
 		al->level = '.';
 	else {
@@ -282,33 +318,73 @@
 		 * "[vdso]" dso, but for now lets use the old trick of looking
 		 * in the whole kernel symbol list.
 		 */
-		if ((long long)al->addr < 0 && mg != kmaps) {
-			mg = kmaps;
+		if ((long long)al->addr < 0 && mg != &session->kmaps) {
+			mg = &session->kmaps;
 			goto try_again;
 		}
 		al->sym = NULL;
 	} else {
 		al->addr = al->map->map_ip(al->map, al->addr);
-		al->sym = map__find_symbol(al->map, al->addr, filter);
+		al->sym = map__find_symbol(al->map, session, al->addr, filter);
 	}
 }
 
-int event__preprocess_sample(const event_t *self, struct addr_location *al,
-			     symbol_filter_t filter)
+static void dso__calc_col_width(struct dso *self)
+{
+	if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
+	    (!symbol_conf.dso_list ||
+	     strlist__has_entry(symbol_conf.dso_list, self->name))) {
+		unsigned int slen = strlen(self->name);
+		if (slen > dsos__col_width)
+			dsos__col_width = slen;
+	}
+
+	self->slen_calculated = 1;
+}
+
+int event__preprocess_sample(const event_t *self, struct perf_session *session,
+			     struct addr_location *al, symbol_filter_t filter)
 {
 	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	struct thread *thread = threads__findnew(self->ip.pid);
+	struct thread *thread = perf_session__findnew(session, self->ip.pid);
 
 	if (thread == NULL)
 		return -1;
 
+	if (symbol_conf.comm_list &&
+	    !strlist__has_entry(symbol_conf.comm_list, thread->comm))
+		goto out_filtered;
+
 	dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-	thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
+	thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION,
 				   self->ip.ip, al, filter);
 	dump_printf(" ...... dso: %s\n",
 		    al->map ? al->map->dso->long_name :
 			al->level == 'H' ? "[hypervisor]" : "<not found>");
+	/*
+	 * We have to do this here as we may have a dso with no symbol hit that
+	 * has a name longer than the ones with symbols sampled.
+	 */
+	if (al->map && !sort_dso.elide && !al->map->dso->slen_calculated)
+		dso__calc_col_width(al->map->dso);
+
+	if (symbol_conf.dso_list &&
+	    (!al->map || !al->map->dso ||
+	     !(strlist__has_entry(symbol_conf.dso_list, al->map->dso->short_name) ||
+	       (al->map->dso->short_name != al->map->dso->long_name &&
+		strlist__has_entry(symbol_conf.dso_list, al->map->dso->long_name)))))
+		goto out_filtered;
+
+	if (symbol_conf.sym_list && al->sym &&
+	    !strlist__has_entry(symbol_conf.sym_list, al->sym->name))
+		goto out_filtered;
+
+	al->filtered = false;
+	return 0;
+
+out_filtered:
+	al->filtered = true;
 	return 0;
 }
 
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 51a96c2..8027309 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -149,29 +149,35 @@
 struct map *map__clone(struct map *self);
 int map__overlap(struct map *l, struct map *r);
 size_t map__fprintf(struct map *self, FILE *fp);
-struct symbol *map__find_symbol(struct map *self, u64 addr,
-				symbol_filter_t filter);
+
+struct perf_session;
+
+int map__load(struct map *self, struct perf_session *session,
+	      symbol_filter_t filter);
+struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
+				u64 addr, symbol_filter_t filter);
 struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+					struct perf_session *session,
 					symbol_filter_t filter);
 void map__fixup_start(struct map *self);
 void map__fixup_end(struct map *self);
 
-int event__synthesize_thread(pid_t pid, int (*process)(event_t *event));
-void event__synthesize_threads(int (*process)(event_t *event));
+int event__synthesize_thread(pid_t pid,
+			     int (*process)(event_t *event,
+					    struct perf_session *session),
+			     struct perf_session *session);
+void event__synthesize_threads(int (*process)(event_t *event,
+					      struct perf_session *session),
+			       struct perf_session *session);
 
-extern char *event__cwd;
-extern int  event__cwdlen;
-extern struct events_stats event__stats;
-extern unsigned long event__total[PERF_RECORD_MAX];
-
-int event__process_comm(event_t *self);
-int event__process_lost(event_t *self);
-int event__process_mmap(event_t *self);
-int event__process_task(event_t *self);
+int event__process_comm(event_t *self, struct perf_session *session);
+int event__process_lost(event_t *self, struct perf_session *session);
+int event__process_mmap(event_t *self, struct perf_session *session);
+int event__process_task(event_t *self, struct perf_session *session);
 
 struct addr_location;
-int event__preprocess_sample(const event_t *self, struct addr_location *al,
-			     symbol_filter_t filter);
+int event__preprocess_sample(const event_t *self, struct perf_session *session,
+			     struct addr_location *al, symbol_filter_t filter);
 int event__parse_sample(event_t *event, u64 type, struct sample_data *data);
 
 #endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index f2e8d87..8a0bca5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,8 +8,8 @@
 #include "header.h"
 #include "../perf.h"
 #include "trace-event.h"
+#include "session.h"
 #include "symbol.h"
-#include "data_map.h"
 #include "debug.h"
 
 /*
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 0ebf6ee..e8daf5c 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,9 +1,7 @@
 #include "hist.h"
-
-struct rb_root hist;
-struct rb_root collapse_hists;
-struct rb_root output_hists;
-int callchain;
+#include "session.h"
+#include "sort.h"
+#include <math.h>
 
 struct callchain_param	callchain_param = {
 	.mode	= CHAIN_GRAPH_REL,
@@ -14,11 +12,12 @@
  * histogram, sorted on item, collects counts
  */
 
-struct hist_entry *__hist_entry__add(struct addr_location *al,
-				     struct symbol *sym_parent,
-				     u64 count, bool *hit)
+struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+						  struct addr_location *al,
+						  struct symbol *sym_parent,
+						  u64 count, bool *hit)
 {
-	struct rb_node **p = &hist.rb_node;
+	struct rb_node **p = &self->hists.rb_node;
 	struct rb_node *parent = NULL;
 	struct hist_entry *he;
 	struct hist_entry entry = {
@@ -54,7 +53,7 @@
 		return NULL;
 	*he = entry;
 	rb_link_node(&he->rb_node, parent, p);
-	rb_insert_color(&he->rb_node, &hist);
+	rb_insert_color(&he->rb_node, &self->hists);
 	*hit = false;
 	return he;
 }
@@ -102,9 +101,9 @@
  * collapse the histogram
  */
 
-void collapse__insert_entry(struct hist_entry *he)
+static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
 {
-	struct rb_node **p = &collapse_hists.rb_node;
+	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
 	struct hist_entry *iter;
 	int64_t cmp;
@@ -128,38 +127,45 @@
 	}
 
 	rb_link_node(&he->rb_node, parent, p);
-	rb_insert_color(&he->rb_node, &collapse_hists);
+	rb_insert_color(&he->rb_node, root);
 }
 
-void collapse__resort(void)
+void perf_session__collapse_resort(struct perf_session *self)
 {
+	struct rb_root tmp;
 	struct rb_node *next;
 	struct hist_entry *n;
 
 	if (!sort__need_collapse)
 		return;
 
-	next = rb_first(&hist);
+	tmp = RB_ROOT;
+	next = rb_first(&self->hists);
+
 	while (next) {
 		n = rb_entry(next, struct hist_entry, rb_node);
 		next = rb_next(&n->rb_node);
 
-		rb_erase(&n->rb_node, &hist);
-		collapse__insert_entry(n);
+		rb_erase(&n->rb_node, &self->hists);
+		collapse__insert_entry(&tmp, n);
 	}
+
+	self->hists = tmp;
 }
 
 /*
  * reverse the map, sort on count.
  */
 
-void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
+static void perf_session__insert_output_hist_entry(struct rb_root *root,
+						   struct hist_entry *he,
+						   u64 min_callchain_hits)
 {
-	struct rb_node **p = &output_hists.rb_node;
+	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
 	struct hist_entry *iter;
 
-	if (callchain)
+	if (symbol_conf.use_callchain)
 		callchain_param.sort(&he->sorted_chain, &he->callchain,
 				      min_callchain_hits, &callchain_param);
 
@@ -174,29 +180,483 @@
 	}
 
 	rb_link_node(&he->rb_node, parent, p);
-	rb_insert_color(&he->rb_node, &output_hists);
+	rb_insert_color(&he->rb_node, root);
 }
 
-void output__resort(u64 total_samples)
+void perf_session__output_resort(struct perf_session *self, u64 total_samples)
 {
+	struct rb_root tmp;
 	struct rb_node *next;
 	struct hist_entry *n;
-	struct rb_root *tree = &hist;
 	u64 min_callchain_hits;
 
 	min_callchain_hits =
 		total_samples * (callchain_param.min_percent / 100);
 
-	if (sort__need_collapse)
-		tree = &collapse_hists;
-
-	next = rb_first(tree);
+	tmp = RB_ROOT;
+	next = rb_first(&self->hists);
 
 	while (next) {
 		n = rb_entry(next, struct hist_entry, rb_node);
 		next = rb_next(&n->rb_node);
 
-		rb_erase(&n->rb_node, tree);
-		output__insert_entry(n, min_callchain_hits);
+		rb_erase(&n->rb_node, &self->hists);
+		perf_session__insert_output_hist_entry(&tmp, n,
+						       min_callchain_hits);
 	}
+
+	self->hists = tmp;
+}
+
+static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
+{
+	int i;
+	int ret = fprintf(fp, "            ");
+
+	for (i = 0; i < left_margin; i++)
+		ret += fprintf(fp, " ");
+
+	return ret;
+}
+
+static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
+					  int left_margin)
+{
+	int i;
+	size_t ret = callchain__fprintf_left_margin(fp, left_margin);
+
+	for (i = 0; i < depth; i++)
+		if (depth_mask & (1 << i))
+			ret += fprintf(fp, "|          ");
+		else
+			ret += fprintf(fp, "           ");
+
+	ret += fprintf(fp, "\n");
+
+	return ret;
+}
+
+static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
+				     int depth, int depth_mask, int count,
+				     u64 total_samples, int hits,
+				     int left_margin)
+{
+	int i;
+	size_t ret = 0;
+
+	ret += callchain__fprintf_left_margin(fp, left_margin);
+	for (i = 0; i < depth; i++) {
+		if (depth_mask & (1 << i))
+			ret += fprintf(fp, "|");
+		else
+			ret += fprintf(fp, " ");
+		if (!count && i == depth - 1) {
+			double percent;
+
+			percent = hits * 100.0 / total_samples;
+			ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
+		} else
+			ret += fprintf(fp, "%s", "          ");
+	}
+	if (chain->sym)
+		ret += fprintf(fp, "%s\n", chain->sym->name);
+	else
+		ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
+
+	return ret;
+}
+
+static struct symbol *rem_sq_bracket;
+static struct callchain_list rem_hits;
+
+static void init_rem_hits(void)
+{
+	rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
+	if (!rem_sq_bracket) {
+		fprintf(stderr, "Not enough memory to display remaining hits\n");
+		return;
+	}
+
+	strcpy(rem_sq_bracket->name, "[...]");
+	rem_hits.sym = rem_sq_bracket;
+}
+
+static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
+					 u64 total_samples, int depth,
+					 int depth_mask, int left_margin)
+{
+	struct rb_node *node, *next;
+	struct callchain_node *child;
+	struct callchain_list *chain;
+	int new_depth_mask = depth_mask;
+	u64 new_total;
+	u64 remaining;
+	size_t ret = 0;
+	int i;
+
+	if (callchain_param.mode == CHAIN_GRAPH_REL)
+		new_total = self->children_hit;
+	else
+		new_total = total_samples;
+
+	remaining = new_total;
+
+	node = rb_first(&self->rb_root);
+	while (node) {
+		u64 cumul;
+
+		child = rb_entry(node, struct callchain_node, rb_node);
+		cumul = cumul_hits(child);
+		remaining -= cumul;
+
+		/*
+		 * The depth mask manages the output of pipes that show
+		 * the depth. We don't want to keep the pipes of the current
+		 * level for the last child of this depth.
+		 * Except if we have remaining filtered hits. They will
+		 * supersede the last child
+		 */
+		next = rb_next(node);
+		if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
+			new_depth_mask &= ~(1 << (depth - 1));
+
+		/*
+		 * But we keep the older depth mask for the line seperator
+		 * to keep the level link until we reach the last child
+		 */
+		ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
+						   left_margin);
+		i = 0;
+		list_for_each_entry(chain, &child->val, list) {
+			if (chain->ip >= PERF_CONTEXT_MAX)
+				continue;
+			ret += ipchain__fprintf_graph(fp, chain, depth,
+						      new_depth_mask, i++,
+						      new_total,
+						      cumul,
+						      left_margin);
+		}
+		ret += __callchain__fprintf_graph(fp, child, new_total,
+						  depth + 1,
+						  new_depth_mask | (1 << depth),
+						  left_margin);
+		node = next;
+	}
+
+	if (callchain_param.mode == CHAIN_GRAPH_REL &&
+		remaining && remaining != new_total) {
+
+		if (!rem_sq_bracket)
+			return ret;
+
+		new_depth_mask &= ~(1 << (depth - 1));
+
+		ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
+					      new_depth_mask, 0, new_total,
+					      remaining, left_margin);
+	}
+
+	return ret;
+}
+
+static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
+				       u64 total_samples, int left_margin)
+{
+	struct callchain_list *chain;
+	bool printed = false;
+	int i = 0;
+	int ret = 0;
+
+	list_for_each_entry(chain, &self->val, list) {
+		if (chain->ip >= PERF_CONTEXT_MAX)
+			continue;
+
+		if (!i++ && sort__first_dimension == SORT_SYM)
+			continue;
+
+		if (!printed) {
+			ret += callchain__fprintf_left_margin(fp, left_margin);
+			ret += fprintf(fp, "|\n");
+			ret += callchain__fprintf_left_margin(fp, left_margin);
+			ret += fprintf(fp, "---");
+
+			left_margin += 3;
+			printed = true;
+		} else
+			ret += callchain__fprintf_left_margin(fp, left_margin);
+
+		if (chain->sym)
+			ret += fprintf(fp, " %s\n", chain->sym->name);
+		else
+			ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
+	}
+
+	ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
+
+	return ret;
+}
+
+static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
+				      u64 total_samples)
+{
+	struct callchain_list *chain;
+	size_t ret = 0;
+
+	if (!self)
+		return 0;
+
+	ret += callchain__fprintf_flat(fp, self->parent, total_samples);
+
+
+	list_for_each_entry(chain, &self->val, list) {
+		if (chain->ip >= PERF_CONTEXT_MAX)
+			continue;
+		if (chain->sym)
+			ret += fprintf(fp, "                %s\n", chain->sym->name);
+		else
+			ret += fprintf(fp, "                %p\n",
+					(void *)(long)chain->ip);
+	}
+
+	return ret;
+}
+
+static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
+					    u64 total_samples, int left_margin)
+{
+	struct rb_node *rb_node;
+	struct callchain_node *chain;
+	size_t ret = 0;
+
+	rb_node = rb_first(&self->sorted_chain);
+	while (rb_node) {
+		double percent;
+
+		chain = rb_entry(rb_node, struct callchain_node, rb_node);
+		percent = chain->hit * 100.0 / total_samples;
+		switch (callchain_param.mode) {
+		case CHAIN_FLAT:
+			ret += percent_color_fprintf(fp, "           %6.2f%%\n",
+						     percent);
+			ret += callchain__fprintf_flat(fp, chain, total_samples);
+			break;
+		case CHAIN_GRAPH_ABS: /* Falldown */
+		case CHAIN_GRAPH_REL:
+			ret += callchain__fprintf_graph(fp, chain, total_samples,
+							left_margin);
+		case CHAIN_NONE:
+		default:
+			break;
+		}
+		ret += fprintf(fp, "\n");
+		rb_node = rb_next(rb_node);
+	}
+
+	return ret;
+}
+
+static size_t hist_entry__fprintf(struct hist_entry *self,
+				  struct perf_session *session,
+				  struct perf_session *pair_session,
+				  bool show_displacement,
+				  long displacement, FILE *fp)
+{
+	struct sort_entry *se;
+	u64 count, total;
+	const char *sep = symbol_conf.field_sep;
+	size_t ret;
+
+	if (symbol_conf.exclude_other && !self->parent)
+		return 0;
+
+	if (pair_session) {
+		count = self->pair ? self->pair->count : 0;
+		total = pair_session->events_stats.total;
+	} else {
+		count = self->count;
+		total = session->events_stats.total;
+	}
+
+	if (total)
+		ret = percent_color_fprintf(fp, sep ? "%.2f" : "   %6.2f%%",
+					    (count * 100.0) / total);
+	else
+		ret = fprintf(fp, sep ? "%lld" : "%12lld ", count);
+
+	if (symbol_conf.show_nr_samples) {
+		if (sep)
+			fprintf(fp, "%c%lld", *sep, count);
+		else
+			fprintf(fp, "%11lld", count);
+	}
+
+	if (pair_session) {
+		char bf[32];
+		double old_percent = 0, new_percent = 0, diff;
+
+		if (total > 0)
+			old_percent = (count * 100.0) / total;
+		if (session->events_stats.total > 0)
+			new_percent = (self->count * 100.0) / session->events_stats.total;
+
+		diff = new_percent - old_percent;
+
+		if (fabs(diff) >= 0.01)
+			snprintf(bf, sizeof(bf), "%+4.2F%%", diff);
+		else
+			snprintf(bf, sizeof(bf), " ");
+
+		if (sep)
+			ret += fprintf(fp, "%c%s", *sep, bf);
+		else
+			ret += fprintf(fp, "%11.11s", bf);
+
+		if (show_displacement) {
+			if (displacement)
+				snprintf(bf, sizeof(bf), "%+4ld", displacement);
+			else
+				snprintf(bf, sizeof(bf), " ");
+
+			if (sep)
+				fprintf(fp, "%c%s", *sep, bf);
+			else
+				fprintf(fp, "%6.6s", bf);
+		}
+	}
+
+	list_for_each_entry(se, &hist_entry__sort_list, list) {
+		if (se->elide)
+			continue;
+
+		fprintf(fp, "%s", sep ?: "  ");
+		ret += se->print(fp, self, se->width ? *se->width : 0);
+	}
+
+	ret += fprintf(fp, "\n");
+
+	if (symbol_conf.use_callchain) {
+		int left_margin = 0;
+
+		if (sort__first_dimension == SORT_COMM) {
+			se = list_first_entry(&hist_entry__sort_list, typeof(*se),
+						list);
+			left_margin = se->width ? *se->width : 0;
+			left_margin -= thread__comm_len(self->thread);
+		}
+
+		hist_entry_callchain__fprintf(fp, self, session->events_stats.total,
+					      left_margin);
+	}
+
+	return ret;
+}
+
+size_t perf_session__fprintf_hists(struct perf_session *self,
+				   struct perf_session *pair,
+				   bool show_displacement, FILE *fp)
+{
+	struct sort_entry *se;
+	struct rb_node *nd;
+	size_t ret = 0;
+	unsigned long position = 1;
+	long displacement = 0;
+	unsigned int width;
+	const char *sep = symbol_conf.field_sep;
+	char *col_width = symbol_conf.col_width_list_str;
+
+	init_rem_hits();
+
+	fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
+
+	if (symbol_conf.show_nr_samples) {
+		if (sep)
+			fprintf(fp, "%cSamples", *sep);
+		else
+			fputs("  Samples  ", fp);
+	}
+
+	if (pair) {
+		if (sep)
+			ret += fprintf(fp, "%cDelta", *sep);
+		else
+			ret += fprintf(fp, "  Delta    ");
+
+		if (show_displacement) {
+			if (sep)
+				ret += fprintf(fp, "%cDisplacement", *sep);
+			else
+				ret += fprintf(fp, " Displ");
+		}
+	}
+
+	list_for_each_entry(se, &hist_entry__sort_list, list) {
+		if (se->elide)
+			continue;
+		if (sep) {
+			fprintf(fp, "%c%s", *sep, se->header);
+			continue;
+		}
+		width = strlen(se->header);
+		if (se->width) {
+			if (symbol_conf.col_width_list_str) {
+				if (col_width) {
+					*se->width = atoi(col_width);
+					col_width = strchr(col_width, ',');
+					if (col_width)
+						++col_width;
+				}
+			}
+			width = *se->width = max(*se->width, width);
+		}
+		fprintf(fp, "  %*s", width, se->header);
+	}
+	fprintf(fp, "\n");
+
+	if (sep)
+		goto print_entries;
+
+	fprintf(fp, "# ........");
+	if (symbol_conf.show_nr_samples)
+		fprintf(fp, " ..........");
+	if (pair) {
+		fprintf(fp, " ..........");
+		if (show_displacement)
+			fprintf(fp, " .....");
+	}
+	list_for_each_entry(se, &hist_entry__sort_list, list) {
+		unsigned int i;
+
+		if (se->elide)
+			continue;
+
+		fprintf(fp, "  ");
+		if (se->width)
+			width = *se->width;
+		else
+			width = strlen(se->header);
+		for (i = 0; i < width; i++)
+			fprintf(fp, ".");
+	}
+
+	fprintf(fp, "\n#\n");
+
+print_entries:
+	for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) {
+		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+		if (show_displacement) {
+			if (h->pair != NULL)
+				displacement = ((long)h->pair->position -
+					        (long)position);
+			else
+				displacement = 0;
+			++position;
+		}
+		ret += hist_entry__fprintf(h, self, pair, show_displacement,
+					   displacement, fp);
+	}
+
+	free(rem_sq_bracket);
+
+	return ret;
 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 3020db0..e5f99b2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -1,50 +1,27 @@
 #ifndef __PERF_HIST_H
 #define __PERF_HIST_H
-#include "../builtin.h"
 
-#include "util.h"
-
-#include "color.h"
-#include <linux/list.h>
-#include "cache.h"
-#include <linux/rbtree.h>
-#include "symbol.h"
-#include "string.h"
+#include <linux/types.h>
 #include "callchain.h"
-#include "strlist.h"
-#include "values.h"
 
-#include "../perf.h"
-#include "debug.h"
-#include "header.h"
-
-#include "parse-options.h"
-#include "parse-events.h"
-
-#include "thread.h"
-#include "sort.h"
-
-extern struct rb_root hist;
-extern struct rb_root collapse_hists;
-extern struct rb_root output_hists;
-extern int callchain;
 extern struct callchain_param callchain_param;
-extern unsigned long total;
-extern unsigned long total_mmap;
-extern unsigned long total_comm;
-extern unsigned long total_fork;
-extern unsigned long total_unknown;
-extern unsigned long total_lost;
 
-struct hist_entry *__hist_entry__add(struct addr_location *al,
-				     struct symbol *parent,
-				     u64 count, bool *hit);
+struct perf_session;
+struct hist_entry;
+struct addr_location;
+struct symbol;
+
+struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self,
+						  struct addr_location *al,
+						  struct symbol *parent,
+						  u64 count, bool *hit);
 extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
 extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
-extern void hist_entry__free(struct hist_entry *);
-extern void collapse__insert_entry(struct hist_entry *);
-extern void collapse__resort(void);
-extern void output__insert_entry(struct hist_entry *, u64);
-extern void output__resort(u64);
+void hist_entry__free(struct hist_entry *);
 
+void perf_session__output_resort(struct perf_session *self, u64 total_samples);
+void perf_session__collapse_resort(struct perf_session *self);
+size_t perf_session__fprintf_hists(struct perf_session *self,
+				   struct perf_session *pair,
+				   bool show_displacement, FILE *fp);
 #endif	/* __PERF_HIST_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 76bdca6..c4d55a0 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -104,11 +104,16 @@
 
 #define DSO__DELETED "(deleted)"
 
-static int map__load(struct map *self, symbol_filter_t filter)
+int map__load(struct map *self, struct perf_session *session,
+	      symbol_filter_t filter)
 {
 	const char *name = self->dso->long_name;
-	int nr = dso__load(self->dso, self, filter);
+	int nr;
 
+	if (dso__loaded(self->dso, self->type))
+		return 0;
+
+	nr = dso__load(self->dso, self, session, filter);
 	if (nr < 0) {
 		if (self->dso->has_build_id) {
 			char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -143,19 +148,20 @@
 	return 0;
 }
 
-struct symbol *map__find_symbol(struct map *self, u64 addr,
-				symbol_filter_t filter)
+struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
+				u64 addr, symbol_filter_t filter)
 {
-	if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
+	if (map__load(self, session, filter) < 0)
 		return NULL;
 
 	return dso__find_symbol(self->dso, self->type, addr);
 }
 
 struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
+					struct perf_session *session,
 					symbol_filter_t filter)
 {
-	if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
+	if (map__load(self, session, filter) < 0)
 		return NULL;
 
 	if (!dso__sorted_by_name(self->dso, self->type))
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d14a458..2ca6215 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -69,10 +69,23 @@
 	char c, nc = 0;
 	/*
 	 * <Syntax>
-	 * perf probe SRC:LN
-	 * perf probe FUNC[+OFFS|%return][@SRC]
+	 * perf probe [EVENT=]SRC:LN
+	 * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC]
+	 *
+	 * TODO:Group name support
 	 */
 
+	ptr = strchr(arg, '=');
+	if (ptr) {	/* Event name */
+		*ptr = '\0';
+		tmp = ptr + 1;
+		ptr = strchr(arg, ':');
+		if (ptr)	/* Group name is not supported yet. */
+			semantic_error("Group name is not supported yet.");
+		pp->event = strdup(arg);
+		arg = tmp;
+	}
+
 	ptr = strpbrk(arg, ":+@%");
 	if (ptr) {
 		nc = *ptr;
@@ -150,10 +163,13 @@
 }
 
 /* Parse perf-probe event definition */
-int parse_perf_probe_event(const char *str, struct probe_point *pp)
+void parse_perf_probe_event(const char *str, struct probe_point *pp,
+			    bool *need_dwarf)
 {
 	char **argv;
-	int argc, i, need_dwarf = 0;
+	int argc, i;
+
+	*need_dwarf = false;
 
 	argv = argv_split(str, &argc);
 	if (!argv)
@@ -164,7 +180,7 @@
 	/* Parse probe point */
 	parse_perf_probe_probepoint(argv[0], pp);
 	if (pp->file || pp->line)
-		need_dwarf = 1;
+		*need_dwarf = true;
 
 	/* Copy arguments and ensure return probe has no C argument */
 	pp->nr_args = argc - 1;
@@ -177,17 +193,15 @@
 			if (pp->retprobe)
 				semantic_error("You can't specify local"
 						" variable for kretprobe");
-			need_dwarf = 1;
+			*need_dwarf = true;
 		}
 	}
 
 	argv_free(argv);
-	return need_dwarf;
 }
 
 /* Parse kprobe_events event into struct probe_point */
-void parse_trace_kprobe_event(const char *str, char **group, char **event,
-			      struct probe_point *pp)
+void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
 {
 	char pr;
 	char *p;
@@ -203,18 +217,17 @@
 
 	/* Scan event and group name. */
 	ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
-		     &pr, (float *)(void *)group, (float *)(void *)event);
+		     &pr, (float *)(void *)&pp->group,
+		     (float *)(void *)&pp->event);
 	if (ret != 3)
 		semantic_error("Failed to parse event name: %s", argv[0]);
-	pr_debug("Group:%s Event:%s probe:%c\n", *group, *event, pr);
-
-	if (!pp)
-		goto end;
+	pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
 
 	pp->retprobe = (pr == 'r');
 
 	/* Scan function name and offset */
-	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, &pp->offset);
+	ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
+		     &pp->offset);
 	if (ret == 1)
 		pp->offset = 0;
 
@@ -233,15 +246,15 @@
 			die("Failed to copy argument.");
 	}
 
-end:
 	argv_free(argv);
 }
 
-int synthesize_perf_probe_event(struct probe_point *pp)
+/* Synthesize only probe point (not argument) */
+int synthesize_perf_probe_point(struct probe_point *pp)
 {
 	char *buf;
 	char offs[64] = "", line[64] = "";
-	int i, len, ret;
+	int ret;
 
 	pp->probes[0] = buf = zalloc(MAX_CMDLEN);
 	if (!buf)
@@ -262,10 +275,24 @@
 				 offs, pp->retprobe ? "%return" : "", line);
 	else
 		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line);
-	if (ret <= 0)
-		goto error;
-	len = ret;
+	if (ret <= 0) {
+error:
+		free(pp->probes[0]);
+		pp->probes[0] = NULL;
+	}
+	return ret;
+}
 
+int synthesize_perf_probe_event(struct probe_point *pp)
+{
+	char *buf;
+	int i, len, ret;
+
+	len = synthesize_perf_probe_point(pp);
+	if (len < 0)
+		return 0;
+
+	buf = pp->probes[0];
 	for (i = 0; i < pp->nr_args; i++) {
 		ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
 				 pp->args[i]);
@@ -278,6 +305,7 @@
 	return pp->found;
 error:
 	free(pp->probes[0]);
+	pp->probes[0] = NULL;
 
 	return ret;
 }
@@ -307,6 +335,7 @@
 	return pp->found;
 error:
 	free(pp->probes[0]);
+	pp->probes[0] = NULL;
 
 	return ret;
 }
@@ -366,6 +395,10 @@
 {
 	int i;
 
+	if (pp->event)
+		free(pp->event);
+	if (pp->group)
+		free(pp->group);
 	if (pp->function)
 		free(pp->function);
 	if (pp->file)
@@ -380,13 +413,15 @@
 }
 
 /* Show an event */
-static void show_perf_probe_event(const char *group, const char *event,
-				  const char *place, struct probe_point *pp)
+static void show_perf_probe_event(const char *event, const char *place,
+				  struct probe_point *pp)
 {
-	int i;
+	int i, ret;
 	char buf[128];
 
-	e_snprintf(buf, 128, "%s:%s", group, event);
+	ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
+	if (ret < 0)
+		die("Failed to copy event: %s", strerror(-ret));
 	printf("  %-40s (on %s", buf, place);
 
 	if (pp->nr_args > 0) {
@@ -400,9 +435,7 @@
 /* List up current perf-probe events */
 void show_perf_probe_events(void)
 {
-	unsigned int i;
-	int fd, nr;
-	char *group, *event;
+	int fd;
 	struct probe_point pp;
 	struct strlist *rawlist;
 	struct str_node *ent;
@@ -411,18 +444,12 @@
 	rawlist = get_trace_kprobe_event_rawlist(fd);
 	close(fd);
 
-	for (i = 0; i < strlist__nr_entries(rawlist); i++) {
-		ent = strlist__entry(rawlist, i);
-		parse_trace_kprobe_event(ent->s, &group, &event, &pp);
+	strlist__for_each(ent, rawlist) {
+		parse_trace_kprobe_event(ent->s, &pp);
 		/* Synthesize only event probe point */
-		nr = pp.nr_args;
-		pp.nr_args = 0;
-		synthesize_perf_probe_event(&pp);
-		pp.nr_args = nr;
+		synthesize_perf_probe_point(&pp);
 		/* Show an event */
-		show_perf_probe_event(group, event, pp.probes[0], &pp);
-		free(group);
-		free(event);
+		show_perf_probe_event(pp.event, pp.probes[0], &pp);
 		clear_probe_point(&pp);
 	}
 
@@ -432,26 +459,25 @@
 /* Get current perf-probe event names */
 static struct strlist *get_perf_event_names(int fd, bool include_group)
 {
-	unsigned int i;
-	char *group, *event;
 	char buf[128];
 	struct strlist *sl, *rawlist;
 	struct str_node *ent;
+	struct probe_point pp;
 
+	memset(&pp, 0, sizeof(pp));
 	rawlist = get_trace_kprobe_event_rawlist(fd);
 
 	sl = strlist__new(true, NULL);
-	for (i = 0; i < strlist__nr_entries(rawlist); i++) {
-		ent = strlist__entry(rawlist, i);
-		parse_trace_kprobe_event(ent->s, &group, &event, NULL);
+	strlist__for_each(ent, rawlist) {
+		parse_trace_kprobe_event(ent->s, &pp);
 		if (include_group) {
-			if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
+			if (e_snprintf(buf, 128, "%s:%s", pp.group,
+				       pp.event) < 0)
 				die("Failed to copy group:event name.");
 			strlist__add(sl, buf);
 		} else
-			strlist__add(sl, event);
-		free(group);
-		free(event);
+			strlist__add(sl, pp.event);
+		clear_probe_point(&pp);
 	}
 
 	strlist__delete(rawlist);
@@ -470,7 +496,7 @@
 }
 
 static void get_new_event_name(char *buf, size_t len, const char *base,
-			       struct strlist *namelist)
+			       struct strlist *namelist, bool allow_suffix)
 {
 	int i, ret;
 
@@ -481,6 +507,12 @@
 	if (!strlist__has_entry(namelist, buf))
 		return;
 
+	if (!allow_suffix) {
+		pr_warning("Error: event \"%s\" already exists. "
+			   "(Use -f to force duplicates.)\n", base);
+		die("Can't add new event.");
+	}
+
 	/* Try to add suffix */
 	for (i = 1; i < MAX_EVENT_INDEX; i++) {
 		ret = e_snprintf(buf, len, "%s_%d", base, i);
@@ -493,13 +525,15 @@
 		die("Too many events are on the same function.");
 }
 
-void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
+void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
+			     bool force_add)
 {
 	int i, j, fd;
 	struct probe_point *pp;
 	char buf[MAX_CMDLEN];
 	char event[64];
 	struct strlist *namelist;
+	bool allow_suffix;
 
 	fd = open_kprobe_events(O_RDWR, O_APPEND);
 	/* Get current event names */
@@ -507,21 +541,35 @@
 
 	for (j = 0; j < nr_probes; j++) {
 		pp = probes + j;
+		if (!pp->event)
+			pp->event = strdup(pp->function);
+		if (!pp->group)
+			pp->group = strdup(PERFPROBE_GROUP);
+		DIE_IF(!pp->event || !pp->group);
+		/* If force_add is true, suffix search is allowed */
+		allow_suffix = force_add;
 		for (i = 0; i < pp->found; i++) {
 			/* Get an unused new event name */
-			get_new_event_name(event, 64, pp->function, namelist);
+			get_new_event_name(event, 64, pp->event, namelist,
+					   allow_suffix);
 			snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
 				 pp->retprobe ? 'r' : 'p',
-				 PERFPROBE_GROUP, event,
+				 pp->group, event,
 				 pp->probes[i]);
 			write_trace_kprobe_event(fd, buf);
 			printf("Added new event:\n");
 			/* Get the first parameter (probe-point) */
 			sscanf(pp->probes[i], "%s", buf);
-			show_perf_probe_event(PERFPROBE_GROUP, event,
-					      buf, pp);
+			show_perf_probe_event(event, buf, pp);
 			/* Add added event name to namelist */
 			strlist__add(namelist, event);
+			/*
+			 * Probes after the first probe which comes from same
+			 * user input are always allowed to add suffix, because
+			 * there might be several addresses corresponding to
+			 * one code line.
+			 */
+			allow_suffix = true;
 		}
 	}
 	/* Show how to use the event. */
@@ -532,29 +580,55 @@
 	close(fd);
 }
 
+static void __del_trace_kprobe_event(int fd, struct str_node *ent)
+{
+	char *p;
+	char buf[128];
+
+	/* Convert from perf-probe event to trace-kprobe event */
+	if (e_snprintf(buf, 128, "-:%s", ent->s) < 0)
+		die("Failed to copy event.");
+	p = strchr(buf + 2, ':');
+	if (!p)
+		die("Internal error: %s should have ':' but not.", ent->s);
+	*p = '/';
+
+	write_trace_kprobe_event(fd, buf);
+	printf("Remove event: %s\n", ent->s);
+}
+
 static void del_trace_kprobe_event(int fd, const char *group,
 				   const char *event, struct strlist *namelist)
 {
 	char buf[128];
+	struct str_node *ent, *n;
+	int found = 0;
 
 	if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
 		die("Failed to copy event.");
-	if (!strlist__has_entry(namelist, buf)) {
-		pr_warning("Warning: event \"%s\" is not found.\n", buf);
-		return;
-	}
-	/* Convert from perf-probe event to trace-kprobe event */
-	if (e_snprintf(buf, 128, "-:%s/%s", group, event) < 0)
-		die("Failed to copy event.");
 
-	write_trace_kprobe_event(fd, buf);
-	printf("Remove event: %s:%s\n", group, event);
+	if (strpbrk(buf, "*?")) { /* Glob-exp */
+		strlist__for_each_safe(ent, n, namelist)
+			if (strglobmatch(ent->s, buf)) {
+				found++;
+				__del_trace_kprobe_event(fd, ent);
+				strlist__remove(namelist, ent);
+			}
+	} else {
+		ent = strlist__find(namelist, buf);
+		if (ent) {
+			found++;
+			__del_trace_kprobe_event(fd, ent);
+			strlist__remove(namelist, ent);
+		}
+	}
+	if (found == 0)
+		pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf);
 }
 
 void del_trace_kprobe_events(struct strlist *dellist)
 {
 	int fd;
-	unsigned int i;
 	const char *group, *event;
 	char *p, *str;
 	struct str_node *ent;
@@ -564,20 +638,21 @@
 	/* Get current event names */
 	namelist = get_perf_event_names(fd, true);
 
-	for (i = 0; i < strlist__nr_entries(dellist); i++) {
-		ent = strlist__entry(dellist, i);
+	strlist__for_each(ent, dellist) {
 		str = strdup(ent->s);
 		if (!str)
 			die("Failed to copy event.");
+		pr_debug("Parsing: %s\n", str);
 		p = strchr(str, ':');
 		if (p) {
 			group = str;
 			*p = '\0';
 			event = p + 1;
 		} else {
-			group = PERFPROBE_GROUP;
+			group = "*";
 			event = str;
 		}
+		pr_debug("Group: %s, Event: %s\n", group, event);
 		del_trace_kprobe_event(fd, group, event, namelist);
 		free(str);
 	}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f752159..7f1d499 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -1,15 +1,18 @@
 #ifndef _PROBE_EVENT_H
 #define _PROBE_EVENT_H
 
+#include <stdbool.h>
 #include "probe-finder.h"
 #include "strlist.h"
 
-extern int parse_perf_probe_event(const char *str, struct probe_point *pp);
+extern void parse_perf_probe_event(const char *str, struct probe_point *pp,
+				   bool *need_dwarf);
+extern int synthesize_perf_probe_point(struct probe_point *pp);
 extern int synthesize_perf_probe_event(struct probe_point *pp);
-extern void parse_trace_kprobe_event(const char *str, char **group,
-				     char **event, struct probe_point *pp);
+extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp);
 extern int synthesize_trace_kprobe_event(struct probe_point *pp);
-extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes);
+extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes,
+				    bool force_add);
 extern void del_trace_kprobe_events(struct strlist *dellist);
 extern void show_perf_probe_events(void);
 
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 4585f1d..4b852c0 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -687,10 +687,8 @@
 	struct probe_finder pf = {.pp = pp};
 
 	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
-	if (ret != DW_DLV_OK) {
-		pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO.\n");
+	if (ret != DW_DLV_OK)
 		return -ENOENT;
-	}
 
 	pp->found = 0;
 	while (++cu_number) {
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index bdebca6..5e4050c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -12,6 +12,9 @@
 }
 
 struct probe_point {
+	char	*event;		/* Event name */
+	char	*group;		/* Event group */
+
 	/* Inputs */
 	char	*file;		/* File name */
 	int	line;		/* Line number */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 707ce1c..ce3a6c8 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 
 #include "session.h"
+#include "sort.h"
 #include "util.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
@@ -50,31 +51,100 @@
 
 struct perf_session *perf_session__new(const char *filename, int mode, bool force)
 {
-	size_t len = strlen(filename) + 1;
+	size_t len = filename ? strlen(filename) + 1 : 0;
 	struct perf_session *self = zalloc(sizeof(*self) + len);
 
 	if (self == NULL)
 		goto out;
 
 	if (perf_header__init(&self->header) < 0)
-		goto out_delete;
+		goto out_free;
 
 	memcpy(self->filename, filename, len);
+	self->threads = RB_ROOT;
+	self->last_match = NULL;
+	self->mmap_window = 32;
+	self->cwd = NULL;
+	self->cwdlen = 0;
+	map_groups__init(&self->kmaps);
 
-	if (mode == O_RDONLY && perf_session__open(self, force) < 0) {
-		perf_session__delete(self);
-		self = NULL;
-	}
+	if (perf_session__create_kernel_maps(self) < 0)
+		goto out_delete;
+
+	if (mode == O_RDONLY && perf_session__open(self, force) < 0)
+		goto out_delete;
 out:
 	return self;
-out_delete:
+out_free:
 	free(self);
 	return NULL;
+out_delete:
+	perf_session__delete(self);
+	return NULL;
 }
 
 void perf_session__delete(struct perf_session *self)
 {
 	perf_header__exit(&self->header);
 	close(self->fd);
+	free(self->cwd);
 	free(self);
 }
+
+static bool symbol__match_parent_regex(struct symbol *sym)
+{
+	if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
+		return 1;
+
+	return 0;
+}
+
+struct symbol **perf_session__resolve_callchain(struct perf_session *self,
+						struct thread *thread,
+						struct ip_callchain *chain,
+						struct symbol **parent)
+{
+	u8 cpumode = PERF_RECORD_MISC_USER;
+	struct symbol **syms = NULL;
+	unsigned int i;
+
+	if (symbol_conf.use_callchain) {
+		syms = calloc(chain->nr, sizeof(*syms));
+		if (!syms) {
+			fprintf(stderr, "Can't allocate memory for symbols\n");
+			exit(-1);
+		}
+	}
+
+	for (i = 0; i < chain->nr; i++) {
+		u64 ip = chain->ips[i];
+		struct addr_location al;
+
+		if (ip >= PERF_CONTEXT_MAX) {
+			switch (ip) {
+			case PERF_CONTEXT_HV:
+				cpumode = PERF_RECORD_MISC_HYPERVISOR;	break;
+			case PERF_CONTEXT_KERNEL:
+				cpumode = PERF_RECORD_MISC_KERNEL;	break;
+			case PERF_CONTEXT_USER:
+				cpumode = PERF_RECORD_MISC_USER;	break;
+			default:
+				break;
+			}
+			continue;
+		}
+
+		thread__find_addr_location(thread, self, cpumode,
+					   MAP__FUNCTION, ip, &al, NULL);
+		if (al.sym != NULL) {
+			if (sort__has_parent && !*parent &&
+			    symbol__match_parent_regex(al.sym))
+				*parent = al.sym;
+			if (!symbol_conf.use_callchain)
+				break;
+			syms[i] = al.sym;
+		}
+	}
+
+	return syms;
+}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index f3699c8..32eaa1b 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -1,16 +1,61 @@
 #ifndef __PERF_SESSION_H
 #define __PERF_SESSION_H
 
+#include "event.h"
 #include "header.h"
+#include "thread.h"
+#include <linux/rbtree.h>
+#include "../../../include/linux/perf_event.h"
+
+struct ip_callchain;
+struct thread;
+struct symbol;
 
 struct perf_session {
 	struct perf_header	header;
 	unsigned long		size;
+	unsigned long		mmap_window;
+	struct map_groups	kmaps;
+	struct rb_root		threads;
+	struct thread		*last_match;
+	struct events_stats	events_stats;
+	unsigned long		event_total[PERF_RECORD_MAX];
+	struct rb_root		hists;
+	u64			sample_type;
 	int			fd;
+	int			cwdlen;
+	char			*cwd;
 	char filename[0];
 };
 
+typedef int (*event_op)(event_t *self, struct perf_session *session);
+
+struct perf_event_ops {
+	event_op	process_sample_event;
+	event_op	process_mmap_event;
+	event_op	process_comm_event;
+	event_op	process_fork_event;
+	event_op	process_exit_event;
+	event_op	process_lost_event;
+	event_op	process_read_event;
+	event_op	process_throttle_event;
+	event_op	process_unthrottle_event;
+	int		(*sample_type_check)(struct perf_session *session);
+	unsigned long	total_unknown;
+	bool		full_paths;
+};
+
 struct perf_session *perf_session__new(const char *filename, int mode, bool force);
 void perf_session__delete(struct perf_session *self);
 
+int perf_session__process_events(struct perf_session *self,
+				 struct perf_event_ops *event_ops);
+
+struct symbol **perf_session__resolve_callchain(struct perf_session *self,
+						struct thread *thread,
+						struct ip_callchain *chain,
+						struct symbol **parent);
+
+int perf_header__read_build_ids(int input, u64 offset, u64 file_size);
+
 #endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b490354..cb0f327 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -288,3 +288,29 @@
 
 	return -ESRCH;
 }
+
+void setup_sorting(const char * const usagestr[], const struct option *opts)
+{
+	char *tmp, *tok, *str = strdup(sort_order);
+
+	for (tok = strtok_r(str, ", ", &tmp);
+			tok; tok = strtok_r(NULL, ", ", &tmp)) {
+		if (sort_dimension__add(tok) < 0) {
+			error("Unknown --sort key: `%s'", tok);
+			usage_with_options(usagestr, opts);
+		}
+	}
+
+	free(str);
+}
+
+void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
+			     const char *list_name, FILE *fp)
+{
+	if (list && strlist__nr_entries(list) == 1) {
+		if (fp != NULL)
+			fprintf(fp, "# %s: %s\n", list_name,
+				strlist__entry(list, 0)->s);
+		self->elide = true;
+	}
+}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 333e664..753f9ea 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -49,9 +49,13 @@
 	struct symbol		*sym;
 	u64			ip;
 	char			level;
-	struct symbol		*parent;
+	struct symbol	  *parent;
 	struct callchain_node	callchain;
-	struct rb_root		sorted_chain;
+	union {
+		unsigned long	  position;
+		struct hist_entry *pair;
+		struct rb_root	  sorted_chain;
+	};
 };
 
 enum sort_type {
@@ -81,6 +85,8 @@
 extern struct sort_entry sort_thread;
 extern struct list_head hist_entry__sort_list;
 
+void setup_sorting(const char * const usagestr[], const struct option *opts);
+
 extern int repsep_fprintf(FILE *fp, const char *fmt, ...);
 extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
 extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
@@ -95,5 +101,7 @@
 extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
 extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
 extern int sort_dimension__add(const char *);
+void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
+			     const char *list_name, FILE *fp);
 
 #endif	/* __PERF_SORT_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index f24a8cc..5352d7d 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -226,3 +226,28 @@
 	argv_free(argv);
 	return NULL;
 }
+
+/* Glob expression pattern matching */
+bool strglobmatch(const char *str, const char *pat)
+{
+	while (*str && *pat && *pat != '*') {
+		if (*pat == '?') {
+			str++;
+			pat++;
+		} else
+			if (*str++ != *pat++)
+				return false;
+	}
+	/* Check wild card */
+	if (*pat == '*') {
+		while (*pat == '*')
+			pat++;
+		if (!*pat)	/* Tail wild card matches all */
+			return true;
+		while (*str)
+			if (strglobmatch(str++, pat))
+				return true;
+	}
+	return !*str && !*pat;
+}
+
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index bfecec2..02ede58 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,6 +1,7 @@
 #ifndef __PERF_STRING_H_
 #define __PERF_STRING_H_
 
+#include <stdbool.h>
 #include "types.h"
 
 int hex2u64(const char *ptr, u64 *val);
@@ -8,6 +9,7 @@
 s64 perf_atoll(const char *str);
 char **argv_split(const char *str, int *argcp);
 void argv_free(char **argv);
+bool strglobmatch(const char *str, const char *pat);
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 7ad3817..6783a20 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -102,7 +102,7 @@
 	str_node__delete(sn, self->dupstr);
 }
 
-bool strlist__has_entry(struct strlist *self, const char *entry)
+struct str_node *strlist__find(struct strlist *self, const char *entry)
 {
 	struct rb_node **p = &self->entries.rb_node;
 	struct rb_node *parent = NULL;
@@ -120,10 +120,10 @@
 		else if (rc < 0)
 			p = &(*p)->rb_right;
 		else
-			return true;
+			return sn;
 	}
 
-	return false;
+	return NULL;
 }
 
 static int strlist__parse_list_entry(struct strlist *self, const char *s)
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index cb46593..3ba8390 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -23,7 +23,12 @@
 int strlist__add(struct strlist *self, const char *str);
 
 struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
-bool strlist__has_entry(struct strlist *self, const char *entry);
+struct str_node *strlist__find(struct strlist *self, const char *entry);
+
+static inline bool strlist__has_entry(struct strlist *self, const char *entry)
+{
+	return strlist__find(self, entry) != NULL;
+}
 
 static inline bool strlist__empty(const struct strlist *self)
 {
@@ -35,5 +40,39 @@
 	return self->nr_entries;
 }
 
+/* For strlist iteration */
+static inline struct str_node *strlist__first(struct strlist *self)
+{
+	struct rb_node *rn = rb_first(&self->entries);
+	return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
+}
+static inline struct str_node *strlist__next(struct str_node *sn)
+{
+	struct rb_node *rn;
+	if (!sn)
+		return NULL;
+	rn = rb_next(&sn->rb_node);
+	return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
+}
+
+/**
+ * strlist_for_each      - iterate over a strlist
+ * @pos:	the &struct str_node to use as a loop cursor.
+ * @self:	the &struct strlist for loop.
+ */
+#define strlist__for_each(pos, self)	\
+	for (pos = strlist__first(self); pos; pos = strlist__next(pos))
+
+/**
+ * strlist_for_each_safe - iterate over a strlist safe against removal of
+ *                         str_node
+ * @pos:	the &struct str_node to use as a loop cursor.
+ * @n:		another &struct str_node to use as temporary storage.
+ * @self:	the &struct strlist for loop.
+ */
+#define strlist__for_each_safe(pos, n, self)	\
+	for (pos = strlist__first(self), n = strlist__next(pos); pos;\
+	     pos = n, n = strlist__next(n))
+
 int strlist__parse_list(struct strlist *self, const char *s);
 #endif /* __PERF_STRLIST_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d3d9fed..ab92763 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,5 +1,7 @@
 #include "util.h"
 #include "../perf.h"
+#include "session.h"
+#include "sort.h"
 #include "string.h"
 #include "symbol.h"
 #include "thread.h"
@@ -31,19 +33,16 @@
 static void dsos__add(struct list_head *head, struct dso *dso);
 static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
 static int dso__load_kernel_sym(struct dso *self, struct map *map,
-				struct map_groups *mg, symbol_filter_t filter);
-unsigned int symbol__priv_size;
+				struct perf_session *session, symbol_filter_t filter);
 static int vmlinux_path__nr_entries;
 static char **vmlinux_path;
 
-static struct symbol_conf symbol_conf__defaults = {
+struct symbol_conf symbol_conf = {
+	.exclude_other	  = true,
 	.use_modules	  = true,
 	.try_vmlinux_path = true,
 };
 
-static struct map_groups kmaps_mem;
-struct map_groups *kmaps = &kmaps_mem;
-
 bool dso__loaded(const struct dso *self, enum map_type type)
 {
 	return self->loaded & (1 << type);
@@ -132,13 +131,13 @@
 static struct symbol *symbol__new(u64 start, u64 len, const char *name)
 {
 	size_t namelen = strlen(name) + 1;
-	struct symbol *self = zalloc(symbol__priv_size +
+	struct symbol *self = zalloc(symbol_conf.priv_size +
 				     sizeof(*self) + namelen);
 	if (self == NULL)
 		return NULL;
 
-	if (symbol__priv_size)
-		self = ((void *)self) + symbol__priv_size;
+	if (symbol_conf.priv_size)
+		self = ((void *)self) + symbol_conf.priv_size;
 
 	self->start = start;
 	self->end   = len ? start + len - 1 : start;
@@ -152,7 +151,7 @@
 
 static void symbol__delete(struct symbol *self)
 {
-	free(((void *)self) - symbol__priv_size);
+	free(((void *)self) - symbol_conf.priv_size);
 }
 
 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
@@ -456,7 +455,7 @@
  * the original ELF section names vmlinux have.
  */
 static int dso__split_kallsyms(struct dso *self, struct map *map,
-			       struct map_groups *mg, symbol_filter_t filter)
+			       struct perf_session *session, symbol_filter_t filter)
 {
 	struct map *curr_map = map;
 	struct symbol *pos;
@@ -473,13 +472,13 @@
 
 		module = strchr(pos->name, '\t');
 		if (module) {
-			if (!mg->use_modules)
+			if (!symbol_conf.use_modules)
 				goto discard_symbol;
 
 			*module++ = '\0';
 
 			if (strcmp(self->name, module)) {
-				curr_map = map_groups__find_by_name(mg, map->type, module);
+				curr_map = map_groups__find_by_name(&session->kmaps, map->type, module);
 				if (curr_map == NULL) {
 					pr_debug("/proc/{kallsyms,modules} "
 					         "inconsistency!\n");
@@ -510,7 +509,7 @@
 			}
 
 			curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
-			map_groups__insert(mg, curr_map);
+			map_groups__insert(&session->kmaps, curr_map);
 			++kernel_range;
 		}
 
@@ -531,7 +530,7 @@
 
 
 static int dso__load_kallsyms(struct dso *self, struct map *map,
-			      struct map_groups *mg, symbol_filter_t filter)
+			      struct perf_session *session, symbol_filter_t filter)
 {
 	if (dso__load_all_kallsyms(self, map) < 0)
 		return -1;
@@ -539,14 +538,7 @@
 	symbols__fixup_end(&self->symbols[map->type]);
 	self->origin = DSO__ORIG_KERNEL;
 
-	return dso__split_kallsyms(self, map, mg, filter);
-}
-
-size_t kernel_maps__fprintf(FILE *fp)
-{
-	size_t printed = fprintf(fp, "Kernel maps:\n");
-	printed += map_groups__fprintf_maps(kmaps, fp);
-	return printed + fprintf(fp, "END kernel maps\n");
+	return dso__split_kallsyms(self, map, session, filter);
 }
 
 static int dso__load_perf_map(struct dso *self, struct map *map,
@@ -873,7 +865,7 @@
 }
 
 static int dso__load_sym(struct dso *self, struct map *map,
-			 struct map_groups *mg, const char *name, int fd,
+			 struct perf_session *session, const char *name, int fd,
 			 symbol_filter_t filter, int kernel, int kmodule)
 {
 	struct map *curr_map = map;
@@ -977,7 +969,7 @@
 			snprintf(dso_name, sizeof(dso_name),
 				 "%s%s", self->short_name, section_name);
 
-			curr_map = map_groups__find_by_name(mg, map->type, dso_name);
+			curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name);
 			if (curr_map == NULL) {
 				u64 start = sym.st_value;
 
@@ -996,7 +988,7 @@
 				curr_map->map_ip = identity__map_ip;
 				curr_map->unmap_ip = identity__map_ip;
 				curr_dso->origin = DSO__ORIG_KERNEL;
-				map_groups__insert(kmaps, curr_map);
+				map_groups__insert(&session->kmaps, curr_map);
 				dsos__add(&dsos__kernel, curr_dso);
 			} else
 				curr_dso = curr_map->dso;
@@ -1211,7 +1203,8 @@
 	return origin[self->origin];
 }
 
-int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
+int dso__load(struct dso *self, struct map *map, struct perf_session *session,
+	      symbol_filter_t filter)
 {
 	int size = PATH_MAX;
 	char *name;
@@ -1222,7 +1215,7 @@
 	dso__set_loaded(self, map->type);
 
 	if (self->kernel)
-		return dso__load_kernel_sym(self, map, kmaps, filter);
+		return dso__load_kernel_sym(self, map, session, filter);
 
 	name = malloc(size);
 	if (!name)
@@ -1323,7 +1316,7 @@
 	return NULL;
 }
 
-static int dsos__set_modules_path_dir(char *dirname)
+static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname)
 {
 	struct dirent *dent;
 	DIR *dir = opendir(dirname);
@@ -1343,7 +1336,7 @@
 
 			snprintf(path, sizeof(path), "%s/%s",
 				 dirname, dent->d_name);
-			if (dsos__set_modules_path_dir(path) < 0)
+			if (perf_session__set_modules_path_dir(self, path) < 0)
 				goto failure;
 		} else {
 			char *dot = strrchr(dent->d_name, '.'),
@@ -1357,7 +1350,7 @@
 				 (int)(dot - dent->d_name), dent->d_name);
 
 			strxfrchar(dso_name, '-', '_');
-			map = map_groups__find_by_name(kmaps, MAP__FUNCTION, dso_name);
+			map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name);
 			if (map == NULL)
 				continue;
 
@@ -1377,7 +1370,7 @@
 	return -1;
 }
 
-static int dsos__set_modules_path(void)
+static int perf_session__set_modules_path(struct perf_session *self)
 {
 	struct utsname uts;
 	char modules_path[PATH_MAX];
@@ -1388,7 +1381,7 @@
 	snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
 		 uts.release);
 
-	return dsos__set_modules_path_dir(modules_path);
+	return perf_session__set_modules_path_dir(self, modules_path);
 }
 
 /*
@@ -1410,7 +1403,7 @@
 	return self;
 }
 
-static int map_groups__create_module_maps(struct map_groups *self)
+static int perf_session__create_module_maps(struct perf_session *self)
 {
 	char *line = NULL;
 	size_t n;
@@ -1467,14 +1460,14 @@
 			dso->has_build_id = true;
 
 		dso->origin = DSO__ORIG_KMODULE;
-		map_groups__insert(self, map);
+		map_groups__insert(&self->kmaps, map);
 		dsos__add(&dsos__kernel, dso);
 	}
 
 	free(line);
 	fclose(file);
 
-	return dsos__set_modules_path();
+	return perf_session__set_modules_path(self);
 
 out_delete_line:
 	free(line);
@@ -1483,7 +1476,7 @@
 }
 
 static int dso__load_vmlinux(struct dso *self, struct map *map,
-			     struct map_groups *mg,
+			     struct perf_session *session,
 			     const char *vmlinux, symbol_filter_t filter)
 {
 	int err = -1, fd;
@@ -1517,14 +1510,14 @@
 		return -1;
 
 	dso__set_loaded(self, map->type);
-	err = dso__load_sym(self, map, mg, self->long_name, fd, filter, 1, 0);
+	err = dso__load_sym(self, map, session, self->long_name, fd, filter, 1, 0);
 	close(fd);
 
 	return err;
 }
 
 static int dso__load_kernel_sym(struct dso *self, struct map *map,
-				struct map_groups *mg, symbol_filter_t filter)
+				struct perf_session *session, symbol_filter_t filter)
 {
 	int err;
 	bool is_kallsyms;
@@ -1534,7 +1527,7 @@
 		pr_debug("Looking at the vmlinux_path (%d entries long)\n",
 			 vmlinux_path__nr_entries);
 		for (i = 0; i < vmlinux_path__nr_entries; ++i) {
-			err = dso__load_vmlinux(self, map, mg,
+			err = dso__load_vmlinux(self, map, session,
 						vmlinux_path[i], filter);
 			if (err > 0) {
 				pr_debug("Using %s for symbols\n",
@@ -1550,12 +1543,12 @@
 	if (is_kallsyms)
 		goto do_kallsyms;
 
-	err = dso__load_vmlinux(self, map, mg, self->long_name, filter);
+	err = dso__load_vmlinux(self, map, session, self->long_name, filter);
 	if (err <= 0) {
 		pr_info("The file %s cannot be used, "
 			"trying to use /proc/kallsyms...", self->long_name);
 do_kallsyms:
-		err = dso__load_kallsyms(self, map, mg, filter);
+		err = dso__load_kallsyms(self, map, session, filter);
 		if (err > 0 && !is_kallsyms)
                         dso__set_long_name(self, strdup("[kernel.kallsyms]"));
 	}
@@ -1748,32 +1741,69 @@
 	return -1;
 }
 
-int symbol__init(struct symbol_conf *conf)
+static int setup_list(struct strlist **list, const char *list_str,
+		      const char *list_name)
 {
-	const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults;
+	if (list_str == NULL)
+		return 0;
 
+	*list = strlist__new(true, list_str);
+	if (!*list) {
+		pr_err("problems parsing %s list\n", list_name);
+		return -1;
+	}
+	return 0;
+}
+
+int symbol__init(void)
+{
 	elf_version(EV_CURRENT);
-	symbol__priv_size = pconf->priv_size;
-	if (pconf->sort_by_name)
-		symbol__priv_size += (sizeof(struct symbol_name_rb_node) -
-				      sizeof(struct symbol));
-	map_groups__init(kmaps);
+	if (symbol_conf.sort_by_name)
+		symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
+					  sizeof(struct symbol));
 
-	if (pconf->try_vmlinux_path && vmlinux_path__init() < 0)
+	if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0)
 		return -1;
 
-	if (map_groups__create_kernel_maps(kmaps, pconf->vmlinux_name) < 0) {
-		vmlinux_path__exit();
+	if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
+		pr_err("'.' is the only non valid --field-separator argument\n");
 		return -1;
 	}
 
-	kmaps->use_modules = pconf->use_modules;
-	if (pconf->use_modules && map_groups__create_module_maps(kmaps) < 0)
-		pr_debug("Failed to load list of modules in use, "
-			 "continuing...\n");
+	if (setup_list(&symbol_conf.dso_list,
+		       symbol_conf.dso_list_str, "dso") < 0)
+		return -1;
+
+	if (setup_list(&symbol_conf.comm_list,
+		       symbol_conf.comm_list_str, "comm") < 0)
+		goto out_free_dso_list;
+
+	if (setup_list(&symbol_conf.sym_list,
+		       symbol_conf.sym_list_str, "symbol") < 0)
+		goto out_free_comm_list;
+
+	return 0;
+
+out_free_dso_list:
+	strlist__delete(symbol_conf.dso_list);
+out_free_comm_list:
+	strlist__delete(symbol_conf.comm_list);
+	return -1;
+}
+
+int perf_session__create_kernel_maps(struct perf_session *self)
+{
+	if (map_groups__create_kernel_maps(&self->kmaps,
+					   symbol_conf.vmlinux_name) < 0)
+		return -1;
+
+	if (symbol_conf.use_modules &&
+	    perf_session__create_module_maps(self) < 0)
+		pr_debug("Failed to load list of modules for session %s, "
+			 "continuing...\n", self->filename);
 	/*
 	 * Now that we have all the maps created, just set the ->end of them:
 	 */
-	map_groups__fixup_end(kmaps);
+	map_groups__fixup_end(&self->kmaps);
 	return 0;
 }
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index cf99f88..8aded23 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -49,19 +49,32 @@
 	char		name[0];
 };
 
+struct strlist;
+
 struct symbol_conf {
 	unsigned short	priv_size;
 	bool		try_vmlinux_path,
 			use_modules,
-			sort_by_name;
-	const char	*vmlinux_name;
+			sort_by_name,
+			show_nr_samples,
+			use_callchain,
+			exclude_other;
+	const char	*vmlinux_name,
+			*field_sep;
+	char            *dso_list_str,
+			*comm_list_str,
+			*sym_list_str,
+			*col_width_list_str;
+       struct strlist	*dso_list,
+			*comm_list,
+			*sym_list;
 };
 
-extern unsigned int symbol__priv_size;
+extern struct symbol_conf symbol_conf;
 
 static inline void *symbol__priv(struct symbol *self)
 {
-	return ((void *)self) - symbol__priv_size;
+	return ((void *)self) - symbol_conf.priv_size;
 }
 
 struct addr_location {
@@ -70,6 +83,7 @@
 	struct symbol *sym;
 	u64	      addr;
 	char	      level;
+	bool	      filtered;
 };
 
 struct dso {
@@ -98,8 +112,11 @@
 
 void dso__sort_by_name(struct dso *self, enum map_type type);
 
+struct perf_session;
+
 struct dso *dsos__findnew(const char *name);
-int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
+int dso__load(struct dso *self, struct map *map, struct perf_session *session,
+	      symbol_filter_t filter);
 void dsos__fprintf(FILE *fp);
 size_t dsos__fprintf_buildid(FILE *fp);
 
@@ -116,12 +133,9 @@
 bool dsos__read_build_ids(void);
 int build_id__sprintf(u8 *self, int len, char *bf);
 
-size_t kernel_maps__fprintf(FILE *fp);
+int symbol__init(void);
+int perf_session__create_kernel_maps(struct perf_session *self);
 
-int symbol__init(struct symbol_conf *conf);
-
-struct map_groups;
-struct map_groups *kmaps;
 extern struct list_head dsos__user, dsos__kernel;
 extern struct dso *vdso;
 #endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index b68a00e..4a08dcf 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -2,13 +2,11 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include "session.h"
 #include "thread.h"
 #include "util.h"
 #include "debug.h"
 
-static struct rb_root threads;
-static struct thread *last_match;
-
 void map_groups__init(struct map_groups *self)
 {
 	int i;
@@ -122,9 +120,9 @@
 	       map_groups__fprintf(&self->mg, fp);
 }
 
-struct thread *threads__findnew(pid_t pid)
+struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
 {
-	struct rb_node **p = &threads.rb_node;
+	struct rb_node **p = &self->threads.rb_node;
 	struct rb_node *parent = NULL;
 	struct thread *th;
 
@@ -133,15 +131,15 @@
 	 * so most of the time we dont have to look up
 	 * the full rbtree:
 	 */
-	if (last_match && last_match->pid == pid)
-		return last_match;
+	if (self->last_match && self->last_match->pid == pid)
+		return self->last_match;
 
 	while (*p != NULL) {
 		parent = *p;
 		th = rb_entry(parent, struct thread, rb_node);
 
 		if (th->pid == pid) {
-			last_match = th;
+			self->last_match = th;
 			return th;
 		}
 
@@ -154,25 +152,13 @@
 	th = thread__new(pid);
 	if (th != NULL) {
 		rb_link_node(&th->rb_node, parent, p);
-		rb_insert_color(&th->rb_node, &threads);
-		last_match = th;
+		rb_insert_color(&th->rb_node, &self->threads);
+		self->last_match = th;
 	}
 
 	return th;
 }
 
-struct thread *register_idle_thread(void)
-{
-	struct thread *thread = threads__findnew(0);
-
-	if (!thread || thread__set_comm(thread, "swapper")) {
-		fprintf(stderr, "problem inserting idle task.\n");
-		exit(-1);
-	}
-
-	return thread;
-}
-
 static void map_groups__remove_overlappings(struct map_groups *self,
 					    struct map *map)
 {
@@ -281,12 +267,12 @@
 	return 0;
 }
 
-size_t threads__fprintf(FILE *fp)
+size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
 {
 	size_t ret = 0;
 	struct rb_node *nd;
 
-	for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
+	for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) {
 		struct thread *pos = rb_entry(nd, struct thread, rb_node);
 
 		ret += thread__fprintf(pos, fp);
@@ -296,13 +282,14 @@
 }
 
 struct symbol *map_groups__find_symbol(struct map_groups *self,
+				       struct perf_session *session,
 				       enum map_type type, u64 addr,
 				       symbol_filter_t filter)
 {
 	struct map *map = map_groups__find(self, type, addr);
 
 	if (map != NULL)
-		return map__find_symbol(map, map->map_ip(map, addr), filter);
+		return map__find_symbol(map, session, map->map_ip(map, addr), filter);
 
 	return NULL;
 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 1751802..c206f72 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -8,7 +8,6 @@
 struct map_groups {
 	struct rb_root		maps[MAP__NR_TYPES];
 	struct list_head	removed_maps[MAP__NR_TYPES];
-	bool			use_modules;
 };
 
 struct thread {
@@ -23,12 +22,11 @@
 void map_groups__init(struct map_groups *self);
 int thread__set_comm(struct thread *self, const char *comm);
 int thread__comm_len(struct thread *self);
-struct thread *threads__findnew(pid_t pid);
-struct thread *register_idle_thread(void);
+struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
 void thread__insert_map(struct thread *self, struct map *map);
 int thread__fork(struct thread *self, struct thread *parent);
 size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp);
-size_t threads__fprintf(FILE *fp);
+size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
 
 void maps__insert(struct rb_root *maps, struct map *map);
 struct map *maps__find(struct rb_root *maps, u64 addr);
@@ -50,19 +48,21 @@
 	return self ? map_groups__find(&self->mg, type, addr) : NULL;
 }
 
-void thread__find_addr_location(struct thread *self, u8 cpumode,
+void thread__find_addr_location(struct thread *self,
+				struct perf_session *session, u8 cpumode,
 				enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter);
 struct symbol *map_groups__find_symbol(struct map_groups *self,
+				       struct perf_session *session,
 				       enum map_type type, u64 addr,
 				       symbol_filter_t filter);
 
 static inline struct symbol *
-map_groups__find_function(struct map_groups *self, u64 addr,
-			  symbol_filter_t filter)
+map_groups__find_function(struct map_groups *self, struct perf_session *session,
+			  u64 addr, symbol_filter_t filter)
 {
-	return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter);
+	return map_groups__find_symbol(self, session, MAP__FUNCTION, addr, filter);
 }
 
 struct map *map_groups__find_by_name(struct map_groups *self,
diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c
index a5ffe60..6d6d76b 100644
--- a/tools/perf/util/trace-event-perl.c
+++ b/tools/perf/util/trace-event-perl.c
@@ -267,7 +267,7 @@
 }
 
 static void perl_process_event(int cpu, void *data,
-			       int size __attribute((unused)),
+			       int size __unused,
 			       unsigned long long nsecs, char *comm)
 {
 	struct format_field *field;
@@ -359,28 +359,46 @@
 /*
  * Start trace script
  */
-static int perl_start_script(const char *script)
+static int perl_start_script(const char *script, int argc, const char **argv)
 {
-	const char *command_line[2] = { "", NULL };
+	const char **command_line;
+	int i, err = 0;
 
+	command_line = malloc((argc + 2) * sizeof(const char *));
+	command_line[0] = "";
 	command_line[1] = script;
+	for (i = 2; i < argc + 2; i++)
+		command_line[i] = argv[i - 2];
 
 	my_perl = perl_alloc();
 	perl_construct(my_perl);
 
-	if (perl_parse(my_perl, xs_init, 2, (char **)command_line,
-		       (char **)NULL))
-		return -1;
+	if (perl_parse(my_perl, xs_init, argc + 2, (char **)command_line,
+		       (char **)NULL)) {
+		err = -1;
+		goto error;
+	}
 
-	perl_run(my_perl);
-	if (SvTRUE(ERRSV))
-		return -1;
+	if (perl_run(my_perl)) {
+		err = -1;
+		goto error;
+	}
+
+	if (SvTRUE(ERRSV)) {
+		err = -1;
+		goto error;
+	}
 
 	run_start_sub();
 
+	free(command_line);
 	fprintf(stderr, "perf trace started with Perl script %s\n\n", script);
-
 	return 0;
+error:
+	perl_free(my_perl);
+	free(command_line);
+
+	return err;
 }
 
 /*
@@ -579,7 +597,9 @@
 		"\n  etc.\n");
 }
 
-static int perl_start_script_unsupported(const char *script __unused)
+static int perl_start_script_unsupported(const char *script __unused,
+					 int argc __unused,
+					 const char **argv __unused)
 {
 	print_unsupported_msg();
 
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 81698d5..6ad4056 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -270,7 +270,7 @@
 
 struct scripting_ops {
 	const char *name;
-	int (*start_script) (const char *);
+	int (*start_script) (const char *script, int argc, const char **argv);
 	int (*stop_script) (void);
 	void (*process_event) (int cpu, void *data, int size,
 			       unsigned long long nsecs, char *comm);
diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c
index 83b3dde..b2b3c2d 100644
--- a/usr/gen_init_cpio.c
+++ b/usr/gen_init_cpio.c
@@ -354,7 +354,10 @@
 		push_pad();
 
 		if (size) {
-			fwrite(filebuf, size, 1, stdout);
+			if (fwrite(filebuf, size, 1, stdout) != 1) {
+				fprintf(stderr, "writing filebuf failed\n");
+				goto error;
+			}
 			offset += size;
 			push_pad();
 		}